OpenCV - Cropping non rectangular region from image using C++

前端 未结 2 736
暖寄归人
暖寄归人 2020-12-30 14:52

How can I crop a non rectangular region from image?

Imagine I have four points and I want to crop it, this shape wouldn\'t be a triangle somehow!

For exampl

相关标签:
2条回答
  • 2020-12-30 15:22

    You may use cv::Mat::copyTo() like this:

    cv::Mat img = cv::imread("image.jpeg");
    // note mask may be single channel, even if img is multichannel
    cv::Mat mask = cv::Mat::zeros(img.rows, img.cols, CV_8UC1);
    // fill mask with nonzero values, e.g. as Tim suggests
    // cv::fillPoly(...)
    cv::Mat result(img.size(), img.type(), cv::Scalar(255, 255, 255));
    img.copyTo(result, mask);
    
    0 讨论(0)
  • 2020-12-30 15:34

    The procedure for cropping an arbitrary quadrilateral (or any polygon for that matter) part of an image is summed us as:

    • Generate a "mask". The mask is black where you want to keep the image, and white where you don't want to keep it
    • Compute the "bitwise_and" between your input image and the mask

    So, lets assume you have an image. Throughout this I'll use an image size of 30x30 for simplicity, you can change this to suit your use case.

    cv::Mat source_image = cv::imread("filename.txt");
    

    And you have four points you want to use as the corners:

    cv::Point corners[1][4];
    corners[0][0] = Point( 10, 10 );
    corners[0][1] = Point( 20, 20 );
    corners[0][2] = Point( 30, 10 );
    corners[0][3] = Point( 20, 10 );
    const Point* corner_list[1] = { corners[0] };
    

    You can use the function cv::fillPoly to draw this shape on a mask:

    int num_points = 4;
    int num_polygons = 1;
    int line_type = 8;
    cv::Mat mask(30,30,CV_8UC3, cv::Scalar(0,0,0));
    cv::fillPoly( mask, corner_list, &num_points, num_polygons, cv::Scalar( 255, 255, 255 ),  line_type);
    

    Then simply compute the bitwise_and of the image and mask:

    cv::Mat result;
    cv::bitwise_and(source_image, mask, result);
    

    result now has the cropped image in it. If you want the edges to end up white instead of black you could instead do:

    cv::Mat result_white(30,30,CV_8UC3, cv::Scalar(255,255,255));
    cv::bitwise_and(source_image, mask, result_white, mask);
    

    In this case we use bitwise_and's mask parameter to only do the bitwise_and inside the mask. See this tutorial for more information and links to all the functions I mentioned.

    0 讨论(0)
提交回复
热议问题