The program I'm working right now is almost done but I'm not very satisfy with the result. By using Canny algorithm, I managed to get a very clear of the object's contour but the program has some problem to recognize the contour and draw the contour with a red line. The program:
void setwindowSettings(){
namedWindow("Contours", CV_WINDOW_AUTOSIZE);
createTrackbar("LowerC", "Contours", &lowerC, 255, NULL);
createTrackbar("UpperC", "Contours", &upperC, 255, NULL);
}
void wait(void)
{
long t=30000000;
while(t--);
}
int main(void)
{
VideoCapture cap(0); // open the default camera
if(!cap.isOpened()) // check if we succeeded
return -1;
Mat frame,foreground,image;
double pt1, pt2, area;
Rect rect;
int i;
vector<vector<Point> > contours;
vector<vector<Point> > largest_contours;
namedWindow("Capture", CV_WINDOW_AUTOSIZE);
setwindowSettings();
while(1){
cap >> frame; // get a new frame from camera
if( frame.empty() )
break;
image=frame.clone();
cvtColor(image,foreground,CV_BGR2GRAY);
GaussianBlur(foreground,foreground,Size(9,11),0,0);
Canny(foreground,foreground,lowerC,upperC,3);
findContours(foreground,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_SIMPLE);
if(contours.empty())
continue;
double largest_area = 0;
for( i= 0; i < contours.size(); i++){ // get the largest contour
area = fabs(contourArea(contours[i]));
if(area >= largest_area){
largest_area = area;
largest_contours.clear();
largest_contours.push_back(contours[i]);
}
}
if(largest_area>=3000){ // draw the largest contour if exceeded minimum largest area
drawContours(image,largest_contours,-1,Scalar(0,0,255),2);
printf("area = %.f\n",largest_area);
}
wait();
imshow( "Capture",image );
imshow("Contours",foreground);
if(waitKey(30) >= 0) break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}
Program summary:
- Get images from camera
- Noise filtration (Convert to gray → blur → Canny)
- Find contours
- Find the largest contour and its area in the image aka the object
- Draw a red line around the object and print out the largest area
- Rinse and repeat
And the results:
Rarely I got what I want; Contour detected, red line drawn (GOOD ONE):
...and usually I got this; No contour detected, not red line (BAD ONE):
The chances to get the GOOD ONE are about 1/20
which is not very good. Also, the line of the object's contour in Contours
screen will blink when the red line appears around the object (see the GOOD ONE picture).
I'm using one of my object (A small black square box) for this question but please note that the main objective of this object detection program is to detect the object regardless of its shape or its color.
So my questions are:
- Why I still get the BAD ONES despite the contour is as clear as day?
- Can anyone share a better idea on how to improve the contour detection? (i.e better blur algorithm)
- How to avoid the contour's line from blinking when the red line is drawn around the object?
EDIT: I just discovered that contour's line blinking is not because of the red line drawn around it (either with drawContours
or line
function) but it happens after the largest contour is detected by findContours
function and calculated as the largest contour.
For question about no. 3 click HERE. VIDEO HERE, CLICK IT!!!
Thanks in advance.
PS: I'm using OpenCV 2.4.3 on Ms Visual C++ 2010 Exp.