I want to track an object in 2 images (Shot A, Shot B).
I know the location of the object in the first shot (ShotA) but I don't know the location of the object in the second shot (Shot B).
Shot A has multiple objects, so in order to track a specific object, I am selecting ROI of image where the object I want to track is. The problem is how do I track the features of that object in Shot B while keeping the same ROI size. Can I track the features of that object in the whole Image B without selecting an ROI?
This is the code I have. Currently it selects the same ROI of SHOTA in SHOTB, but sometimes the object in ROI of SHOTA is not in the ROI of SHOT B.
IplImage* imgA = cvLoadImage("52783180_RAW_OVR1.jpg",CV_LOAD_IMAGE_GRAYSCALE);
cvSetImageROI(imgA, cvRect(2300, 1700, 1000,1200));
cvNamedWindow("SHOTA",0);
cvShowImage("SHOTA", imgA);
//cvWaitKey(0);
CvSize img_sz = cvGetSize( imgA );
int win_size = 10;
IplImage* imgB = cvLoadImage("52783180_RAW_OVR2.jpg",CV_LOAD_IMAGE_GRAYSCALE);
cvSetImageROI(imgB, cvRect(2300, 1700, 1000,1200));
cvNamedWindow("SHOTB",0);
cvShowImage("SHOTB", imgB);
IplImage* imgC=cvLoadImage("52783180_RAW_OVR2.jpg",CV_LOAD_IMAGE_UNCHANGED);
cvSetImageROI(imgC, cvRect(2300, 1700, 1000,1200));
//cvNamedWindow("SHOTA",0);
//cvShowImage("SHOTA", imgA);
IplImage* eig_image = cvCreateImage( img_sz, IPL_DEPTH_32F, 1 );
IplImage* tmp_image = cvCreateImage( img_sz, IPL_DEPTH_32F, 1 );
int corner_count = MAX_CORNERS;
CvPoint2D32f* cornersA = new CvPoint2D32f[ MAX_CORNERS ];
//cvSetImageROI(imgA, cvRect(2300, 1700, 1000,1200));
cvGoodFeaturesToTrack(
imgA,
eig_image,
tmp_image,
cornersA,
&corner_count,
0.01,
5.0,
0,
3,
0,
0.04
);
//cvResetImageROI(imgA);
cvFindCornerSubPix(
imgA,
cornersA,
corner_count,
cvSize(win_size,win_size),
cvSize(-1,-1),
cvTermCriteria(CV_TERMCRIT_ITER|CV_TERMCRIT_EPS,20,0.03)
);
// Call the Lucas Kanade algorithm
//
char features_found[ MAX_CORNERS ];
float feature_errors[ MAX_CORNERS ];
CvSize pyr_sz = cvSize( imgA->width+8, imgB->height/3 );
IplImage* pyrA = cvCreateImage( pyr_sz, IPL_DEPTH_32F, 1 );
IplImage* pyrB = cvCreateImage( pyr_sz, IPL_DEPTH_32F, 1 );
CvPoint2D32f* cornersB = new CvPoint2D32f[ MAX_CORNERS ];
cvCalcOpticalFlowPyrLK(
imgA,
imgB,
pyrA,
pyrB,
cornersA,
cornersB,
corner_count,
cvSize( win_size,win_size ),
5,
features_found,
feature_errors,
cvTermCriteria( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, .3 ),
0
);
// Now make some image of what we are looking at:
//
float sum=0;
for( int i=0; i<corner_count; i++ ) {
if( features_found[i]==0|| feature_errors[i]>550 ) {
// printf("Error is %f/n",feature_errors[i]);
continue;
}
sum+=(cornersA[i].x-cornersB[i].x)*(cornersA[i].x-cornersB[i].x)+(cornersA[i].y-cornersB[i].y)*(cornersA[i].y-cornersB[i].y);
// printf("Got it/n");
CvPoint p0 = cvPoint(
cvRound( cornersA[i].x ),
cvRound( cornersA[i].y )
);
CvPoint p1 = cvPoint(
cvRound( cornersB[i].x ),
cvRound( cornersB[i].y )
);
cvLine( imgC, p0, p1, CV_RGB(255,0,0),2 );
}
cvResetImageROI(imgC);
sum=sum/corner_count;
printf("%f\n",sum);
cvNamedWindow("ImageA",0);
cvNamedWindow("ImageB",0);
cvNamedWindow("LKpyr_OpticalFlow",0);
cvShowImage("ImageA",imgA);
cvShowImage("ImageB",imgB);
cvShowImage("LKpyr_OpticalFlow",imgC);
cvWaitKey(0);
Problem solved by using mask instead of setimageroi for GoodfeaturestoTrack
Related
I have created a haar cascade classifier for detecting a hand with 1000 positive images and 2000 negative images. The xml file was created using convert_cascade.c from opencv samples. Now I am using the following code for detection, but the assert statement is giving an error as shown below
"assertion failed= cascade && storage && capture, line 21", which is the assertion call itself. I know that assertion fails when the expression evaluates to zero. so, any idea what could be wrong with classifier, because storage and capture should be working fine anyways,
#include <stdio.h>
#include "opencv/cv.h"
#include "opencv/highgui.h"
CvHaarClassifierCascade *cascade;
CvMemStorage *storage;
void detect( IplImage *img );
int main( )
{
CvCapture *capture;
IplImage *frame;
int key;
char *filename = "haar3.xml"; // name of my classifier
cascade = ( CvHaarClassifierCascade* )cvLoad( filename, 0, 0, 0 );
storage = cvCreateMemStorage(0);
capture = cvCaptureFromCAM(0);
assert( cascade && storage && capture );
cvNamedWindow("video", 1);
while(1) {
frame = cvQueryFrame( capture );
detect(frame);
key = cvWaitKey(50);
}
cvReleaseImage(&frame);
cvReleaseCapture(&capture);
cvDestroyWindow("video");
cvReleaseHaarClassifierCascade(&cascade);
cvReleaseMemStorage(&storage);
return 0;
}
void detect(IplImage *img)
{
int i;
CvSeq *object = cvHaarDetectObjects(
img,
cascade,
storage,
1.5, //-------------------SCALE FACTOR
2,//------------------MIN NEIGHBOURS
1,//----------------------
// CV_HAAR_DO_CANNY_PRUNING,
cvSize( 24,24), // ------MINSIZE
cvSize(640,480) );//---------MAXSIZE
for( i = 0 ; i < ( object ? object->total : 0 ) ; i++ )
{
CvRect *r = ( CvRect* )cvGetSeqElem( object, i );
cvRectangle( img,
cvPoint( r->x, r->y ),
cvPoint( r->x + r->width, r->y + r->height ),
CV_RGB( 255, 0, 0 ), 2, 8, 0 );
//printf("%d,%d\nnumber =%d\n",r->x,r->y,object->total);
}
cvShowImage( "video", img );
}
I am trying to write some simple real time face detection code, but somehow it doesn't work. (I tried face detection code on an image and it works but with the code below i get a grey image onscreen and the code fails)
here is the code i have tried (it prints 'face detected!' one time to the output window)
CvHaarClassifierCascade *cascade;
CvMemStorage *storage;
char *face_cascade="haarcascade_frontalface_alt2.xml";
CvRect* r;
const CvArr* img_size;
IplImage *grayscale;
void detectFacialFeatures( IplImage *img)
{
grayscale = cvCreateImage(cvGetSize(img), 8, 1);
cvCvtColor(img, grayscale, CV_BGR2GRAY);
CvMemStorage* storage=cvCreateMemStorage(0);
cvClearMemStorage( storage );
cvEqualizeHist(grayscale, grayscale);
cascade = ( CvHaarClassifierCascade* )cvLoad( face_cascade, 0, 0, 0 );
CvSeq* faces = cvHaarDetectObjects(grayscale, cascade, storage, 1.1, 3, CV_HAAR_DO_CANNY_PRUNING, cvSize( 50, 50 ) );
if(faces)
{
printf("face detected!");
r = ( CvRect* )cvGetSeqElem( faces, 0 );
cvRectangle( img,cvPoint( r->x, r->y ),cvPoint( r->x + r->width, r->y + r->height ), CV_RGB( 255, 0, 0 ), 1, 8, 0 );
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int c;
IplImage* color_img;
CvCapture* cv_cap = cvCreateCameraCapture(0);
cvSetCaptureProperty(cv_cap, CV_CAP_PROP_FRAME_WIDTH, 640);
cvSetCaptureProperty(cv_cap, CV_CAP_PROP_FRAME_HEIGHT, 480);
cvNamedWindow("Video",1); // create window
for(;;) {
color_img = cvQueryFrame(cv_cap); // get frame
if(color_img==0)
break;
cvFlip(color_img, 0, 1); //mirror image
detectFacialFeatures(color_img);
cvShowImage("Video", color_img); // show frame
c = cvWaitKey(10); // wait 10 ms or for key stroke
if(c == 27)
break; // if ESC, break and quit
}
/* clean up */
cvReleaseCapture( &cv_cap );
cvDestroyWindow("Video");
}
Try without calling functions cvFlip and cvEqualizeHistogram.
Look at(just use cvShowImage) result of each operation(cvFlip, cvCvtColor, cvEqualizeHistogram) - it's possible that result of one of these operations is gray image.
You don't have to load haar classifier each time you try to find a face - load it at the beginning. Operations on files are slow so it should makes you code faster.
I have implemented optical flow to track vehicles on road and it turned out to be very slow.
my code uses the functions:
cvGoodFeaturesToTrack
cvFindCornerSubPix
cvCalcOpticalFlowPyrLK
How do I make this tracking fast and efficient?
My code is:
#include "highgui.h"
#include "cv.h"
#include "cxcore.h"
#include <iostream>
using namespace std;
const int MAX_CORNERS = 500;
int main()
{
CvCapture* capture=cvCreateFileCapture("E:\cam1.avi");
IplImage* img_A;// = cvLoadImage("image0.png", CV_LOAD_IMAGE_GRAYSCALE);
IplImage* img_B;// = cvLoadImage("image1.png", CV_LOAD_IMAGE_GRAYSCALE);
img_A=cvQueryFrame(capture);
IplImage* imgA = cvCreateImage( cvGetSize(img_A), 8, 1 );
IplImage* imgB = cvCreateImage( cvGetSize(img_A), 8, 1 );
cvNamedWindow( "ImageA", CV_WINDOW_AUTOSIZE );
cvNamedWindow( "ImageB", CV_WINDOW_AUTOSIZE );
cvNamedWindow( "LKpyr_OpticalFlow", CV_WINDOW_AUTOSIZE );
while(1)
{
int couter=0;
for(int k=0;k<20;k++)
{
img_B=cvQueryFrame(capture);
}
//cvCvtColor(imgA,imgA,CV_BGR2GRAY);
//cvCvtColor(imgB,imgB,CV_BGR2GRAY);
// Load two images and allocate other structures
/*IplImage* imgA = cvLoadImage("image0.png", CV_LOAD_IMAGE_GRAYSCALE);
IplImage* imgB = cvLoadImage("image1.png", CV_LOAD_IMAGE_GRAYSCALE);*/
CvSize img_sz = cvGetSize( img_A );
int win_size = 10;
IplImage* imgC = cvCreateImage( cvGetSize(img_A), 8, 1 );
cvZero(imgC);
// Get the features for tracking
IplImage* eig_image = cvCreateImage( img_sz, IPL_DEPTH_32F, 1 );
IplImage* tmp_image = cvCreateImage( img_sz, IPL_DEPTH_32F, 1 );
int corner_count = MAX_CORNERS;
CvPoint2D32f* cornersA = new CvPoint2D32f[ MAX_CORNERS ];
cvCvtColor(img_A,imgA,CV_BGR2GRAY);
cvCvtColor(img_B,imgB,CV_BGR2GRAY);
cvGoodFeaturesToTrack( imgA, eig_image, tmp_image, cornersA, &corner_count ,0.05, 5.0, 0, 3, 0, 0.04 );
cvFindCornerSubPix( imgA, cornersA, corner_count, cvSize( win_size, win_size ) ,cvSize( -1, -1 ), cvTermCriteria( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.03 ) );
// Call Lucas Kanade algorithm
char features_found[ MAX_CORNERS ];
float feature_errors[ MAX_CORNERS ];
CvSize pyr_sz = cvSize( imgA->width+8, imgB->height/3 );
IplImage* pyrA = cvCreateImage( pyr_sz, IPL_DEPTH_32F, 1 );
IplImage* pyrB = cvCreateImage( pyr_sz, IPL_DEPTH_32F, 1 );
CvPoint2D32f* cornersB = new CvPoint2D32f[ MAX_CORNERS ];
/*int jk=0;
for(int i=0;i<imgA->width;i+=10)
{
for(int j=0;j<imgA->height;j+=10)
{
cornersA[jk].x=i;
cornersA[jk].y=j;
++jk;
}
}
*/
cvCalcOpticalFlowPyrLK( imgA, imgB, pyrA, pyrB, cornersA, cornersB, corner_count,
cvSize( win_size, win_size ), 5, features_found, feature_errors,
cvTermCriteria( CV_TERMCRIT_ITER | CV_TERMCRIT_EPS, 20, 0.3 ), 0 );
// Make an image of the results
for( int i=0; i < corner_count; i++ )
{
if( features_found[i]==0|| feature_errors[i]>550 )
{
//printf("Error is %f/n",feature_errors[i]);
continue;
}
//printf("Got it/n");
CvPoint p0 = cvPoint( cvRound( cornersA[i].x ), cvRound( cornersA[i].y ) );
CvPoint p1 = cvPoint( cvRound( cornersB[i].x ), cvRound( cornersB[i].y ) );
cvLine( imgC, p0, p1, CV_RGB(255,0,0), 2 );
cout<<p0.x<<" "<<p0.y<<endl;
}
cvShowImage( "LKpyr_OpticalFlow", imgC );
cvShowImage( "ImageA", imgA );
cvShowImage( "ImageB", imgB );
//cvCopyImage(imgB,imgA);
delete[] cornersA;
delete[] cornersB;
cvWaitKey(33);
}
return 0;
}
I might be going a bit over the line here but I would suggest you to check out OpenTLD. OpenTLD (aka Predator) is one of the most efficient tracking algorithm. Zdenek Kalal has implemented OpenTLD in MATLAB. George Nebehay has made a very efficient C++ OpenCV port of OpenTLD.
It's very easy to install and tracking is really efficient.
OpenTLD uses Median Flow Tracker to track and implements PN learning algorithm. In this YouTube Video, Zdenek Kalal shows the use of OpenTLD.
If you just want to implement a Median Flow Tracker, follow this link https://github.com/gnebehay/OpenTLD/tree/master/src/mftracker
If you want to use it in Python, I have made a Median Flow Tracker and also made a Python port of OpenTLD. But python port isn't much efficient.
First of all to track a car you have to somehow detect it (using color segmentation/background subtraction for example). When car is detected you have to track it (track some points on it) using cvCalcOpticalFlowPyrLK. I didn't find code that responces for car detection.
Take a look at this and this articles. Your idea should be the same.
Also your code is a bit wrong. For example why do you call cvGoodFeaturesToTrack in the main loop? You have to call it once - before loop to detect good features to track. But this will also detect non-cars.
Take a look at default OpenCV example: OpenCV/samples/cpp/lkdemo.cpp.
hey i tried to made a histogram that shows frames substraction, the code is running but i got gray window without result.
the message on the command window is:
Compiler did not align stack variables. Libavcodec has been miscompiled
and may be very slow or crash. This is not a bug in libavcodec,
but in the compiler. You may try recompiling using gcc >= 4.2.
Do not report crashes to FFmpeg developers.
OpenCV Error: Assertion failed (images[j].channels() == 1) in unknown function,
file ........\ocv\opencv\src\cv\cvhistogram.cpp, line 137
here is the code someone have an idea?thanks for help.....
int main()
{
int key = 0;
CvCapture* capture = cvCaptureFromAVI( "macroblock.mpg" );
IplImage* frame = cvQueryFrame( capture );
IplImage* currframe = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3);
IplImage* destframe = cvCreateImage(cvGetSize(frame),IPL_DEPTH_8U,3);
IplImage* imgHistogram = 0;
CvHistogram* hist;
if ( !capture )
{
fprintf( stderr, "Cannot open AVI!\n" );
return 1;
}
int fps = ( int )cvGetCaptureProperty( capture, CV_CAP_PROP_FPS );
cvNamedWindow( "dest", CV_WINDOW_AUTOSIZE );
cvNamedWindow( "imgHistogram", CV_WINDOW_AUTOSIZE );
while( key != 'x' )
{
frame = cvQueryFrame( capture );
currframe = cvCloneImage( frame );
frame = cvQueryFrame( capture );
cvSub(frame,currframe,destframe);
int bins = 256;
int hsize[] = {bins};
float max_value = 0, min_value = 0;
float value;
int normalized;
float xranges[] = {0, 256};
float* ranges[] = {xranges};
IplImage* planes[] = {destframe};
hist = cvCreateHist(1, hsize, CV_HIST_ARRAY, ranges,1);
cvCalcHist(planes, hist, 0, NULL);
cvGetMinMaxHistValue(hist, &min_value, &max_value);
// printf("Minimum Histogram Value: %f, Maximum Histogram Value: %f\n", min_value, max_value);
imgHistogram = cvCreateImage(cvSize(bins, 50),IPL_DEPTH_8U,3);
cvRectangle(imgHistogram, cvPoint(0,0), cvPoint(256,50), CV_RGB(255,255,255),-1);
for(int i=0; i < bins; i++){
value = cvQueryHistValue_1D(hist, i);
normalized = cvRound(value*50/max_value);
cvLine(imgHistogram,cvPoint(i,50), cvPoint(i,50-normalized), CV_RGB(0,0,0));
}
if(key==27 )break;
cvShowImage( "dest",destframe);
cvShowImage( "imgHistogram",imgHistogram);
key = cvWaitKey( 1000 / 10 );
}
cvDestroyWindow( "dest" );
cvReleaseCapture( &capture );
return 0;
}
Since you are trying to show a 1D histogram, the histogram plane needs to be in grayscale. So, you need to convert the resulting image from cvSub() to grayscale first. Try
IplImage *gray = NULL;
gray = cvCreateImage(cvGetSize(frame), IPL_DEPTH_8U, 1);
while(key != 'x') {
...
cvSub(frame, currframe, destframe);
cvCvtColor(destframe, gray, CV_BGR2GRAY);
...
IplImage* planes[] = {gray};
..
}
Let me know if it works for you.
I am using the code available in this website: http://nashruddin.com/OpenCV_Face_Detection to do face detection.
I would like to increase the size of the detected face region. I am not sure how to do it. Need some help on it..
The code i am using is this:
//
#include "stdafx.h"
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
CvHaarClassifierCascade *cascade;
CvMemStorage *storage;
void detectFaces( IplImage *img );
int main( int argc, char** argv )
{
CvCapture *capture;
IplImage *frame;
int key;
char *filename = "C:/OpenCV2.1/data/haarcascades/haarcascade_frontalface_alt.xml";
cascade = ( CvHaarClassifierCascade* )cvLoad( filename, 0, 0, 0 );
storage = cvCreateMemStorage( 0 );
capture = cvCaptureFromCAM( 0 );
assert( cascade && storage && capture );
cvNamedWindow( "video", 1 );
while( key != 'q' ) {
frame = cvQueryFrame( capture );
if( !frame ) {
fprintf( stderr, "Cannot query frame!\n" );
break;
}
cvFlip( frame, frame, -1 );
frame->origin = 0;
detectFaces( frame );
key = cvWaitKey( 10 );
}
cvReleaseCapture( &capture );
cvDestroyWindow( "video" );
cvReleaseHaarClassifierCascade( &cascade );
cvReleaseMemStorage( &storage );
return 0;
}
void detectFaces( IplImage *img )
{
int i;
CvSeq *faces = cvHaarDetectObjects(
img,
cascade,
storage,
1.1,
3,
0 /*CV_HAAR_DO_CANNY_PRUNNING*/,
cvSize( 40, 40 ) );
for( i = 0 ; i < ( faces ? faces->total : 0 ) ; i++ ) {
CvRect *r = ( CvRect* )cvGetSeqElem( faces, i );
cvRectangle( img,
cvPoint( r->x, r->y ),
cvPoint( r->x + r->width, r->y + r->height ),
CV_RGB( 255, 0, 0 ), 1, 8, 0 );
}
cvShowImage( "video", img );
}
This increases the size of the rectangle around the face. If you meant increasing the haar detector's window size, please update your question.
int padding_width = 30; // pixels
int padding_height = 30; // pixels
for( i = 0 ; i < ( faces ? faces->total : 0 ) ; i++ ) {
CvRect *r = ( CvRect* )cvGetSeqElem( faces, i );
// Yes yes, all of this could be written much more compactly.
// It was written like this for clarity.
int topleft_x = r->x - (padding_width / 2);
int topleft_y = r->y - (padding_height / 2);
if (topleft_x < 0)
topleft_x = 0;
if (topleft_y < 0)
topleft_y = 0;
int bottomright_x = r->x + r->width + (padding_width / 2);
int bottomright_y = r->y + r->height + (padding_height / 2);
if (bottomright_x >= img->width)
bottomright_x = img->width - 1;
if (bottomright_y >= img->height)
bottomright_y = img->height - 1;
cvRectangle( img,
cvPoint(topleft_x, topleft_y),
cvPoint(bottomright_x, bottomright_y),
CV_RGB( 255, 0, 0 ), 1, 8, 0 );
}