【问题标题】:Why OpenCV has no specialize data structure for region?为什么 OpenCV 没有专门针对区域的数据结构?
【发布时间】:2016-04-29 09:45:25
【问题描述】:

我已经使用 MVTec 的 Halcon 图像处理库半年和 OpenCV 1 年。

1.我发现 Halcon 远胜过 OpenCV 的一件事是 OpenCV 没有专门针对区域的数据结构。

如果我只想在大空间中存储一个小区域,这会浪费很多。 OpenCV 不应该对 Mat Class 以外的区域有一些专门的数据结构。

2。第二个,是前一个的结果,OpenCV 遍历区域很尴尬。

想象一下,在做阈值之后我有 10 个连接的区域块,我想遍历这 10 个块来处理每个块。据我所知,我必须首先使用 findContours 获取每个区域的所有轮廓,然后使用 drawContour 获取该区域。那么我可以说这些区域是由轮廓数据存储的,并且每次我想取回该区域时都必须调用 drawContours 吗?

Mat myImage = imread("Path_To_Source_Image");
threshold(myImage, region, 128, 1, THRESH_BINARY);
vector<vector<Point>> contours;
findContours(region, contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
for (int i = 0; i < contours.size, i++){
    Mat oneBlock(myImage.size(), CV_8U); 
    drawContours(oneBlock, contours, i, Scalar(255), -1);
        // Now I finally get my region

        //  ***************************************
        //
        //   Do my image procesing for that region
        //
        //  ***************************************
    }

【问题讨论】:

  • 很遗憾我没有 Halcon 经验。你能更好地解释一下什么是区域吗?它们是某种子图像还是更像稀疏像素位置?区域可以进行什么样的处理?根据我的理解/直觉,子图像和蒙版的组合可能是区域。
  • "并且每次我想取回该区域时,我都必须调用 drawContours 吗?" - 为什么不只记住 drawContours 的结果?

标签: opencv structure space


【解决方案1】:

表示区域的常用方法是使用包含区域索引的Mat1i(又名Mat,类型为CV_32S),即labels

然后您可以通过以下方式访问第 i 个区域:Mat1b region_mask = (labels == i);

OpenCV findConturs 和drawContours 创建labels 图像:

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

int main()
{
    // Read image from file 
    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

    Mat1b region;
    threshold(img, region, 200, 255, THRESH_BINARY);

    vector<vector<Point>> contours;
    findContours(region.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);

    Mat1i labels(img.rows, img.cols, int(0));
    int n_labels = contours.size();

    for (int i = 0; i < contours.size(); ++i)
    {
        drawContours(labels, contours, i, Scalar(i + 1), CV_FILLED); // Note the +1, since 0 is the background
    }

    // Now you can get your regiones as:

    // Label "0" is the background
    for (int i = 1; i <= n_labels; ++i)
    {
        Mat1b region_mask = (labels == i);
        imshow("Region", region_mask);
        waitKey();
    }

    return 0;
}

OpenCV >= 3.0 可以使用connectedComponents,它会直接返回labels

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

int main()
{
    // Read image from file 
    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

    Mat1b region;
    threshold(img, region, 200, 255, THRESH_BINARY);

    Mat1i labels;
    int n_labels = connectedComponents(region, labels);

    // Now you can get your regiones as:

    // Label "0" is the background
    for (int i = 1; i <= n_labels; ++i)
    {
        Mat1b region_mask = (labels == i);
        imshow("Region", region_mask);
        waitKey();
    }

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多