c++ - OpenCV:检查像素是否在边界矩形内,由等高线分隔

标签 c++ opencv

我有一个图像蒙版,其中有一些我从 Canny 那里得到的轮廓。我可以计算一个边界矩形(具有固定的给定角度)。

enter image description here

现在我需要将该矩形的左右两个区域分开。 我该怎么做?

请注意,我想处理矩形内的区域,而不是轮廓像素。

编辑

这就是我从蒙版中获取每个边界矩形的方式:

cv::Mat img_edges; // mask with contours

// Apply clustering to the edge mask from here
// http://stackoverflow.com/questions/33825249/opencv-euclidean-clustering-vs-findcontours?noredirect=1#comment55433731_33825249

// Find boundary rectangle
for (auto &contour: contours) { // Iterate over every contour cluster
  cv::Mat Srot = cv::getRotationMatrix2D(cv::Point2f(float(img_edges.cols) / 2., float(img_edges.rows) / 2.), -ILLUMINATION_ANGLE_DEG, 1.0);

  cv::transform(contour, contour, Srot);

  float min_x, min_y, max_x, max_y;

  min_x = min_y = std::numeric_limits<float>::max();
  max_x = max_y = -std::numeric_limits<float>::max();

  // Simply find edges of aligned rectangle, then rotate back by inverse of Srot
}

最佳答案

Ok let's assume I can get a connected component. How can I proceed then?

根据对问题的评论,我们同意此过程适用于轴对齐 矩形。这不会失去一般性,因为您可以旋转旋转的矩形使其与轴对齐,应用此过程,然后将点旋转回来。

从具有一些边缘的示例图像开始,例如:

enter image description here

你可以得到这样的东西,其中 blue 是被边缘分隔的边界框的左边部分,red 是右边部分:

enter image description here

这个算法可能不是最聪明的方法,但在实践中工作正常。

找到每条边的边界框后:

  1. 在给定的 roi 上创建一个矩阵 tmp,左边 1 列,右边 1 列。这将使算法对特定情况具有鲁棒性。
  2. 在新的坐标系中移动所有边界点,然后绘制到tmp中。
  3. 应用floodFill 算法找到左边的点。种子位于 tmp 的左上角。
  4. 应用floodFill 算法找到正确的点。种子是tmp的右上角。
  5. 检索两个区域中的点,转移到原始坐标系。

这里是注释代码,如果有什么不清楚的地方,请 ping 我:

#include <opencv2/opencv.hpp>
#include <vector>
using namespace std;
using namespace cv;


void separateAreas(const Rect& roi, const vector<Point>& points, vector<Point>& left, vector<Point>& right)
{
    left.clear();
    right.clear();

    // Temporary matrix
    // 0 : background pixels
    // 1 : boundary pixels
    // 2 : left pixels
    // 3 : right pixels
    Mat1b tmp(roi.height, roi.width + 2, uchar(0));

    // Shift points to roi origin, i.e tmp(0,1)
    vector<Point> pts(points);
    for (int i = 0; i < points.size(); ++i)
    {
        pts[i] -= roi.tl();

        // Draw boundary on tmp matrix
        tmp(pts[i] + Point(1,0)) = 1;
    }

    // Fill left area, seed top left point
    floodFill(tmp, Point(0, 0), Scalar(2));

    // Fill right area, seed top right point
    floodFill(tmp, Point(tmp.cols-1, 0), Scalar(3));

    // Find left and right points
    findNonZero(tmp.colRange(1, tmp.cols - 1) == 2, left);
    findNonZero(tmp.colRange(1, tmp.cols - 1) == 3, right);

    // Shift back
    for (int i = 0; i < left.size(); ++i)
    {
        left[i] += roi.tl();
    }
    for (int i = 0; i < right.size(); ++i)
    {
        right[i] += roi.tl();
    }
}


int main()
{
    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

    Mat3b res;
    cvtColor(img, res, COLOR_GRAY2BGR);

    vector<vector<Point>> contours;
    findContours(img.clone(), contours, RETR_LIST, CV_CHAIN_APPROX_NONE);

    for (int i = 0; i < contours.size(); ++i)
    {
        Rect roi = boundingRect(contours[i]);
        //rectangle(res, roi, Scalar(0,255,0));

        vector<Point> left, right;
        separateAreas(roi, contours[i], left, right);

        // Draw areas on res
        for (int j = 0; j < left.size(); ++j)
        {
            res(left[j]) = Vec3b(255,0,0); // Blue for left
        }
        for (int j = 0; j < right.size(); ++j)
        {
            res(right[j]) = Vec3b(0, 0, 255); // Red for right
        }
    }

    imshow("Image", img);
    imshow("Result", res);
    waitKey();

    return 0;
}

关于c++ - OpenCV:检查像素是否在边界矩形内,由等高线分隔,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33876282/

相关文章:

c++ - 寻找增长函数

c++ - 对象表示和运算符sizeof的定义

c++ - 如何在 CMake 中对目标依赖项进行分组?

python - 通过条件操纵像素来遮盖图像

python - 如何在不使用 OpenCV Python 中的拆分功能的情况下获取图像的单一颜色 channel ?

python - OpenCV VideoWriter自动编解码器选择

c++ - SIGABRT 和 SIGSEGV 有什么区别

c++ - std::stod 为应该有效的字符串抛出 out_of_range 错误

opencv - OpenCV中adaptiveThreshold()的GPU实现

opencv从任意区域提取路径(中心线)