video stabilization using opencv - c++

I am trying to do video stabilization with opencv(without the opencv video stabilization class).
the steps for my algo is as follows->
Surf points extraction,
Matching,
Homography matrix,
warpPerspective
And the output video is not stabilized at all :(. it just looks like the original video. I could not find and reference code for video stabilization. I followed the procedure described here . Can anybody help me out by telling me where I am going wrong or provide me some source code link to improve my algo.
Please help. Thank you

You can use my code snippet as a start point (not very stable but seems it works):
#include "opencv2/opencv.hpp"
#include <iostream>
#include <vector>
#include <stdio.h>
using namespace cv;
using namespace std;
int main(int ac, char** av)
{
VideoCapture capture(0);
namedWindow("Cam");
namedWindow("Camw");
Mat frame;
Mat frame_edg;
Mat prev_frame;
int k=0;
Mat Transform;
Mat Transform_avg=Mat::eye(2,3,CV_64FC1);
Mat warped;
while(k!=27)
{
capture >> frame;
cv::cvtColor(frame,frame,cv::COLOR_BGR2GRAY);
cv::equalizeHist(frame,frame);
cv::Canny(frame,frame_edg,64,64);
//frame=frame_edg.clone();
imshow("Cam_e",frame_edg);
imshow("Cam",frame);
if(!prev_frame.empty())
{
Transform=estimateRigidTransform(frame,prev_frame,0);
Transform(Range(0,2),Range(0,2))=Mat::eye(2,2,CV_64FC1);
Transform_avg+=(Transform-Transform_avg)/2.0;
warpAffine(frame,warped,Transform_avg,Size( frame.cols, frame.rows));
imshow("Camw",warped);
}
if(prev_frame.empty())
{
prev_frame=frame.clone();
}
k=waitKey(20);
}
cv::destroyAllWindows();
return 0;
}
You can also look for paper: Chen_Halawa_Pang_FastVideoStabilization.pdf as I remeber there was MATLAB source code supplied.

In your "warpAffine(frame,warped,Transform_avg,Size( frame.cols, frame.rows));" function, you must specify FLAG as WARP_INVERSE_MAP for stabilization.
Sample code I have written:
Mat src, prev, curr, rigid_mat, dst;
VideoCapture cap("test_a3.avi");
while (1)
{
bool bSuccess = cap.read(src);
if (!bSuccess) //if not success, break loop
{
cout << "Cannot read the frame from video file" << endl;
break;
}
cvtColor(src, curr, CV_BGR2GRAY);
if (prev.empty())
{
prev = curr.clone();
}
rigid_mat = estimateRigidTransform(prev, curr, false);
warpAffine(src, dst, rigid_mat, src.size(), INTER_NEAREST|WARP_INVERSE_MAP, BORDER_CONSTANT);
// ---------------------------------------------------------------------------//
imshow("input", src);
imshow("output", dst);
Mat dst_gray;
cvtColor(dst, dst_gray, CV_BGR2GRAY);
prev = dst_gray.clone();
waitKey(30);
}
Hoping this will solve your problem :)

Surf is not so fast. the way I work is with Optical Flow. First you have to calculating good features on your first frame with the GoodFeaturesToTrack() function. After that I do some optimalisation with the FindCornerSubPix() function.
now you have the featurepoints in your startframe, the next thing you have to do is determine the optical flow. There are several Optical Flow functions but the one I use is OpticalFlow.PyrLK(), in one of the out parameters you get the featurespoints in the current frame. With that you can calculate the Homography matrix with the FindHomography() function. Next you have to do is invert this matrix, the explanation you can easily find with google, next you call the WarpPerspective() function to stabilize your frame.
PS. The functions I put here where from EmguCV, the .NET wrapper for OpenCV, so ther may be some differences

Related

Compare two image in real time with predefined image with real time capture image in Opencv c++

I am doing a project of Automatic fabric defect detection. In this i developed the algorithm using the [FFT][1] (Fast Fourier Transform) and its working fine in my Ubuntu 14.04 opencv c++. But now i want to develop this to real time there i have to capture image every 2s and have to process that image with my developed algorithm. I need ideas on how to capture images using webcam in opencv c++ and to process withat same image which is being captured. Please do help me if anyone knows of this. Thank you in advance.
You can follow the guidance which has given by OpenCV - They have provided enough examples such as following sample code. Following code is provided by OpenCV Dev team as sample.
#include "opencv2/opencv.hpp"
using namespace cv;
int main(int, char**)
{
VideoCapture cap(0); // open the default camera
if(!cap.isOpened()) // check if we succeeded
return -1;
Mat edges;
namedWindow("edges",1);
for(;;)
{
Mat frame;
cap >> frame; // get a new frame from camera
cvtColor(frame, edges, CV_BGR2GRAY);
GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
Canny(edges, edges, 0, 30, 3);
imshow("edges", edges);
if(waitKey(30) >= 0) break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}

OpenCV histogram of an irregular shape

I'm comparatively new to OpenCV. I was wondering if it is possible to get histogram of a contour (which can be a perfect rectangular or irregular in shape) found by findcontour.
Thanks in advance.
Edit:
This is what exactly I'm trying to achieve. I want to analyse area in contour to detect defects (by analyzing histogram of an area ?) and declare piece defective or good. Images attached.
Good sample. (Contour detected is outlined in gray color)
Defective sample. (defect around top left corner)
You may probably misuse the histogram.
Contour of an image should be a binary-valued, color-less matrix which does not represent grayscale-level of pixels, but the boundaries.
Meanwhile, histogram is a tool for analyzing how grayscale-valued of pixels distribute in your 2D image, isn't it?
Thus, why you want to profile the histogram of a binary-valued matrix which might not help you analyzing the image? Histogram is not the right t ool for the contour analysis though.
What you may get from the histogram should just be only a two-bar histogram because the contoured matrix contains only binary values. This might not be helpful for analysis.
Here's an other way, using morphological operations.
#include <string>
#include <iostream>
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
cv::Mat make_element(int morph_size, int elem_type)
{
cv::Size sz{2*morph_size+1, 2*morph_size+1};
cv::Point pt{morph_size, morph_size};
cv::Mat element{getStructuringElement(elem_type, sz, pt)};
return element;
}
int main(int argc, char **argv)
{
std::string fn{argv[1]};
cv::Mat src{cv::imread(fn)}, dst, mask[3];
if (!src.data) {
std::cerr << "No image data :(" << std::endl;
return -1;
}
// Clean out noise
cv::Mat elem1{make_element(5, cv::MORPH_RECT)};
cv::morphologyEx(src, dst, cv::MORPH_OPEN, elem1);
// Close the hole, then XOR with original
cv::Mat elem2{make_element(45, cv::MORPH_ELLIPSE)};
morphologyEx(dst, dst, cv::MORPH_CLOSE, elem2);
cv::bitwise_xor(src, dst, dst);
// Clean out noise (again)
cv::Mat elem3{make_element(1, cv::MORPH_RECT)};
cv::morphologyEx(dst, dst, cv::MORPH_OPEN, elem3);
// Mark the hole
cv::split(dst, mask);
cv::bitwise_xor(src, dst, dst, mask[0]);
// Overlay
cv::split(dst, mask);
cv::Mat empty{dst.size(), CV_8UC1};
std::vector<cv::Mat> v{empty, empty, mask[0]};
cv::merge(v, dst);
cv::bitwise_or(src, dst, dst);
cv::namedWindow("Defect (ESC to quit)", cv::WINDOW_NORMAL);
cv::startWindowThread();
cv::imshow("Defect (ESC to quit)", dst);
while (true) {
int k = cv::waitKey(100) & 0xff;
if (k == 27) {
break;
}
}
cv::destroyAllWindows();
return 0;
};
Some additional reading:
Shapiro/Stockman, Finding gear defects, Chapter 3
OpenCV morphology tutorial

Thresholding Images from a Webcam

I am teaching myself OpenCV for a work project that will eventually involve object tracking and such, and I'm just trying to familiarize myself with the basics right now. I have a chunk of code that's meant to simply grab images from my webcam, convert them to grayscale and threshold them, and print them out to a window. I keep getting this error:
"cannot convert parameter 1 from 'cv::Mat' to 'const CvArr *'"
with this code:
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
int main()
{
Mat img;
VideoCapture cap(0);
while (true)
{
cap >> img;
Mat tHold;
cvtColor(img, tHold, CV_BGR2GRAY);
cvThreshold(tHold, tHold, 50, 255, CV_THRESH_BINARY);
imshow("Thresholded Image", tHold);
waitKey(1);
}
return 0;
}
The thing is that other functions seem to work, like Canny(), etc...I just can't get thresholding to work. Thoughts? Thanks!
You are using the function cvThreshold from the C interface of OpenCV. Whereas the input images are of type cv::Mat which are from the C++ interface.
The corresponding C++ function of cvThreshold is cv::threshold. Just replace cvThreshold with cv::threshold.

C/C++ OpenCV video processing

Good day everyone! So currently I'm working on a project with video processing, so I decided to give a try to OpenCV. As I'm new to it, I decided to find few sample codes and test them out. First one, is C OpenCV and looks like this:
#include <opencv/cv.h>
#include <opencv/highgui.h>
#include <stdio.h>
int main( void ) {
CvCapture* capture = 0;
IplImage *frame = 0;
if (!(capture = cvCaptureFromCAM(0)))
printf("Cannot initialize camera\n");
cvNamedWindow("Capture", CV_WINDOW_AUTOSIZE);
while (1) {
frame = cvQueryFrame(capture);
if (!frame)
break;
IplImage *temp = cvCreateImage(cvSize(frame->width/2, frame->height/2), frame->depth, frame->nChannels); // A new Image half size
cvResize(frame, temp, CV_INTER_CUBIC); // Resize
cvSaveImage("test.jpg", temp, 0); // Save this image
cvShowImage("Capture", frame); // Display the frame
cvReleaseImage(&temp);
if (cvWaitKey(5000) == 27) // Escape key and wait, 5 sec per capture
break;
}
cvReleaseImage(&frame);
cvReleaseCapture(&capture);
return 0;
}
So, this one works perfectly well and stores image to hard drive nicely. But problems begin with next sample, which uses C++ OpenCV:
#include "opencv2/opencv.hpp"
#include <string>
using namespace cv;
int main(int, char**)
{
VideoCapture cap(0); // open the default camera
if(!cap.isOpened()) // check if we succeeded
return -1;
Mat edges;
//namedWindow("edges",1);
for(;;)
{
Mat frame;
cap >> frame; // get a new frame from camera
cvtColor(frame, edges, CV_RGB2XYZ);
imshow("edges", edges);
//imshow("edges2", frame);
//imwrite("test1.jpg", frame);
if(waitKey(1000) >= 0) break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}
So, yeah, generally, in terms of showing video (image frames) there is practically no changes, but when it comes to using im** functions, some problems arise.
Using cvSaveImage() works out nicely, but the moment I try to use imwrite(), unhandled exception arises in regards of 'access violation reading location'. Same goes for imread(), when I'm trying to load image.
So, the thing I wanted to ask, is it possible to use most of the functionality with C OpenCV? Or is it necessary to use C++ OpenCV. If yes, is there any solution for the problem I described earlier.
Also as stated here, images initially are in BGR-format, so conversion needed. But doing BGR2XYZ conversion seems to invert colors, while RGB2XYZ preserve them. Examples:
images
Or is it necessary to use C++ OpenCV?
No, there is no necessity whatsoever. You can use any interface you like and you think you are good with it (OpenCV offers C, C++, Python interfaces).
For your problem about imwrite() and imread() :
For color images the order channel is normally Blue, Green, Red , this
is what imshow() , imread() and imwrite() expect
Quoted from there

OpenCV Gives an error when using the imgproc functions

when I compile and run this code, I get an error. It compiles, but when I try to run it, it gives the following error:
The application has requested the Runtime to terminate in an unusual way.
This is the code:
#include <opencv2/opencv.hpp>
#include <string>
int main() {
cv::VideoCapture c(0);
double rate = 10;
bool stop(false);
cv::Mat frame;
cv::namedWindow("Hi!");
int delay = 1000/rate;
cv::Mat corners;
while(!stop){
if(!c.read(frame))
break;
cv::cornerHarris(frame,corners,3,3,0.1);
cv::imshow("Hi!",corners);
if(cv::waitKey(delay)>=0)
stop = true;
}
return 0;
}
BTW, I get the same error when using the Canny edge detector.
Your corners matrix is declared as a variable, but there is no memory allocated to it. The same with your frame variable. First you have to create a matrix big enough for the image to fit into it.
I suggest you first take a look at cvCreateImage so you can learn how basic images are created and handled, before you start working with video streams.
Make sure the capture is ready, and the image is ok:
if(!cap.IsOpened())
break;
if(!c.read(frame))
break;
if(frame.empty())
break;
You need to convert the image to grayscale before you use the corner detector:
cv::Mat frameGray;
cv::cvtColor(frame, frameGray, CV_RGB2GRAY);