c++opencvopencv-mat

OpenCV clone() and copyTo() methods don't produce Mat of same type as original?


I am new to OpenCV and following along with a book. I am trying to extract a binary image indicating component regions with the following:

cv::Mat result;
result = image.clone();
cv::watershed(image, result);

When executed, this produces the following error:

segmentation.cpp:159: error: (-215) src.type() == CV_8UC3 && dst.type() == CV_32SC1 
in function watershed

The error is certainly correct, as I verified with the type2str function in this SO post: How to find out what type of a Mat object is with Mat::type() in OpenCV

I also tried using image.copyTo(result) instead of clone(), but this produces the same error message. What am I doing wrong, and how can I copy a Mat to get the same type?

I am guessing the hacky solution would be to convert the color of result to match the color of image, as is done here: OpenCV: How to convert CV_8UC1 mat to CV_8UC3 but this seems wrong no?


Solution

  • As also mentioned here: Difference Clone CopyTo, in this context there is no difference between clone() and copyTo().

    In fact, the source code for clone() is as follows:

    inline Mat Mat::clone() const
    {
        Mat m;
        copyTo(m);
        return m;
    }
    

    copyTo however can be used in association with a mask, and in general copies data to another matrix, so can be useful for example to draw a subimage into another image.

    Regarding the code for watershed, the documentation states,

    So image (your image) and markers (your result) should not be the same.

    Before passing the image to the function, you have to roughly outline the desired regions in the image markers with positive (>0) indices. So, every region is represented as one or more connected components with the pixel values 1, 2, 3, and so on. Such markers can be retrieved from a binary mask using findContours() and drawContours() (see the watershed.cpp demo). The markers are “seeds” of the future image regions. All the other pixels in markers , whose relation to the outlined regions is not known and should be defined by the algorithm, should be set to 0’s. In the function output, each pixel in markers is set to a value of the “seed” components or to -1 at boundaries between the regions.

    Visual demonstration and usage example of the function can be found in the OpenCV samples directory (see the watershed.cpp demo).