【问题标题】:Crop Triangle with opencv c++用opencv c ++裁剪三角形
【发布时间】:2016-02-11 01:07:36
【问题描述】:

用户,

我想裁剪图像上的三角形并使用 opencv c++ 在另一个窗口中显示它。我知道所有三个坐标。 谁能帮我?我在网上没有找到任何关于“三角形裁剪”的答案。谢谢!

编辑:这里的问题是我不能使用 ROI 来裁剪三角形。我必须只复制没有任何背景或其他东西的三角形。是否可以通过知道三角形 [p1(302,179), p2(329,178), p3(315,205)] 的坐标来创建自己的 ROI?

【问题讨论】:

    标签: c++ opencv image-processing 2d mask


    【解决方案1】:
    cv::Mat inputImage = cv::imread("input.png");
    if (inputImage.channels() > 1)
    {
        cv::cvtColor(inputImage, inputImage, CV_RGB2GRAY);
    }
    
    // replace these values with your actual coordinates
    // I found these by first saving your provided image, then 
    // using Microsoft Paint
    int x0 = 242;
    int y0 = 164;
    int x1 = 314;
    int y1 = 38;
    int x2 = 387;
    int y2 = 164;
    
    // then create a line masking using these three points
    cv::Mat lineMask = cv::Mat::zeros(inputImage.size(), inputImage.type());
    cv::line(lineMask, cv::Point(x0, y0), cv::Point(x1, y1), cv::Scalar(255, 255, 0), 1, 8, 0);
    cv::line(lineMask, cv::Point(x0, y0), cv::Point(x2, y2), cv::Scalar(255, 255, 0), 1, 8, 0);
    cv::line(lineMask, cv::Point(x1, y1), cv::Point(x2, y2), cv::Scalar(255, 255, 0), 1, 8, 0);
    
    // perform contour detection on your line mask
    cv::vector<cv::vector<cv::Point>> contours;
    cv::vector<cv::Vec4i> hierarchy;
    cv::findContours(lineMask, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
    
    // calculate the distance to the contour
    cv::Mat raw_dist(lineMask.size(), CV_32FC1);
    
    for (int i = 0; i < lineMask.rows; i++)
    {
        for (int j = 0; j < lineMask.cols; j++)
        {
            raw_dist.at<float>(i, j) = cv::pointPolygonTest(contours[0], cv::Point2f(j, i), true);
        }
    }
    
    double minVal; double maxVal;
    cv::minMaxLoc(raw_dist, &minVal, &maxVal, 0, 0, cv::Mat());
    minVal = std::abs(minVal);
    maxVal = std::abs(maxVal);
    
    // depicting the distances graphically
    cv::Mat mask = cv::Mat::zeros(inputImage.size(), CV_8UC1);
    
    for (int i = 0; i < mask.rows; i++)
    {
        for (int j = 0; j < mask.cols; j++)
        {
            if (raw_dist.at<float>(i, j) < 0)
            {
                mask.at<uchar>(i, j) = static_cast<uchar>(0);
                continue;
            }           
            mask.at<uchar>(i, j) = static_cast<uchar>(255);
        }
    }
    
    // inverse the input image
    cv::Mat invInput;   
    cv::bitwise_not(inputImage, invInput);
    
    // then get only the region of your triangle
    cv::Mat outputImage;
    invInput.copyTo(outputImage, mask);
    cv::bitwise_not(outputImage, outputImage);
    
    // display for debugging purpose
    cv::imshow("inputImage", inputImage);
    cv::imshow("lineMask", lineMask);
    cv::imshow("mask", mask);
    cv::imshow("outputImage", outputImage);
    cv::waitKey();  
    

    这是你的inputImage

    这是你的lineMask

    这是您创建的二进制文件mask

    这是你最后的outputImage

    参考资料:

    OpenCV draw line

    OpenCV findContours

    Point Polygon Test

    【讨论】:

    • 感谢它帮了大忙!
    【解决方案2】:

    您可以使用下面的代码所示的掩码来做到这一点

    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include <iostream>
    
    using namespace cv;
    using namespace std;
    
    int main( int, char** argv )
    {
        Mat src = imread( argv[1] );
        Mat gray;
    
        cvtColor(src, gray, COLOR_BGR2GRAY );
        gray = gray < 127;
    
        vector<vector<Point> > contours;
    
        findContours(gray, contours,
                     RETR_EXTERNAL,
                     CHAIN_APPROX_SIMPLE);
    
        for( size_t i = 0; i< contours.size(); i++ )
        {
            Rect rect = boundingRect(contours[i]);
            Mat mask = gray(rect);
            Mat srcROI = src(rect);
            srcROI.setTo(Scalar(0,0,255),mask);
            imshow("srcROI",srcROI);
            waitKey();
        }
    
        imshow( "result", src );
    
        waitKey(0);
        return(0);
    }
    

    编辑:根据问题的变化我建议下面的测试代码

    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    
    using namespace cv;
    using namespace std;
    
    int main( int, char** argv )
    {
        Mat src = imread("lena.jpg");
        vector<Point> points;
        points.push_back( Point(200,200));
        points.push_back( Point(370,370));
        points.push_back( Point(220,410));
    
        Mat mask = Mat::zeros( src.size(), CV_8UC1 );
        fillConvexPoly( mask, points, Scalar( 255 ));
    
        Rect rect = boundingRect( points );
        Mat roi = src( rect ).clone();
        mask = mask( rect ).clone();
    
        rect.x = rect.x - 180;
        rect.y = rect.y - 180;
    
        Mat srcROI = src( rect );
        roi.copyTo( srcROI, mask );
    
        imshow( "result", src );
    
        waitKey(0);
        return(0);
    }
    

    【讨论】:

    • 我在你的代码的 for 循环的第二轮中得到一个异常,所以我看不到结果窗口:/ [CropTriangleOpenCv.exe 中 0x013096C8 (opencv_improc231.dll) 处的未处理异常:0xC0000005:访问冲突读取位置 0xBAADF011]。
    • 我现在不在电脑旁。我很快就会提供一个简单的代码,但是你的 OpenCV 版本是什么?
    • 请对我的回答投反对票的人解释一下他/她投反对票的原因?
    • OpenCV 2.31 谢谢!
    【解决方案3】:
    • 正如你所说,你知道三角形的坐标,使用下面的代码你可以找到三角形。

      Mat image = imread("imagePath");
      bitwise_not(image, image);
      Mat grayImage;
      cv::cvtColor(image, grayImage, CV_RGB2GRAY);
      cv::vector<cv::vector<cv::Point> > contours;
      cv::vector<cv::Vec4i> hierarchy;
      cv::findContours(grayImage, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0));
      Mat contourMat(grayImage.size(), grayImage.type(), Scalar(255));
      for(int i = 0; i < contours.size(); i++)
      {
          if(contours[i].data()->x == 314 && contours[i].data()->y == 37)
              drawContours(contourMat, contours, i, Scalar(0), CV_FILLED, 8, hierarchy);
      }
      imshow("WindowName", contourMat);
      
    • 希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2013-04-02
      • 1970-01-01
      • 1970-01-01
      • 2018-08-22
      • 2015-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-03
      相关资源
      最近更新 更多