Commit 52d0d8b7 authored by laurentBerger's avatar laurentBerger

bugfix4269 included remarks in…

bugfix4269 included remarks in http://answers.opencv.org/question/59293/problem-with-example-motemplcpp/
parent 292b8fa6
...@@ -12,22 +12,21 @@ using namespace cv::motempl; ...@@ -12,22 +12,21 @@ using namespace cv::motempl;
static void help(void) static void help(void)
{ {
printf( printf(
"\nThis program demonstrated the use of motion templates -- basically using the gradients\n" "\nThis program demonstrated the use of motion templates -- basically using the gradients\n"
"of thresholded layers of decaying frame differencing. New movements are stamped on top with floating system\n" "of thresholded layers of decaying frame differencing. New movements are stamped on top with floating system\n"
"time code and motions too old are thresholded away. This is the 'motion history file'. The program reads from the camera of your choice or from\n" "time code and motions too old are thresholded away. This is the 'motion history file'. The program reads from the camera of your choice or from\n"
"a file. Gradients of motion history are used to detect direction of motoin etc\n" "a file. Gradients of motion history are used to detect direction of motion etc\n"
"Usage :\n" "Usage :\n"
"./motempl [camera number 0-n or file name, default is camera 0]\n" "./motempl [camera number 0-n or file name, default is camera 0]\n"
); );
} }
// various tracking parameters (in seconds) // various tracking parameters (in seconds)
const double MHI_DURATION = 1; const double MHI_DURATION = 5;
const double MAX_TIME_DELTA = 0.5; const double MAX_TIME_DELTA = 0.5;
const double MIN_TIME_DELTA = 0.05; const double MIN_TIME_DELTA = 0.05;
// number of cyclic frame buffer used for motion detection // number of cyclic frame buffer used for motion detection
// (should, probably, depend on FPS) // (should, probably, depend on FPS)
const int N = 4;
// ring image buffer // ring image buffer
vector<Mat> buf; vector<Mat> buf;
...@@ -41,131 +40,129 @@ vector<Rect> regions; ...@@ -41,131 +40,129 @@ vector<Rect> regions;
// img - input video frame // img - input video frame
// dst - resultant motion picture // dst - resultant motion picture
// args - optional parameters // args - optional parameters
static void update_mhi( const Mat& img, Mat& dst, int diff_threshold ) static void update_mhi(const Mat& img, Mat& dst, int diff_threshold)
{ {
double timestamp = (double)clock()/CLOCKS_PER_SEC; // get current time in seconds double timestamp = (double)clock() / CLOCKS_PER_SEC; // get current time in seconds
Size size = img.size(); Size size = img.size();
int i, idx1 = last; int i, idx1 = last;
Rect comp_rect; Rect comp_rect;
double count; double count;
double angle; double angle;
Point center; Point center;
double magnitude; double magnitude;
Scalar color; Scalar color;
// allocate images at the beginning or // allocate images at the beginning or
// reallocate them if the frame size is changed // reallocate them if the frame size is changed
if( mhi.size() != size ) if (mhi.size() != size)
{ {
mhi = Mat::zeros(size, CV_32F); mhi = Mat::zeros(size, CV_32F);
zplane = Mat::zeros(size, CV_8U); zplane = Mat::zeros(size, CV_8U);
buf.resize(N); buf[0] = Mat::zeros(size, CV_8U);
for( i = 0; i < N; i++ ) buf[1] = Mat::zeros(size, CV_8U);
{ }
buf[i] = Mat::zeros(size, CV_8U);
} cvtColor(img, buf[last], COLOR_BGR2GRAY); // convert frame to grayscale
}
int idx2 = (last + 1) % 2; // index of (last - (N-1))th frame
cvtColor( img, buf[last], COLOR_BGR2GRAY ); // convert frame to grayscale last = idx2;
int idx2 = (last + 1) % N; // index of (last - (N-1))th frame Mat silh = buf[idx2];
last = idx2; absdiff(buf[idx1], buf[idx2], silh); // get difference between frames
Mat silh = buf[idx2]; threshold(silh, silh, diff_threshold, 1, THRESH_BINARY); // and threshold it
absdiff( buf[idx1], buf[idx2], silh ); // get difference between frames updateMotionHistory(silh, mhi, timestamp, MHI_DURATION); // update MHI
threshold( silh, silh, diff_threshold, 1, THRESH_BINARY ); // and threshold it // convert MHI to blue 8u image
updateMotionHistory( silh, mhi, timestamp, MHI_DURATION ); // update MHI mhi.convertTo(mask, CV_8U, 255. / MHI_DURATION, (MHI_DURATION - timestamp)*255. / MHI_DURATION);
// convert MHI to blue 8u image Mat planes[] = { mask, zplane, zplane };
mhi.convertTo( mask, CV_8U, 255./MHI_DURATION, (MHI_DURATION - timestamp)*255./MHI_DURATION ); merge(planes, 3, dst);
Mat planes[] = {mask, zplane, zplane}; // calculate motion gradient orientation and valid orientation mask
merge(planes, 3, dst); calcMotionGradient(mhi, mask, orient, MAX_TIME_DELTA, MIN_TIME_DELTA, 3);
// calculate motion gradient orientation and valid orientation mask // segment motion: get sequence of motion components
calcMotionGradient( mhi, mask, orient, MAX_TIME_DELTA, MIN_TIME_DELTA, 3 ); // segmask is marked motion components map. It is not used further
regions.clear();
// segment motion: get sequence of motion components segmentMotion(mhi, segmask, regions, timestamp, MAX_TIME_DELTA);
// segmask is marked motion components map. It is not used further
// iterate through the motion components,
segmentMotion(mhi, segmask, regions, timestamp, MAX_TIME_DELTA); // One more iteration (i == -1) corresponds to the whole image (global motion)
for (i = -1; i < (int)regions.size(); i++) {
// iterate through the motion components,
// One more iteration (i == -1) corresponds to the whole image (global motion) if (i < 0) { // case of the whole image
for( i = -1; i < (int)regions.size(); i++ ) { comp_rect = Rect(0, 0, size.width, size.height);
color = Scalar(255, 255, 255);
if( i < 0 ) { // case of the whole image magnitude = 100;
comp_rect = Rect( 0, 0, size.width, size.height ); }
color = Scalar(255,255,255); else { // i-th motion component
magnitude = 100; comp_rect = regions[i];
} if (comp_rect.width + comp_rect.height < 100) // reject very small components
else { // i-th motion component continue;
comp_rect = regions[i]; color = Scalar(0, 0, 255);
if( comp_rect.width + comp_rect.height < 100 ) // reject very small components magnitude = 30;
continue; }
color = Scalar(0,0,255);
magnitude = 30; // select component ROI
} Mat silh_roi = silh(comp_rect);
Mat mhi_roi = mhi(comp_rect);
// select component ROI Mat orient_roi = orient(comp_rect);
Mat silh_roi = silh(comp_rect); Mat mask_roi = mask(comp_rect);
Mat mhi_roi = mhi(comp_rect);
Mat orient_roi = orient(comp_rect); // calculate orientation
Mat mask_roi = mask(comp_rect); angle = calcGlobalOrientation(orient_roi, mask_roi, mhi_roi, timestamp, MHI_DURATION);
angle = 360.0 - angle; // adjust for images with top-left origin
// calculate orientation
angle = calcGlobalOrientation( orient_roi, mask_roi, mhi_roi, timestamp, MHI_DURATION); count = norm(silh_roi, NORM_L1);; // calculate number of points within silhouette ROI
angle = 360.0 - angle; // adjust for images with top-left origin
// check for the case of little motion
count = norm( silh, 0, NORM_L1, 0 ); // calculate number of points within silhouette ROI if (count < comp_rect.width*comp_rect.height * 0.05)
continue;
// check for the case of little motion
if( count < comp_rect.width*comp_rect.height * 0.05 ) // draw a clock with arrow indicating the direction
continue; center = Point((comp_rect.x + comp_rect.width / 2),
(comp_rect.y + comp_rect.height / 2));
// draw a clock with arrow indicating the direction
center = Point( (comp_rect.x + comp_rect.width/2), circle(img, center, cvRound(magnitude*1.2), color, 3, 16, 0);
(comp_rect.y + comp_rect.height/2) ); line(img, center, Point(cvRound(center.x + magnitude*cos(angle*CV_PI / 180)),
cvRound(center.y - magnitude*sin(angle*CV_PI / 180))), color, 3, 16, 0);
circle( dst, center, cvRound(magnitude*1.2), color, 3, 16, 0 ); }
line( dst, center, Point( cvRound( center.x + magnitude*cos(angle*CV_PI/180)),
cvRound( center.y - magnitude*sin(angle*CV_PI/180))), color, 3, 16, 0 );
}
} }
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
VideoCapture cap; VideoCapture cap;
help(); help();
if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0]))) if (argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
cap.open( argc == 2 ? argv[1][0] - '0' : 0 ); cap.open(argc == 2 ? argv[1][0] - '0' : 0);
else if( argc == 2 ) else if (argc == 2)
cap.open( argv[1] ); cap.open(argv[1]);
if( !cap.isOpened() ) if (!cap.isOpened())
{ {
printf("Could not initialize video capture\n"); printf("Could not initialize video capture\n");
return 0; return 0;
} }
buf.resize(2);
Mat image, motion; Mat image, motion;
for(;;) for (;;)
{ {
cap >> image; cap >> image;
if( image.empty() ) if (image.empty())
break; break;
update_mhi( image, motion, 30 ); update_mhi(image, motion, 30);
imshow( "Motion", motion ); imshow("Image", image);
imshow("Motion", motion);
if( waitKey(10) >= 0 )
break; if (waitKey(10) >= 0)
} break;
}
return 0;
return 0;
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment