Reputation: 932
Trying to recreate a basic change detection program I got from a great blog done by Adrian Rosebrock (if looking to get into python and OpenCV go here). The code was designed in python and I am trying to convert it to C++. You can find the blog post here. My struggle is with the absdiff(firsFrame, gray, imageDifference)
as every iteration of the loop has firstFrame and gray being equal. I think the problem is either where I initialize firstFrame = gray
but I did a cout
check to see how many times it is hit so not sure. Here is code:
int min_area = 500; //min area of motion detectable
//get camera operational and make sure working correctly
VideoCapture camera(0);
if(!camera.isOpened()){
cout << "cannot open camera" << endl;
return(1);
}
Mat firstFrame, gray, imageDifference, thresh;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
while(true){
Mat frame;
camera.read(frame);
if(frame.empty()){
cout << "frame was not captured" << endl;
return(2);
}
//pre processing
//resize(frame, frame, Size (1200,900));
cvtColor(frame, gray, COLOR_BGR2GRAY);
GaussianBlur(gray, gray, Size( 21, 21 ), 0, 0 );
//initrialize first frame if necessary
if(firstFrame.empty()){
cout << "hit" << endl;
firstFrame = gray;
continue;
}
//get difference
absdiff(firstFrame, gray, imageDifference);
threshold(imageDifference, thresh, 25, 255, THRESH_BINARY);
//fill in holes
dilate(thresh, thresh, Mat(), Point(-1, -1), 2, 1, 1);
findContours(thresh, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
//loop over contours
for(int i = 0; i < contours.size(); i++){
//get the boundboxes and save the ROI as an Image
if (contourArea(contours[i]) < min_area){
continue;
}
Rect boundRect = boundingRect( Mat(contours[i]));
rectangle( frame, boundRect.tl(), boundRect.br(), (0,255,0), 1, 8, 0 );
}
//draw everything
imshow("Security feed", frame);
imshow("Thresh", thresh);
imshow("Difference", imageDifference);
if (waitKey(30) >= 0)
break;
}
camera.release();
destroyAllWindows();
return(0);
Upvotes: 0
Views: 4117
Reputation: 18331
Some to be improved:
firstFrame = gray
=> gray.copyTo(firstFrame)
you define firstFrame
and gray
at the same line, then after do firstFrame = gray
, they share same data memory. So every time they are the same.
Skip some frames.
As the camera just starts, so the first frame is not that stable, you should skip some frames(like 10 frames).
cv::Scalar <==> tuple
In C++:
cv::Scalar(b,g,r) <==> tuple(b,g,r)
(b,g,r) ==> r
Modified code:
int cnt = 0;
while(true) {
Mat frame;
camera.read(frame);
if(frame.empty()) {
cout << "frame was not captured" << endl;
return(2);
}
//pre processing
//resize(frame, frame, Size (1200,900));
cvtColor(frame, gray, COLOR_BGR2GRAY);
GaussianBlur(gray, gray, Size( 21, 21 ), 0, 0 );
//initrialize first frame if necessary
if(firstFrame.empty()) {
if(cnt<10){
++cnt;
}else{
cout << "hit" << endl;
gray.copyTo(firstFrame);
}
continue;
}
// ...
/// cv::Scalar(b,g,r) <==> tuple(b,g,r)
/// (b,g,r) ==> r
rectangle( frame, boundRect.tl(), boundRect.br(), Scalar(0,255,0), 1, 8, 0 );
// ...
}
Upvotes: 4