2

I try to crop out a non-rectangular Mat from an image. Followed a lot of tutorials and now I implement this method for my purpose:

void crop(Mat src) {
Scalar mu, sigma;
meanStdDev(src, mu, sigma);

Canny(src, dst, mu.val[0] - sigma.val[0], mu.val[0] + sigma.val[0], 3, false);
cvtColor(dst, cdst, CV_GRAY2BGR);

HoughLinesP(dst, lines, 1, CV_PI / 2, 100, 50, 100);

Vec4i current, previous;
Point pt1, pt2, ppt1, ppt2;

for (size_t i = 1; i < lines.size(); i++) {
    current = lines[i];
    pt1 = Point(current[0], current[1]);
    pt2 = Point(current[2], current[3]);

    previous = lines[i - 1];
    ppt1 = Point(previous[0], previous[1]);
    ppt2 = Point(previous[2], previous[3]);

    vector<Point> pt;
    pt.push_back(Point(previous[2], previous[3]));                              
    pt.push_back(Point(previous[0], previous[1]));
    pt.push_back(Point(current[0], current[1]));
    pt.push_back(Point(current[2], current[3]));

    Rect roi = boundingRect(pt);    
    contourRegion = src(roi);

    Mat mask = Mat::zeros(contourRegion.size(), CV_8UC3);
    vector<Point> ROI_Poly;
    approxPolyDP(pt, ROI_Poly, 1.0, true);
    fillConvexPoly(mask, &ROI_Poly[0], ROI_Poly.size(), 255, 8, 0);

    Mat result = Mat(contourRegion.size(), CV_8UC3);
    try {
        src.copyTo(result, mask);
        imshow("result", result);
        imshow("contReg", contourRegion);
    } catch (Exception e) {}
}

After compiling I get the exception: OpenCV Error: Assertion failed (size() == mask.size()) in cv::Mat::copyTo But why? Actually I set both Mat's to contourRegion.size so it should be the same one?

As a reference, here's the original image: enter image description here

Unnamed
  • 93
  • 8

1 Answers1

-1

Initial answer was wrong. Here is the fix

In copyTo the mask is a convenience to indicate which matrix elements need to be copied, thus is has to have the same size as source src. See the documentation here. Moreover your mask has to activate all three channels. Hence, the following code should work:

int main(int argc, char **argv)
{
vector<Point> pt;
pt.push_back(cv::Point(10, 10));
pt.push_back(cv::Point(100, 20));
pt.push_back(cv::Point(200, 300));
pt.push_back(cv::Point(10, 120));
cv::Mat src = cv::imread(argv[1]);

Rect roi = boundingRect(pt);
cv::Mat contourRegion = src(roi);

Mat mask = Mat::zeros(contourRegion.size(), CV_8UC3);
vector<Point> ROI_Poly;
approxPolyDP(pt, ROI_Poly, 1.0, true);
fillConvexPoly(mask, &ROI_Poly[0], ROI_Poly.size(), 255, 8, 0);
cv::Mat f_mask = cv::Mat(src.size(), CV_8UC3);
f_mask.setTo(0);

// duplicate the mask on three channels
cv::Mat bgr_mask[3];
split(mask,bgr_mask);
cv::Mat in[] = {bgr_mask[0],bgr_mask[0],bgr_mask[0]};
cv::merge(in, 3, mask);

// copy the mask to a "full mask" of the same size as the image
mask.copyTo(f_mask(roi));

Mat result = Mat(src.size(), CV_8UC3);
try {
    src.copyTo(result, f_mask);
    imshow("result", result);
    imshow("src", src);
    cv::imshow("contReg", contourRegion);
    cv::waitKey(0);

} catch (Exception e) {}

return 0;
}

On the well known lena picture, it gives: enter image description here

To get a result with the same size as contourRegion, let use:

imshow("result", result(roi));

You have:

enter image description here

xiawi
  • 1,772
  • 4
  • 19
  • 21
  • Still get an exception, because I want the cropped image to be in the size of `contourRegion`. – Unnamed Jul 27 '17 at 14:47
  • I've edited the post to do so: let use ``result(roi)`` instead of ``result`` – xiawi Jul 28 '17 at 06:14
  • unfortunally, no. I just get a black image. – Unnamed Aug 01 '17 at 11:45
  • Can you at least reproduce my example with the ``lena.png`` image ? Else, add a link to one of your images and the exact points you want and I'll try on my side. – xiawi Aug 01 '17 at 12:24
  • I already tried with your example, but it also doesn't work.. :( Okay, I edited my question with all needed information for you. Thank you for your effort! – Unnamed Aug 01 '17 at 12:33