Ask Your Question

# Issue Masking Input Image to findContours [closed]

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 ...

edit retag reopen merge delete

## Comments

1

I think your creation of black could be the problem. Try CV_8UC1 instead of CV_8U. Then it is a 1 channel image. This is a requirement of findContours() and could explain the "unsupported array type error".

Instead of check with assert(black.size() == canny_output.size()); and assert(black.type() == canny_output.type()); you can do black.create(canny_output.size(), canny_output.type(), 0);

Consider that copyTo() does not do a deep copy in cases the target image is not allocated, but only copies the header.

Another problem you should check is, if it is working when you copy the valid areas from canny_ouput to black and using black in the findContours() function. I'm not sure what happenes when you copy nothing from black to canny_output

( 2015-07-25 14:20:10 -0600 )edit

Hi Matman, thank you for your reply! As far as I'm aware CV_8UC1 and CV_8U evaluate to the same type. In accordance with that knowledge changing the type did not help. black.create() also yielded the same errors. Anyway, I came up with a simpler code that now at least runs, but gives me a black image every iteration, regardless of the contents of mask. I now simply use setTo() to directly change the canny_output to avoid errors while copying. I'll attach the revised code to my initial post.

( 2015-07-27 03:35:26 -0600 )edit

## 1 answer

Sort by » oldest newest most voted

Turns out that the constructor of Mat does not except numbers as arguments to the init_valueparameter, but requires use of Scalar()in order to work. As a consequence mask and black both had data nullpointers.

more

## Comments

ahh, common pitfall, i did not see it either. at least, it was fixed in opencv3.0 !

( 2015-07-27 11:23:59 -0600 )edit

Official site

GitHub

Wiki

Documentation

## Stats

Asked: 2015-07-25 09:15:49 -0600

Seen: 1,667 times

Last updated: Jul 27 '15