mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
243 lines
8.4 KiB
243 lines
8.4 KiB
// Background average sample code done with averages and done with codebooks |
|
// (adapted from the OpenCV book sample) |
|
// |
|
// NOTE: To get the keyboard to work, you *have* to have one of the video windows be active |
|
// and NOT the consule window. |
|
// |
|
// Gary Bradski Oct 3, 2008. |
|
// |
|
/* *************** License:************************** |
|
Oct. 3, 2008 |
|
Right to use this code in any way you want without warrenty, support or any guarentee of it working. |
|
|
|
BOOK: It would be nice if you cited it: |
|
Learning OpenCV: Computer Vision with the OpenCV Library |
|
by Gary Bradski and Adrian Kaehler |
|
Published by O'Reilly Media, October 3, 2008 |
|
|
|
AVAILABLE AT: |
|
http://www.amazon.com/Learning-OpenCV-Computer-Vision-Library/dp/0596516134 |
|
Or: http://oreilly.com/catalog/9780596516130/ |
|
ISBN-10: 0596516134 or: ISBN-13: 978-0596516130 |
|
************************************************** */ |
|
|
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <ctype.h> |
|
|
|
#include "opencv2/core/core.hpp" |
|
#include "opencv2/video/background_segm.hpp" |
|
#include <opencv2/imgproc/imgproc_c.h> |
|
#include "opencv2/highgui/highgui.hpp" |
|
|
|
using namespace std; |
|
using namespace cv; |
|
|
|
//VARIABLES for CODEBOOK METHOD: |
|
CvBGCodeBookModel* model = 0; |
|
const int NCHANNELS = 3; |
|
bool ch[NCHANNELS]={true,true,true}; // This sets what channels should be adjusted for background bounds |
|
|
|
void help(void) |
|
{ |
|
printf("\nLearn background and find foreground using simple average and average difference learning method:\n" |
|
"Originally from the book: Learning OpenCV by O'Reilly press\n" |
|
"\nUsage:\n" |
|
"./bgfg_codebook [--nframes]=<frames number, 300 as default> \n" |
|
" [--input]=<movie filename or camera index, zero camera index as default>\n" |
|
"***Keep the focus on the video windows, NOT the consol***\n\n" |
|
"INTERACTIVE PARAMETERS:\n" |
|
"\tESC,q,Q - quit the program\n" |
|
"\th - print this help\n" |
|
"\tp - pause toggle\n" |
|
"\ts - single step\n" |
|
"\tr - run mode (single step off)\n" |
|
"=== AVG PARAMS ===\n" |
|
"\t- - bump high threshold UP by 0.25\n" |
|
"\t= - bump high threshold DOWN by 0.25\n" |
|
"\t[ - bump low threshold UP by 0.25\n" |
|
"\t] - bump low threshold DOWN by 0.25\n" |
|
"=== CODEBOOK PARAMS ===\n" |
|
"\ty,u,v- only adjust channel 0(y) or 1(u) or 2(v) respectively\n" |
|
"\ta - adjust all 3 channels at once\n" |
|
"\tb - adjust both 2 and 3 at once\n" |
|
"\ti,o - bump upper threshold up,down by 1\n" |
|
"\tk,l - bump lower threshold up,down by 1\n" |
|
"\tSPACE - reset the model\n" |
|
); |
|
} |
|
|
|
// |
|
//USAGE: ch9_background startFrameCollection# endFrameCollection# [movie filename, else from camera] |
|
//If from AVI, then optionally add HighAvg, LowAvg, HighCB_Y LowCB_Y HighCB_U LowCB_U HighCB_V LowCB_V |
|
// |
|
int main(int argc, const char** argv) |
|
{ |
|
help(); |
|
|
|
CommandLineParser parser(argc, argv); |
|
|
|
string inputName = parser.get<string>("input", "0"); |
|
int nframesToLearnBG = parser.get<int>("nframes", 300); |
|
|
|
IplImage* rawImage = 0, *yuvImage = 0; //yuvImage is for codebook method |
|
IplImage *ImaskCodeBook = 0,*ImaskCodeBookCC = 0; |
|
CvCapture* capture = 0; |
|
int c, n, nframes = 0; |
|
|
|
|
|
model = cvCreateBGCodeBookModel(); |
|
|
|
//Set color thresholds to default values |
|
model->modMin[0] = 3; |
|
model->modMin[1] = model->modMin[2] = 3; |
|
model->modMax[0] = 10; |
|
model->modMax[1] = model->modMax[2] = 10; |
|
model->cbBounds[0] = model->cbBounds[1] = model->cbBounds[2] = 10; |
|
|
|
bool pause = false; |
|
bool singlestep = false; |
|
|
|
if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') ) |
|
{ |
|
printf("Capture from camera\n"); |
|
capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' ); |
|
int c = inputName.empty() ? 0 : inputName.c_str()[0] - '0' ; |
|
if( !capture) |
|
{ |
|
printf ("Capture from CAM %d", c); |
|
printf (" didn't work\n"); |
|
} |
|
} |
|
else |
|
{ |
|
printf("Capture from file %s\n",inputName.c_str()); |
|
capture = cvCreateFileCapture(inputName.c_str()); |
|
if( !capture) |
|
{ |
|
printf ("Capture from file %s", inputName.c_str()); |
|
printf (" didn't work\n"); |
|
help(); |
|
return -1; |
|
} |
|
|
|
} |
|
|
|
//MAIN PROCESSING LOOP: |
|
for(;;) |
|
{ |
|
if( !pause ) |
|
{ |
|
rawImage = cvQueryFrame( capture ); |
|
++nframes; |
|
if(!rawImage) |
|
break; |
|
} |
|
if( singlestep ) |
|
pause = true; |
|
|
|
//First time: |
|
if( nframes == 1 && rawImage ) |
|
{ |
|
// CODEBOOK METHOD ALLOCATION |
|
yuvImage = cvCloneImage(rawImage); |
|
ImaskCodeBook = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 1 ); |
|
ImaskCodeBookCC = cvCreateImage( cvGetSize(rawImage), IPL_DEPTH_8U, 1 ); |
|
cvSet(ImaskCodeBook,cvScalar(255)); |
|
|
|
cvNamedWindow( "Raw", 1 ); |
|
cvNamedWindow( "ForegroundCodeBook",1); |
|
cvNamedWindow( "CodeBook_ConnectComp",1); |
|
} |
|
|
|
// If we've got an rawImage and are good to go: |
|
if( rawImage ) |
|
{ |
|
cvCvtColor( rawImage, yuvImage, CV_BGR2YCrCb );//YUV For codebook method |
|
//This is where we build our background model |
|
if( !pause && nframes-1 < nframesToLearnBG ) |
|
cvBGCodeBookUpdate( model, yuvImage ); |
|
|
|
if( nframes-1 == nframesToLearnBG ) |
|
cvBGCodeBookClearStale( model, model->t/2 ); |
|
|
|
//Find the foreground if any |
|
if( nframes-1 >= nframesToLearnBG ) |
|
{ |
|
// Find foreground by codebook method |
|
cvBGCodeBookDiff( model, yuvImage, ImaskCodeBook ); |
|
// This part just to visualize bounding boxes and centers if desired |
|
cvCopy(ImaskCodeBook,ImaskCodeBookCC); |
|
cvSegmentFGMask( ImaskCodeBookCC ); |
|
} |
|
//Display |
|
cvShowImage( "Raw", rawImage ); |
|
cvShowImage( "ForegroundCodeBook",ImaskCodeBook); |
|
cvShowImage( "CodeBook_ConnectComp",ImaskCodeBookCC); |
|
} |
|
|
|
// User input: |
|
c = cvWaitKey(10)&0xFF; |
|
c = tolower(c); |
|
// End processing on ESC, q or Q |
|
if(c == 27 || c == 'q') |
|
break; |
|
//Else check for user input |
|
switch( c ) |
|
{ |
|
case 'h': |
|
help(); |
|
break; |
|
case 'p': |
|
pause = !pause; |
|
break; |
|
case 's': |
|
singlestep = !singlestep; |
|
pause = false; |
|
break; |
|
case 'r': |
|
pause = false; |
|
singlestep = false; |
|
break; |
|
case ' ': |
|
cvBGCodeBookClearStale( model, 0 ); |
|
nframes = 0; |
|
break; |
|
//CODEBOOK PARAMS |
|
case 'y': case '0': |
|
case 'u': case '1': |
|
case 'v': case '2': |
|
case 'a': case '3': |
|
case 'b': |
|
ch[0] = c == 'y' || c == '0' || c == 'a' || c == '3'; |
|
ch[1] = c == 'u' || c == '1' || c == 'a' || c == '3' || c == 'b'; |
|
ch[2] = c == 'v' || c == '2' || c == 'a' || c == '3' || c == 'b'; |
|
printf("CodeBook YUV Channels active: %d, %d, %d\n", ch[0], ch[1], ch[2] ); |
|
break; |
|
case 'i': //modify max classification bounds (max bound goes higher) |
|
case 'o': //modify max classification bounds (max bound goes lower) |
|
case 'k': //modify min classification bounds (min bound goes lower) |
|
case 'l': //modify min classification bounds (min bound goes higher) |
|
{ |
|
uchar* ptr = c == 'i' || c == 'o' ? model->modMax : model->modMin; |
|
for(n=0; n<NCHANNELS; n++) |
|
{ |
|
if( ch[n] ) |
|
{ |
|
int v = ptr[n] + (c == 'i' || c == 'l' ? 1 : -1); |
|
ptr[n] = cv::saturate_cast<uchar>(v); |
|
} |
|
printf("%d,", ptr[n]); |
|
} |
|
printf(" CodeBook %s Side\n", c == 'i' || c == 'o' ? "High" : "Low" ); |
|
} |
|
break; |
|
} |
|
} |
|
|
|
cvReleaseCapture( &capture ); |
|
cvDestroyWindow( "Raw" ); |
|
cvDestroyWindow( "ForegroundCodeBook"); |
|
cvDestroyWindow( "CodeBook_ConnectComp"); |
|
return 0; |
|
}
|
|
|