Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Issue Masking Input Image to findContours

Hi,

I am currently implementing obstacle detection using the camera output of a robot's floor-directed video camera. Using canny edge detection as preprocessing I am able to efficiently find contours using findContours. Whenever I find sufficient amounts of contours I send out an obstacle warning. So far so good - code compiles and works using laptop camera. The last remaining issue is that the robot films its own body using the camera (i.e. its base and wheels) and I obviously do not consider them to be obstacles and would hence like to exclude them from contour finding. Seeing that neither canny nor findContours provide masking functionality, I decided to mask the input myself. So what I am currently doing is performing canny edge on the whole image and then overwriting the area to be ignored with zeroes (i.e. color black), before I pass the image to find contours. I do this using copyTo(). However findContours throws an "Unrecognized or unsupported array type in function cvGetMat" exception if my mask indicates to overwrite nothing, and copyTo() an "EXC_BAD_ACCESS" exception if my mask indicates to overwrite everything. I am unable to trace this error, as I assert type and size equality before using copyTo() and input and mask are static and therefore never empty. I would highly appreciate some feedback. I am guessing I am making a very fundamental mistake, as copyTo() should copy nothing given the code below (with the empty mask) and therefore the code should run just as before.

Any feedback is appreciated.

Warm regards, Mark

int detectFloor(VideoCapture floorCam){

if( !floorCam.isOpened() ){
    cout << "Could not initialize capturing...\n";
    return 0;
}

Mat frame, image, gray, canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
RNG rng(12345);
Mat black(720,1280,CV_8U,0); // The black pixels I am copying later on
Mat mask(720,1280,CV_8U,0); // When to copy them (currently never) - I need to actually build the real mask

// Sensitivity of the contour detection
int thresh = 100;
// Sensitivity of obstacle detection i.e. number of contours needed to raise warning
int critical = 10;

for(;;){
    // Capture a 1280*720 frame
    floorCam >> frame;
    if( frame.empty() )
        break;
    frame.copyTo(image);

    // Convert image to gray for better accuracy during contour detection
    cvtColor(image, gray, COLOR_BGR2GRAY);
    // Blur image to remove disturbances
    blur( gray, gray, Size(3,3) );

    // Detect edges using canny to preprocess image for contour detection
    Canny( gray, canny_output, thresh, thresh*2, 3 );
    // Mask robot from canny_output by filling that area of the image with black
    // That way robot contours will be ignored during detection
    assert(black.size() == canny_output.size());
    assert(black.type() == canny_output.type());
    black.copyTo(canny_output, mask);
    // Find contours i.e. curves that join continuous points having same color or intensity
    findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
    // Contours indicate presence of alien entities
    // Therefore check if sufficient numbers of contours are present to raise alarm
    if (contours.size() > critical)
        cout << "Warning! Obstacle detected - " << contours.size() << " contours found." << endl;

}
return(0);

}

Issue Masking Input Image to findContours

Hi,

I am currently implementing obstacle detection using the camera output of a robot's floor-directed video camera. Using canny edge detection as preprocessing I am able to efficiently find contours using findContours. Whenever I find sufficient amounts of contours I send out an obstacle warning. So far so good - code compiles and works using laptop camera. The last remaining issue is that the robot films its own body using the camera (i.e. its base and wheels) and I obviously do not consider them to be obstacles and would hence like to exclude them from contour finding. Seeing that neither canny nor findContours provide masking functionality, I decided to mask the input myself. So what I am currently doing is performing canny edge on the whole image and then overwriting the area to be ignored with zeroes (i.e. color black), before I pass the image to find contours. I do this using copyTo(). However findContours throws an "Unrecognized or unsupported array type in function cvGetMat" exception if my mask indicates to overwrite nothing, and copyTo() an "EXC_BAD_ACCESS" exception if my mask indicates to overwrite everything. I am unable to trace this error, as I assert type and size equality before using copyTo() and input and mask are static and therefore never empty. I would highly appreciate some feedback. I am guessing I am making a very fundamental mistake, as copyTo() should copy nothing given the code below (with the empty mask) and therefore the code should run just as before.

Any feedback is appreciated.

Warm regards, regards,
Mark

int detectFloor(VideoCapture floorCam){

if( !floorCam.isOpened() ){
    cout << "Could not initialize capturing...\n";
    return 0;
}

Mat frame, image, gray, canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
RNG rng(12345);
Mat black(720,1280,CV_8U,0); // The black pixels I am copying later on
Mat mask(720,1280,CV_8U,0); // When to copy them (currently never) - I need to actually build the real mask

// Sensitivity of the contour detection
int thresh = 100;
// Sensitivity of obstacle detection i.e. number of contours needed to raise warning
int critical = 10;

for(;;){
    // Capture a 1280*720 frame
    floorCam >> frame;
    if( frame.empty() )
        break;
    frame.copyTo(image);

    // Convert image to gray for better accuracy during contour detection
    cvtColor(image, gray, COLOR_BGR2GRAY);
    // Blur image to remove disturbances
    blur( gray, gray, Size(3,3) );

    // Detect edges using canny to preprocess image for contour detection
    Canny( gray, canny_output, thresh, thresh*2, 3 );
    // Mask robot from canny_output by filling that area of the image with black
    // That way robot contours will be ignored during detection
    assert(black.size() == canny_output.size());
    assert(black.type() == canny_output.type());
    black.copyTo(canny_output, mask);
    // Find contours i.e. curves that join continuous points having same color or intensity
    findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
    // Contours indicate presence of alien entities
    // Therefore check if sufficient numbers of contours are present to raise alarm
    if (contours.size() > critical)
        cout << "Warning! Obstacle detected - " << contours.size() << " contours found." << endl;

}
return(0);

}

Issue Masking Input Image to findContours

Hi,

I am currently implementing obstacle detection using the camera output of a robot's floor-directed video camera. Using canny edge detection as preprocessing I am able to efficiently find contours using findContours. Whenever I find sufficient amounts of contours I send out an obstacle warning. So far so good - code compiles and works using laptop camera. The last remaining issue is that the robot films its own body using the camera (i.e. its base and wheels) and I obviously do not consider them to be obstacles and would hence like to exclude them from contour finding. Seeing that neither canny nor findContours provide masking functionality, I decided to mask the input myself. So what I am currently doing is performing canny edge on the whole image and then overwriting the area to be ignored with zeroes (i.e. color black), before I pass the image to find contours. I do this using copyTo(). However findContours throws an "Unrecognized or unsupported array type in function cvGetMat" exception if my mask indicates to overwrite nothing, and copyTo() an "EXC_BAD_ACCESS" exception if my mask indicates to overwrite everything. I am unable to trace this error, as I assert type and size equality before using copyTo() and input and mask are static and therefore never empty. I would highly appreciate some feedback. I am guessing I am making a very fundamental mistake, as copyTo() should copy nothing given the code below (with the empty mask) and therefore the code should run just as before.

Any feedback is appreciated.

Warm regards,
Mark

int detectFloor(VideoCapture floorCam){

if( !floorCam.isOpened() ){
    cout << "Could not initialize capturing...\n";
    return 0;
}

Mat frame, image, gray, canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
RNG rng(12345);
Mat black(720,1280,CV_8U,0); // The black pixels I am copying later on
Mat mask(720,1280,CV_8U,0); // When to copy them (currently never) - I need to actually build the real mask

// Sensitivity of the contour detection
int thresh = 100;
// Sensitivity of obstacle detection i.e. number of contours needed to raise warning
int critical = 10;

for(;;){
    // Capture a 1280*720 frame
    floorCam >> frame;
    if( frame.empty() )
        break;
    frame.copyTo(image);

    // Convert image to gray for better accuracy during contour detection
    cvtColor(image, gray, COLOR_BGR2GRAY);
    // Blur image to remove disturbances
    blur( gray, gray, Size(3,3) );

    // Detect edges using canny to preprocess image for contour detection
    Canny( gray, canny_output, thresh, thresh*2, 3 );
    // Mask robot from canny_output by filling that area of the image with black
    // That way robot contours will be ignored during detection
    assert(black.size() == canny_output.size());
    assert(black.type() == canny_output.type());
    black.copyTo(canny_output, mask);
    // Find contours i.e. curves that join continuous points having same color or intensity
    findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
    // Contours indicate presence of alien entities
    // Therefore check if sufficient numbers of contours are present to raise alarm
    if (contours.size() > critical)
        cout << "Warning! Obstacle detected - " << contours.size() << " contours found." << endl;
 }
return(0);
}

}EDIT: Alternative approach using setTo that eliminates the need for matrix black. The issue at hand is that canny_output is always filled with zeroes regardless of the contents of mask:

int detectFloor(VideoCapture floorCam){

if( !floorCam.isOpened() ){
    cout << "Could not initialize capturing...\n";
    return 0;
}

Mat frame, image, gray, canny_output;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
RNG rng(12345);
Mat mask(720,1280,CV_8U,0);

// Sensitivity of the contour detection
int thresh = 100;
// Sensitivity of obstacle detection i.e. number of contours needed to raise warning
int critical = 10;

for(;;){
    // Capture a 1280*720 frame
    floorCam >> frame;
    if( frame.empty() )
        break;
    frame.copyTo(image);

    // Convert image to gray for better accuracy during contour detection
    cvtColor(image, gray, COLOR_BGR2GRAY);
    // Blur image to remove disturbances
    blur( gray, gray, Size(3,3) );

    // Detect edges using canny to preprocess image for contour detection
    Canny( gray, canny_output, thresh, thresh*2, 3 );
    // Mask robot from canny_output by filling that area of the image with black
    // That way robot contours will be ignored during detection
    canny_output.setTo(0, mask);
    // Find contours i.e. curves that join continuous points having same color or intensity
    findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
    // Contours indicate presence of alien entities
    // Therefore check if sufficient numbers of contours are present to raise alarm
    if (contours.size() > critical)
        cout << "Warning! Obstacle detected - " << contours.size() << " contours found." << endl;
}
return(0);
}