OpenCV Assertion Failed with SolvePnP - c++

I'm trying to use solvePnP in a C++ program that detects a chessboard in a video stream. Every time the calibration finishes, I try to run solvePnP, but I keep getting errors that I think are related to the translation and rotation vectors.
This is the error:
The error
This is my code:
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include <fstream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace cv;
using namespace std;
//Global variables
vector<vector<Point2f> > corner_list;
vector<vector<Point3f> > point_list;
vector<Mat> rotation_vecs, translation_vecs;
int i = 0;
bool calibMode = true, drawMode = false, drawMode2 = false, camMatrixInit = false, calibrated = false;
Mat originalCameraMatrix, cameraMatrix, distCoefficients, frame, gray, rvec, tvec;
//Function declarations
vector<Point3f> genWorldPoints(int cols, int rows);
void printCameraMatrix();
void printDistCoeff();
void printRotVecs();
/*Generates the world points (0, 0, 0), (1, 0, 0), etc. for the camera calibration.*/
vector<Point3f> genWorldPoints(int cols, int rows){
vector<Point3f> ret;
for (int i=0; i<rows; i++) {
for (int j=0; j<cols; j++) {
int tempi = i*(-1);
ret.push_back(Point3f((float)j, (float)tempi, 0.0));
}
}
return ret;
}
/*Print the camera matrix*/
void printCameraMatrix(){
cout << "Original Camera Matrix" << endl << originalCameraMatrix << endl;
cout << "Current Camera Matrix" << endl << cameraMatrix << endl;
}
/*Prints the distortion coefficients*/
void printDistCoeff(){
cout << "Distortion Coefficients:"<< endl << distCoefficients << endl;
}
int main(int argc, char *argv[]){
VideoCapture *capdev;
cameraMatrix = Mat::eye(3, 3, CV_64F);
distCoefficients = Mat::zeros(8, 1, CV_64F);
// open the video device
capdev = new VideoCapture(0);
if (!capdev->isOpened()) {
printf("Unable to open video device\n");
return(-1);
}
namedWindow("Video", 1);
bool found;
*capdev >> frame;
rvec = Mat::zeros(3, 1, CV_64F);
tvec = Mat::zeros(3, 1, CV_64F);
//Initialize camera matrix
cameraMatrix.at<double>(0,2) = (frame.size().width)/2;
cameraMatrix.at<double>(1,2) = (frame.size().height)/2;
cameraMatrix.copyTo(originalCameraMatrix);
printCameraMatrix();
for(;;){
*capdev >> frame;
if (!found) {
imshow("Video", frame);
}
Size patternsize(9,6);
vector<Point2f> corner_set;
vector<Point3f> point_set;
int code = waitKey(10);
cvtColor(frame, gray, CV_BGR2GRAY);
found = findChessboardCorners(gray, patternsize, corner_set, CV_CALIB_CB_ADAPTIVE_THRESH | CV_CALIB_CB_FILTER_QUADS);
//Code to add a calibration frame
if (found && calibMode) {
cornerSubPix(gray, corner_set, Size(11, 11), Size(-1, -1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));
drawChessboardCorners(frame, patternsize, Mat(corner_set), found);
//s key press
if (code == 115){
printf("Adding calibration frame\n");
printf("Number of corners found: %lu\n", corner_set.size());
printf("Point 0 x: %f\ty: %f\n", corner_set[0].x, corner_set[1].y);
//Add the corner set
corner_list.push_back(corner_set);
//Generate point set
vector<Point3f> point_set = genWorldPoints(9,6);
//Add point set to point set list
point_list.push_back(point_set);
//Save the image
string filename = "../data/images/p4_calib_image_"+to_string(i)+".jpeg";
imwrite(filename, frame);
//if there are more than 5 saved calibration images, run calibration procedure
if (i>4) {
//Calculate the reprojection error by running calibrateCamera
double rpe = calibrateCamera(point_list, corner_list, frame.size(), cameraMatrix,
distCoefficients, rotation_vecs, translation_vecs,
CV_CALIB_FIX_ASPECT_RATIO | CV_CALIB_FIX_K4);
//Print the camera matrix
printCameraMatrix();
printDistCoeff();
//Print the reprojection error
cout << "Reprojection error: " << rpe << endl;
calibrated = true;
}
//Increment i
i++;
}
imshow("Video", frame);
}
else if (found && drawMode){
cout << "Draw mode" << endl;
bool solved = solvePnP(point_list, corner_list, cameraMatrix, distCoefficients,
rvec, tvec);
//rotation_vecs.front(), translation_vecs.front());
}
else if (found && drawMode2){
cout << "Draw mode 2" << endl;
bool solved = solvePnP(point_list, corner_list, cameraMatrix, distCoefficients,
rvec, tvec);
//rotation_vecs.front(), translation_vecs.front());
}
//Switching between drawing modes
if (calibrated && code == 49) {
calibMode = false;
drawMode2 = false;
drawMode = true;
}
else if (calibrated && code == 50){
calibMode = false;
drawMode = false;
drawMode2 = true;
}
//Switch back to calibration mode
else if (calibrated && code == 51){
drawMode = false;
drawMode2 = false;
calibMode = true;
}
if (code == 27) {
printf("Terminating\n");
delete capdev;
return(0);
}
}
capdev = new VideoCapture(0);
printf("Terminating\n");
delete capdev;
return(0);
}
Please excuse the indentation...

The problem is that sovlePnP requires vector<Point2/3f> as input, instead of vector<vector<Point2/3f> >. In your code, "point_list" is vector<vector<Point3f> >, and "corner_list" is vector<vector<Point2f> >.
The documentation of solvePnP can be found here: http://docs.opencv.org/3.0-beta/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html

Related

face tracking (eigen face) opencv

I want to do eigen face by opencv ,and this is my code.
#include "opencv2/core/core.hpp"'
#include "opencv2/contrib/contrib.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
using namespace cv;
using namespace std;
static void read_csv(const string& filename, vector<Mat>& images,vector<int>& labels, char separator = ';') {
ifstream file(filename.c_str(), ifstream::in);
if (!file) {
string error_message = "No valid input file was given, please check the given filename.";
CV_Error(CV_StsBadArg, error_message);
}
string line, path, classlabel;
while (getline(file, line)) {
stringstream liness(line);
getline(liness, path, separator);
getline(liness, classlabel);
if(!path.empty() && !classlabel.empty()) {
images.push_back(imread(path, 0));
labels.push_back(atoi(classlabel.c_str()));
}
}
}
int main(int argc, const char *argv[]) {
string fn_haar = string("C:/opencv/sources/data/haarcascades/haarcascade_frontalface_alt_tree.xml");
string fn_csv = string("C:/Users/faho0odywbas/Desktop/csv.ext");
int deviceId = atoi("0");
vector<Mat> images;
vector<int> labels;
try {
read_csv(fn_csv, images, labels);
} catch (cv::Exception& e) {
cerr << "Error opening file \"" << fn_csv << "\". Reason: " << e.msg << endl;
exit(1);
}
int im_width = images[0].cols;
int im_height = images[0].rows;
Ptr<FaceRecognizer> model = createEigenFaceRecognizer(23,2500.0);
CascadeClassifier haar_cascade;
haar_cascade.load(fn_haar);
VideoCapture cap(deviceId);
namedWindow("face_recognizer", CV_WINDOW_AUTOSIZE);
if(!cap.isOpened()) {
cerr << "Capture Device ID " << deviceId << "cannot be opened." << endl;
return -1;
}
vector< Rect_<int> > faces;
Mat frame;
waitKey(1500);
for(;;) {
cap >> frame;
Mat original = frame.clone();
Mat gray;
cvtColor(original, gray, CV_BGR2GRAY);
haar_cascade.detectMultiScale(gray, faces);
for(int i = 0; i < faces.size(); i++) {
Rect face_i = faces[i];
Mat face = gray(face_i);
Mat face_resized;
cv::resize(face, face_resized, Size(im_width, im_height), 1.0, 1.0, INTER_CUBIC);
int prediction = model->predict(face_resized);
rectangle(original, face_i, CV_RGB(255, 0,0), 1);
string box_text = format("Sujeto = %d", prediction);
int pos_x = std::max(face_i.tl().x - 10, 0);
int pos_y = std::max(face_i.tl().y - 10, 0);
putText(original, box_text, Point(pos_x, pos_y), FONT_HERSHEY_PLAIN, 1.0, CV_RGB(0,255,0), 2.0);
}
imshow("face_recognizer", original);
char key = (char) waitKey(1);
if(key == 27){
destroyAllWindows();
break;
}
}
return 0;
}
I'm sure it's right because it was work with my friend's computer, so I think the problem with my visual studio or the windows.
The error that comes to me is
" First-chance exception at 0x74C44598 in Project3.exe: Microsoft C++ exception: cv::Exception at memory location 0x00D7ED2C.
If there is a handler for this exception, the program may be safely continued. "
and when I click break, it shows also to me this error
wkernelbase.pdb not loaded
so, what I have to do ?
I have done this Tools->Options->Debugging->Symbols->Select “Microsoft Symbol Servers”.
but also same error
I have another question which is if I want hit "s" to start recording face for every frame, and hit "d" to end the recording, how can I do that ?
Thanks a lot

face detection (how to detect the circle around the face that we've detected)

my name is budi.
i am a newbie in image processing, recently i've been trying to learn about opencv and visual studio. i already succeed to detect the face then draw the circle around the face that i've detected thanks to the example in some DIY website. my question is, how to detect a circle that encircling the face ? so i can use it for "if" condition, for example
if ( condition )//there is at least one circle in the frame
{
bla bla bla
}
here is the code i use :
#include <opencv2/objdetect/objdetect.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/ocl/ocl.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/opencv_modules.hpp>
#include <opencv2/videostab/deblurring.hpp>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <sstream>
#include <string>
using namespace std;
using namespace cv;
const static Scalar colors[] = { CV_RGB(0,0,255),
CV_RGB(0,128,255),
CV_RGB(0,255,255),
CV_RGB(0,255,0),
CV_RGB(255,128,0),
CV_RGB(255,255,0),
CV_RGB(255,0,0),
CV_RGB(255,0,255)
} ;
void Draw(Mat& img, vector<Rect>& faces, double scale);
int main(int argc, const char** argv)
{
// Setup serial port connection and needed variables.
HANDLE hSerial = CreateFile(L"COM8", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hSerial !=INVALID_HANDLE_VALUE)
{
printf("Port opened! \n");
DCB dcbSerialParams;
GetCommState(hSerial,&dcbSerialParams);
dcbSerialParams.BaudRate = CBR_9600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.Parity = NOPARITY;
dcbSerialParams.StopBits = ONESTOPBIT;
//CvMemStorage* p_strStorage;
char incomingData[256] = ""; // don't forget to pre-allocate memory
//printf("%s\n",incomingData);
int dataLength = 256;
int readResult = 0;
SetCommState(hSerial, &dcbSerialParams);
}
else
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
printf("Serial port doesn't exist! \n");
}
printf("Error while setting up serial port! \n");
}
char outputChars[] ="c" ;
DWORD btsIO;
//void Draw(Mat& img, vector<Rect>& faces, double scale);
Mat frame, frameCopy, image;
//int i; // loop counter
//char charCheckForEscKey; // char for checking key press (Esc exits program)
//create the cascade classifier object used for the face detection
CascadeClassifier face_cascade;
//use the haarcascade_frontalface_alt.xml library
face_cascade.load("haarcascade_frontalface_alt.xml");
//setup video capture device and link it to the first capture device
VideoCapture captureDevice;
captureDevice.open(0);
if(captureDevice.open(0) == NULL)
{ // if capture was not successful . . .
printf("error: capture error \n"); // error message to standard out . . .
getchar(); // getchar() to pause for user see message . . .
return(-1);
}
//setup image files used in the capture process
Mat captureFrame;
Mat grayscaleFrame;
//create a window to present the results
namedWindow("FaceDetection", 1);
//int servoPosition = 90;
//int servoOrientation = 0;
//int servoPosition1=90;
//int servoOrientation1=0;
//create a loop to capture and find faces
while(true)
{
//p_imgOriginal = captureFrame;
//capture a new image frame
captureDevice>>captureFrame;
//convert captured image to gray scale and equalize
cvtColor(captureFrame, grayscaleFrame, CV_BGR2GRAY);
imshow("Grayscale", grayscaleFrame);
equalizeHist(grayscaleFrame, grayscaleFrame);
//p_strStorage = cvCreateMemStorage(0);
//create a vector array to store the face found
std::vector<Rect> faces;
//find faces and store them in the vector array
face_cascade.detectMultiScale(grayscaleFrame, faces, 1.1, 3, CV_HAAR_FIND_BIGGEST_OBJECT|CV_HAAR_SCALE_IMAGE, Size(30,30));
//draw a circle for all found faces in the vector array on the original image
//for(int i = 0; i < faces.size(); i++)
int i = 0;
//for( int i = 0; i < faces.size(); i++ )
for( vector<Rect>::const_iterator r = faces.begin(); r != faces.end(); r++, i++ )
{
Point center( faces[i].x + faces[i].width*0.5, faces[i].y + faces[i].height*0.5 );
Scalar color = colors[i%8];
center.x = cvRound((r->x + r->width*0.5));
center.y = cvRound((r->y + r->height*0.5));
Point pt1(faces[i].x + faces[i].width, faces[i].y + faces[i].height);
Point pt2(faces[i].x, faces[i].y);
int radius;
int X = faces[i].x;
int Y = faces[i].y;
radius = cvRound((faces[i].width + faces[i].height)*0.25);
//ellipse( frame, center, Size( faces[i].width*0.5, faces[i].height*0.5), 0, 0, 360, Scalar( 255, 0, 255 ), 2, 8, 0 );
//rectangle(captureFrame, pt1, pt2, cvScalar(0, 255, 0, 0), 1, 8, 0);
circle(captureFrame,center,radius,cvScalar(0, 255, 0, 0), 1, 8, 0);
cout << "X:" << faces[i].x << " Y:" << faces[i].y << endl;
if (radius >= 85)
{
outputChars[0] = 'a';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
cout << "radius >= 85, advertising begin" << endl;
//FlushFileBuffers(hSerial);
}
else if (radius <= 84)
{
outputChars[0] = 'b';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
//cout << "radius >= 85, advertising begin" << endl;
}
/*else if (radius >= 85 | X<=164 && X>=276)
{
outputChars[0] = 'z';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
cout << "radius >= 85, advertising begin" << endl;
//FlushFileBuffers(hSerial);
}
else if (radius < 85)
{
outputChars[0] = 'b';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
cout << "radius: " << radius << "radius < 85, advertising end!" << endl;
//FlushFileBuffers(hSerial);
}
/*if (X>=165 | X<=275)
{
outputChars[0]='u';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
cout <<"Face in the middle of the frame" << endl;
FlushFileBuffers(hSerial);
}
/*if (X<=164 | X>=276)
{
outputChars[0]='y';
WriteFile(hSerial, outputChars, strlen(outputChars), &btsIO, NULL);
cout <<"no face in the middle of the frame" << endl;
//FlushFileBuffers(hSerial);
}*/
}
//print the output
imshow("FaceDetection", captureFrame);
//pause for 200ms
waitKey(60);
}
cvDestroyWindow("FaceDetection");
cvDestroyWindow("Grayscale");
FlushFileBuffers(hSerial);
// This closes the Serial Port
CloseHandle(hSerial);
return 0;
}
please help me, and thank you all for the attention.

How do I code the optical flow calculations for the left half and the right half of the image?

I want to calculate optical flow on the left half and the right half of the captured video seperately. Using the results from the left and right half I want to eventually detect if the user(i.e. the camera) is moving forward or backward.
Currently, I have this system going for the left half of the screen. The code looks like this:
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <ctype.h>
using namespace cv;
using namespace std;
static void help()
{
cout << "*** Using OpenCV version " << CV_VERSION <<" ***"<< endl;
cout << "\n\nUsage: \n"
"\tESC - quit the program\n"
"\tr - auto-initialize tracking\n"
"\tc - delete all the points\n"
"\tn - switch the \"night\" mode on/off\n"<< endl;
}
int main( int argc, char** argv )
{
help();
//Termination of the algo after 20 iterations or accuracy going under 0.03
TermCriteria termcrit(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 20, 0.3);
Size subPixWinSize(10,10), winSize(31,31);
const int MAX_COUNT = 500;
bool needToInit = false;
bool nightMode = false;
//Video capture is from the default device i.e. the webcam
VideoCapture cap(0);
if( !cap.isOpened() )
{
cout << "Could not initialize capturing...\n";
return 0;
}
namedWindow( "Half screen Optical flow Demo!", 1 );
Mat gray, prevGray, image;
vector<Point2f> points[2];
for(;;)
{
Mat frame;
//Output from the Videocapture is piped to 'frame'
cap >> frame;
if( frame.empty() )
break;
frame.copyTo(image);
cvtColor(image, gray, COLOR_BGR2GRAY);
// Night mode not disabled
if( nightMode )
image = Scalar::all(0);
//This line saves into 'gray' only the left half of the original image. Thus making the detection of optical only on the left side possible.
gray = gray(Range(1,480), Range(1,320));
if( needToInit || points[0].size()<=5)
{
goodFeaturesToTrack(gray, points[1], MAX_COUNT, 0.01, 10, Mat(), 3, 0, 0.4);
cornerSubPix(gray, points[1], subPixWinSize, Size(-1,-1), termcrit);
}
else if( !points[0].empty() )
{
vector<uchar> status;
vector<float> err;
if(prevGray.empty())
gray.copyTo(prevGray);
calcOpticalFlowPyrLK(prevGray, gray, points[0], points[1], status, err, winSize, 3, termcrit, 0, 0.001);
size_t i, k;
for( i = k = 0; i < points[1].size(); i++ )
{
if( !status[i] )
continue;
points[1][k++] = points[1][i];
circle(image, points[1][i], 3, Scalar(0,255,0), -1, 8);
}
points[1].resize(k);
}
needToInit = false;
imshow("Half screen Optical flow Demo!", image);
char c = (char)waitKey(10);
if( c == 27 )
break;
switch( c )
{
case 'r':
needToInit = true;
break;
case 'c':
points[0].clear();
points[1].clear();
break;
case 'n':
nightMode = !nightMode;
break;
}
std::swap(points[1], points[0]);
cv::swap(prevGray, gray);
}
cap.release();
return 0;
}
How do I do this for the right half of the screen as well?
If I simply replicate the functions from above, say by modifying the image=image(Range(), Range()) values etc. I am not getting any output.
EDIT: Should I write out the part where the optical flow is calculated to a separate function and call it twice - once for the left half of the image and then for the right half?

Saving Images of Detected Faces in OpenCV

I have a code that detects faces and saves multiple cropped area images of them to a file path. My code doesn't stop saving images of detected faces until I physically close the program. For every one second a face is detected on a webcam, my code saves 6 images of the face.
Is it possible to have it save just one image per face detected? For example, if there is one face, only one image, if two faces, an image of both faces are saved etc. My code is below. Can anyone help me?
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
using namespace std;
using namespace cv;
void detectAndDisplay(Mat frame);
string face_cascade_name = "C:\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt2.xml";
CascadeClassifier face_cascade;
string window_name = "Window";
int filenumber;
string filename;
int main(void)
{
VideoCapture capture(0);
if (!capture.isOpened())
return -1;
if (!face_cascade.load(face_cascade_name))
{
cout << "error" << endl;
return (-1);
};
Mat frame;
for (;;)
{
capture >> frame;
if (!frame.empty())
{
detectAndDisplay(frame);
}
else
{
cout << "error2" << endl;
break;
}
int c = waitKey(10);
if (27 == char(c))
{
break;
}
}
return 0;
}
void detectAndDisplay(Mat frame)
{
std::vector<Rect> faces;
Mat frame_gray;
Mat crop;
Mat res;
Mat gray;
string text;
stringstream sstm;
cvtColor(frame, frame_gray, COLOR_BGR2GRAY);
equalizeHist(frame_gray, frame_gray);
face_cascade.detectMultiScale(frame_gray, faces, 1.1, 2, 0 | CASCADE_SCALE_IMAGE, Size(30, 30));
cv::Rect roi_b;
cv::Rect roi_c;
size_t ic = 0;
int ac = 0;
size_t ib = 0;
int ab = 0;
for (ic = 0; ic < faces.size(); ic++)
{
roi_c.x = faces[ic].x;
roi_c.y = faces[ic].y;
roi_c.width = (faces[ic].width);
roi_c.height = (faces[ic].height);
ac = roi_c.width * roi_c.height;
roi_b.x = faces[ib].x;
roi_b.y = faces[ib].y;
roi_b.width = (faces[ib].width);
roi_b.height = (faces[ib].height);
crop = frame(roi_b);
resize(crop, res, Size(128, 128), 0, 0, INTER_LINEAR);
cvtColor(crop, gray, CV_BGR2GRAY);
filename = "C:\\Users\\Desktop\\Faces\\face";
stringstream ssfn;
ssfn << filename.c_str() << filenumber << ".jpg";
filename = ssfn.str();
cv::imwrite(filename, res);
filenumber++;
Point pt1(faces[ic].x, faces[ic].y);
Point pt2((faces[ic].x + faces[ic].height), (faces[ic].y + faces[ic].width));
rectangle(frame, pt1, pt2, Scalar(0, 255, 0), 2, 8, 0);
}
sstm << "Crop area size: " << roi_b.width << "x" << roi_b.height << " Filename: " << filename;
text = sstm.str();
if (!crop.empty())
{
imshow("detected", crop);
}
else
destroyWindow("detected");
}

How do i actually set optical flow on half of the image captured?

I already had an optical flow code implemented using C++ in OpenCV. However, i would like to detect optical flow in half of the image frame. Which part should i edit? is it from this function below?
cvCalcOpticalFlowPyrLK(
frame1_1C, frame2_1C,
pyramid1, pyramid2,
frame1_features,
frame2_features,
number_of_features,
optical_flow_window,
5,
optical_flow_found_feature,
optical_flow_feature_error,
optical_flow_termination_criteria,
0 );
No. There are no changes necessary in the function itself. All you need to do is pass only the part of image on which you want to calculate optical flow to the function.
You can define the range of the image that you want to carry out the optical flow calculations on. using
wanted_image=image(Range(x1,y1), Range(x2,y2))
The following is a working code based on the lkdemo.cpp in the samples folder. THe only worthwhile change is
gray = gray(Range(1,480), Range(1,320));
//Gives the left half of the image
which defines the region of interest.
#include "opencv2/video/tracking.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
#include <ctype.h>
using namespace cv;
using namespace std;
static void help()
{
cout << "*** Using OpenCV version " << CV_VERSION <<" ***"<< endl;
cout << "\n\nUsage: \n"
"\tESC - quit the program\n"
"\tr - auto-initialize tracking\n"
"\tc - delete all the points\n"
"\tn - switch the \"night\" mode on/off\n"<< endl;
}
int main( int argc, char** argv )
{
help();
//Termination of the algo after 20 iterations or accuracy going under 0.03
TermCriteria termcrit(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS, 20, 0.3);
Size subPixWinSize(10,10), winSize(31,31);
const int MAX_COUNT = 500;
bool needToInit = false;
bool nightMode = false;
//Video capture is from the default device i.e. the webcam
VideoCapture cap(0);
if( !cap.isOpened() )
{
cout << "Could not initialize capturing...\n";
return 0;
}
namedWindow( "Half screen Optical flow Demo!", 1 );
Mat gray, prevGray, image;
vector<Point2f> points[2];
for(;;)
{
Mat frame;
//Output from the Videocapture is piped to 'frame'
cap >> frame;
if( frame.empty() )
break;
frame.copyTo(image);
cvtColor(image, gray, COLOR_BGR2GRAY);
// Night mode not disabled
if( nightMode )
image = Scalar::all(0);
gray = gray(Range(1,480), Range(1,320));
if( needToInit || points[0].size()<=5)
{
goodFeaturesToTrack(gray, points[1], MAX_COUNT, 0.01, 10, Mat(), 3, 0, 0.4);
cornerSubPix(gray, points[1], subPixWinSize, Size(-1,-1), termcrit);
}
else if( !points[0].empty() )
{
vector<uchar> status;
vector<float> err;
if(prevGray.empty())
gray.copyTo(prevGray);
calcOpticalFlowPyrLK(prevGray, gray, points[0], points[1], status, err, winSize, 3, termcrit, 0, 0.001);
size_t i, k;
for( i = k = 0; i < points[1].size(); i++ )
{
if( !status[i] )
continue;
points[1][k++] = points[1][i];
circle(image, points[1][i], 3, Scalar(0,255,0), -1, 8);
}
points[1].resize(k);
}
needToInit = false;
imshow("Half screen Optical flow Demo!", image);
char c = (char)waitKey(10);
if( c == 27 )
break;
switch( c )
{
case 'r':
needToInit = true;
break;
case 'c':
points[0].clear();
points[1].clear();
break;
case 'n':
nightMode = !nightMode;
break;
}
std::swap(points[1], points[0]);
cv::swap(prevGray, gray);
}
cap.release();
return 0;
}
if you want to detect optical flow only in the half of the image, then you can simply give halves of the images (frame1_1C, frame2_1C) as parameters. For example, following code initializes a matrix belonging to the left half of frame1_1C:
cv::Mat frame1_1C_half(frame1_1C, cv::Range(0, frame1_1C.rows), cv::Range(0, frame1_1C.cols/2));