为什么 OpenCV 没有专门针对区域的数据结构?

Why OpenCV has no specialize data structure for region?

MVTec的Halcon图像处理库用了半年,OpenCV用了1年。

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

如果我只想在大 space 中存储一个小区域,这会造成很大的浪费。 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
        //
        //  ***************************************
    }

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

然后您可以简单地访问第 i 个区域:Mat1b region_mask = (labels == i);

使用 OpenCV < 3.0,您可以使用 findContursdrawContours 来创建 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,这将直接 return 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;
}