Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

calling findcontours throws an exception...

Hi,

I'm new to opencv, trying my hand at image tracking using OpenCV 3.0 and Visual Studio version 12.0.31101.00 Update 4 (2013). I am using code from this tutorial:

https://youtu.be/X6rPdRZzgjg (I'd link directly to the code in dropbox but youtube is playing games w/the URLs.)

...which is (likely) intended for an older version of OpenCV & Visual Studio. But, after altering the project's variables and the program's include and using lines, the code compiles and successfully calls many OpenCV methods. Including "cvtColor", "absdiff", "threshold" and "blur".

Unfortunately, the program throws an exception when "findContours" is called. When checking the "findContours" arguments, I see where the 3rd variable (usually referred to as "hierarchy") is abnormally large (19 decimal digits long) in size.

After reading some posts, I tried switching from calling the "threshold" method to calling the "Canny" method when preparing the image for the "findContours" method. But the program still threw the exception. I have even tried completely different videos. The calls to the other methods worked (pressing "d" while the program runs displays the intermediate images verifying this). But the "findContours" method (pressing "t" while the program runs allows calls to the "findContours" method) still threw the exception.

It is not a very long program. I'll try and insert my version of code here:

(Wow, including code using this web/interface/editor is really difficult! The editor keeps breaking it up with (kind-of) normal text.)

(Sorry, it doesn't appear I can drop in all the code w/o this editor chopping it up. I'll try to drop in only the important bits then.)

This is the bit of code that prepare the image for the call to the "findContours" method. The calls to "imshow" verify these methods are working as expected. Notice I tried to replace a call to the "threshold" method with a call to the "Canny" method as an attempt to avoid the exception when calling the "findContours" method. The call to the "findContours" method is inside the "searchForMovement" method called at the end of this section of code:

        while (capture.get(CV_CAP_PROP_POS_FRAMES)<capture.get(CV_CAP_PROP_FRAME_COUNT) - 1){

        //read first frame
        capture.read(frame1);
        //convert frame1 to gray scale for frame differencing
        cv::cvtColor(frame1, grayImage1, COLOR_BGR2GRAY);
        //copy second frame
        capture.read(frame2);
        //convert frame2 to gray scale for frame differencing
        cv::cvtColor(frame2, grayImage2, COLOR_BGR2GRAY);
        //perform frame differencing with the sequential images. This will output an "intensity image"
        //do not confuse this with a threshold image, we will need to perform thresholding afterwards.
        cv::absdiff(grayImage1, grayImage2, differenceImage);
        //threshold intensity image at a given sensitivity value
        cv::threshold(differenceImage, thresholdImage, SENSITIVITY_VALUE, 255, THRESH_BINARY);
        if (debugMode == true){
            //show the difference image and threshold image
            cv::imshow("Difference Image", differenceImage);
            cv::imshow("Threshold Image", thresholdImage);
        }
        else{
            //if not in debug mode, destroy the windows so we don't see them anymore
            cv::destroyWindow("Difference Image");
            cv::destroyWindow("Threshold Image");
        }
        //blur the image to get rid of the noise. This will output an intensity image
        cv::blur(thresholdImage, thresholdImage, cv::Size(BLUR_SIZE, BLUR_SIZE));
        //threshold again to obtain binary image from blur output
        // cv::threshold(thresholdImage, thresholdImage, SENSITIVITY_VALUE, 255, THRESH_BINARY);
        cv::Canny(thresholdImage, thresholdImage, SENSITIVITY_VALUE, 255, 3);
        if (debugMode == true){
            //show the threshold image after it's been "blurred"

            imshow("Final Threshold Image", thresholdImage);

        }
        else {
            //if not in debug mode, destroy the windows so we don't see them anymore
            cv::destroyWindow("Final Threshold Image");
        }

        //if tracking enabled, search for contours in our thresholded image
        if (trackingEnabled){

            searchForMovement(thresholdImage, frame1);
        }

Here is the "searchForMovement" method containing the call to the "findContours" method where the exception is thrown. You can see where I tried to call the "findContours" method several different ways:

void searchForMovement(Mat thresholdImage, Mat &cameraFeed){
//notice how we use the '&' operator for objectDetected and cameraFeed. This is because we wish
//to take the values passed into the function and manipulate them, rather than just working with a copy.
//eg. we draw to the cameraFeed to be displayed in the main() function.
bool objectDetected = false;
Mat temp;
thresholdImage.copyTo(temp);
//these two vectors needed for output of findContours
vector< vector<Point> > contours;
vector<Vec4i> hierarchy;
//find contours of filtered image using openCV findContours function
// findContours(temp,contours,hierarchy,CV_RETR_CCOMP,CV_CHAIN_APPROX_SIMPLE );// retrieves all contours
findContours(temp, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);// retrieves external contours
// findContours(temp, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);// retrieves external contours
// findContours(temp, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
//if contours vector is not empty, we have found some objects
if (contours.size()>0)objectDetected = true;
else objectDetected = false;

Any ideas as to what to try next would be appreciated.

-thanks