first time posting, hope I put the code in the right way.
I'm trying to detect and count vehicles in a video, and so if you look at my code below I find the contours of the image after thresholding and dilating, and then I use drawContours and rectangle to draw a box around the detected contours.
I tried to put a filter on the drawContours/rectangle if statement by saying if the area of the rectangle isn't bigger than 40,000, then don't draw it.
Now if you look at the picture I attached, you'll see that there are rectangles that are drawn inside the larger rectangles, which I am not trying to do. enter image description here. These rectangles has an area less than 40,000 but they are being drawn for some reason.
I was going to use the rectangles to count the cars on the image, but if that's not the best way to do it I'm open to suggestions.
Thanks.
using namespace cv;
using namespace std;
int main()
{
VideoCapture TestVideo; //Declare video capture
Mat frame; //declare Mat as frame to grab
TestVideo.open("FroggerHighway.mp4"); //open the test video from the project directory
if (!TestVideo.isOpened()) //If its not open declare the error
{
cout << "Video did not open." << endl;
waitKey(0);
}
if (TestVideo.get(CV_CAP_PROP_FRAME_COUNT) < 1) //If the frame count is less than 1, basically an error checker
{
cout << "Video file must have at least one frame." << endl;
waitKey(0);
}
TestVideo.read(frame); //read the first frame
Mat frameGray = Mat::zeros(frame.size(), CV_8UC1); //Convert frame source to gray
cvtColor(frame, frameGray, CV_BGR2GRAY);
Mat frame2 = Mat::zeros(frameGray.size(), frameGray.type()); //Intermediate frame
Mat framediff; //Frame differencing
Mat thresh;
Mat element; //Element used for morphOps (dilation)
Mat dil;
while (TestVideo.isOpened() & waitKey(30) != 27) //while the video is open, show the frame, press escape to end video
{
absdiff(frameGray, frame2, framediff); //take absolute difference of both frames
threshold(framediff, thresh, 22, 255, CV_THRESH_BINARY); //If absdiff is greater than 22, turn it white.
namedWindow("Gray", CV_WINDOW_NORMAL); //Display gray video
imshow("Gray", frameGray);
namedWindow("FrameDiff", CV_WINDOW_NORMAL); //Show frame difference before threshold/dilation
imshow("FrameDiff", framediff);
namedWindow("Threshold", CV_WINDOW_NORMAL); //Show thresholded video
imshow("Threshold", thresh);
element = getStructuringElement(MORPH_CROSS, //morphOps dilation
Size(2 * 5 + 1, 2 * 5 + 1),
Point(5, 5));
dilate(thresh, dil, element, Point(-1, -1), 1, 1, 1);
namedWindow("Dilation", CV_WINDOW_NORMAL); //Show dilated video.
imshow("Dilation", dil);
//Apply findCountours function to draw countours and count the objects.
vector<vector<Point> > contours; //Not sure what this does but it works
findContours(dil, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE); //(outout image, hierarchy, and 2 ways to calculate it)
vector<vector<Point> > contours_poly(contours.size()); //Also not sure what this does
vector<Rect> boundRect(contours.size()); //This is used to approximate a polygon to fit the contours it calculated I think
Mat output = Mat::zeros(dil.rows, dil.cols, CV_8UC3);
int counter = 0; //Used to count # of rectangle drawn
for (int i = 0; i < contours.size(); i++)
{
approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true); //Approximates a polygon to fit the contours calculated ?
boundRect[i] = boundingRect(Mat(contours_poly[i])); //for each approximation, a bounding rectangle is sorted around the contour ?
if ((boundRect[i].x * boundRect[i].y) > 40000) //If the bounding rectangle has an area less than 40,000 then just ignore it completely
{
counter = counter + 1;
drawContours(output, contours, i, Scalar(255, 255, 255), -3); //(input, countors, contour to be drawn, color of it, thickness (negative fills image));
rectangle(output, boundRect[i].tl(), boundRect[i].br(), Scalar(0, 0, 255), 2, 8, 0); //Draws the actual rectangle around the contours
}
}
cout << "Rectangles Drawn: " << counter << endl;
namedWindow("Output", CV_WINDOW_NORMAL);
imshow("Output", output);
if (((TestVideo.get(CV_CAP_PROP_POS_FRAMES) + 1) < TestVideo.get(CV_CAP_PROP_FRAME_COUNT)) & (waitKey(30) != 27)) //Move the frame count up 1, show the frame
{
TestVideo.read(frame);
frameGray.copyTo(frame2); //MUST USE copyTo, or clone! Can't do frame2 = frameGray*
cvtColor(frame, frameGray, CV_BGR2GRAY);
}
else
{
cout << "End of Video" << endl;
waitKey(0);
break;
}
waitKey(30); //wait 30ms between showing each frame
}
return (0);
}