【问题标题】:OpenCV C++ - Rectangle detection which has irregular sideOpenCV C++ - 具有不规则边的矩形检测
【发布时间】:2019-09-23 03:13:00
【问题描述】:

嗨..我遇到了矩形检测的问题,它有不规则的边(不是直的),如上图。实际上使用 houghline 方法可以通过一些参数配置来检测矩形上的线条。计算相交并得到4个角后,我可以将其旋转到正常位置。

但是如果我用另一个矩形(不同大小并且仍然有不规则边)更改图像,我需要重新配置参数。这是因为四边都没有检测到线,而且线可以多于4。

除了houghline还有其他更简单(不需要重新配置/困难配置)的方法吗?

【问题讨论】:

  • 也许您可以考虑膨胀和侵蚀序列来创建一个更“规则”的矩形,以便使用轮廓方法获取角坐标。然后你可以旋转原来的矩形。
  • OpenCV 示例中的 squares.cpp 示例可能会对您有所帮助。使用简单的阈值处理,提取外部轮廓,然后对这些轮廓进行多边形逼近,如示例所示。
  • 谢谢你们帮助我..感谢您的回答..:D

标签: c++ opencv detection


【解决方案1】:

这种方法是计算包含所有矩形像素的旋转矩形。

也许您可以将其与 vasanth 的答案结合起来,因此您可以先近似多项式以获得规则边框,然后使用 cv::minAreaRect 提取旋转矩形

这是我的代码:

int main()
{
    cv::Mat input = cv::imread("../inputData/RotatedRect.png");

    // convert to grayscale (you could load as grayscale instead)
    cv::Mat gray;
    cv::cvtColor(input,gray, CV_BGR2GRAY);

    // compute mask (you could use a simple threshold if the image is always as good as the one you provided)
    cv::Mat mask;
    cv::threshold(gray, mask, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);

    // find contours (if always so easy to segment as your image, you could just add the black/rect pixels to a vector)
    std::vector<std::vector<cv::Point>> contours;
    std::vector<cv::Vec4i> hierarchy;
    cv::findContours(mask,contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);

    /// Draw contours and find biggest contour (if there are other contours in the image, we assume the biggest one is the desired rect)
    // drawing here is only for demonstration!
    int biggestContourIdx = -1;
    float biggestContourArea = 0;
    cv::Mat drawing = cv::Mat::zeros( mask.size(), CV_8UC3 );
    for( int i = 0; i< contours.size(); i++ )
    {
        cv::Scalar color = cv::Scalar(0, 100, 0);
        drawContours( drawing, contours, i, color, 1, 8, hierarchy, 0, cv::Point() );

        float ctArea= cv::contourArea(contours[i]);
        if(ctArea > biggestContourArea)
        {
            biggestContourArea = ctArea;
            biggestContourIdx = i;
        }
    }

    // if no contour found
    if(biggestContourIdx < 0)
    {
        std::cout << "no contour found" << std::endl;
        return 1;
    }

    // compute the rotated bounding rect of the biggest contour! (this is the part that does what you want/need)
    cv::RotatedRect boundingBox = cv::minAreaRect(contours[biggestContourIdx]);
    // one thing to remark: this will compute the OUTER boundary box, so maybe you have to erode/dilate if you want something between the ragged lines



    // draw the rotated rect
    cv::Point2f corners[4];
    boundingBox.points(corners);
    cv::line(drawing, corners[0], corners[1], cv::Scalar(255,255,255));
    cv::line(drawing, corners[1], corners[2], cv::Scalar(255,255,255));
    cv::line(drawing, corners[2], corners[3], cv::Scalar(255,255,255));
    cv::line(drawing, corners[3], corners[0], cv::Scalar(255,255,255));

    // display
    cv::imshow("input", input);
    cv::imshow("drawing", drawing);
    cv::waitKey(0);

    cv::imwrite("rotatedRect.png",drawing);

    return 0;
}

给出这个结果:

【讨论】:

  • 谢谢你 Micka.. 这个方法对我有用.. 也感谢代码中的解释
【解决方案2】:

试试这个:

1.在图片上运行findCountours

2.应用approxPolyDP 将轮廓近似为矩形。轮廓边会更加规则。

3.使用moments 和/或几何分割矩形轮廓。

【讨论】:

  • 谢谢 Vasanth,感谢您的回答,现在我知道除了 houghline 之外的其他方法
【解决方案3】:

使用初等几何, 你需要找到坐标在哪里

  • x 坐标最小的黑色像素位置
  • x 坐标最大的黑色像素位置
  • y 坐标最小的黑色像素位置
  • y 坐标最大的黑色像素位置

这 4 个点将成为矩形的边缘。

【讨论】:

  • 感谢 bikz05,感谢您的回答,+1 简单
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-06
  • 1970-01-01
  • 1970-01-01
  • 2018-09-10
  • 1970-01-01
相关资源
最近更新 更多