halcon视觉专栏深度学习-推荐系统-CV-NLPOpenCv

从Halcon到OpenCV(一):select_shape算子

2019-12-10  本文已影响0人  coolTigers

select_shape算子是一个功能十分强大的算子,算子原型如下:

select_shape(Regions: SelectedRegions: Features, Operation, Min, Max:)

select_shape算子的功能是计算Regions中所有输入region的特征(Features),如果计算的特征在[Min,Max]区间内,则会将每一个符合要求的region(Operation = ‘and’)或者至少一个符合要求的region(Operation = 'or')复制到SelectedRegions中。


图片1.png

Regions:输入区域,比如connection算子的输出;
SelectedRegions:筛选后的输出区域;
Features:特征,常见的有:'area', 'row', 'column'等,详细内容请查询halcon算子region_features;
Operation: 'and' 或者 'or',and是输出所有符合要求的region,'or'是只输出一个符合要求的region即可
Min:特征的阈值下限,闭区间;
Max:特征的阈值上限,闭区间;
假如有如下halcon代码:

connection(src, region)
select_shape(region, selected_regions, 'area', 'and', min, max)

对应的OpenCV代码实现如下:

Mat labels, stats, centroids;
connectedComponentsWithStats(src, labels, stats, centroids);
// 相当于halcon中的select_shape算子
selectShapeAccordingArea(labels, stats, centroids, min, max);

其中selectShapeAccordingArea函数实现如下:

enum CONNECTIONS_STATS {
    X = 0,
    Y,
    WIDTH,
    HEIGHT,
    AREA,
    STATS_INDEX_MAX
};
void selectShapeAccordingArea(Mat& labels, Mat& stats, Mat& centroids, int min, int max)
{
    // 更新stats, centroids
    Mat tempStats, tempCentroids;
    vector<int> index;
    // 从1开始,不计算背景连通域
    for (int i = 1; i < stats.rows; ++i) { 
        int area = stats.row(i).at<int>(0, AREA);
        if (area >= min & area <= max) {
            tempStats.push_back(stats.row(i));
            tempCentroids.push_back(centroids.row(i));
            index.push_back(i);
        }
    }
    stats = tempStats;
    centroids = tempCentroids;
    // 更新labels
    Mat mask(labels.size(), CV_8UC1, Scalar(0));
    for (int i = 0; i < stats.rows; ++i) {
        int rectX = stats.row(i).at<int>(0, X);
        int rectY = stats.row(i).at<int>(0, Y);
        int rectWidth = stats.row(i).at<int>(0, WIDTH);
        int rectHeight = stats.row(i).at<int>(0, HEIGHT);

        Rect roi(rectX, rectY, rectWidth, rectHeight);
        mask(roi) = (labels(roi) == index[i]);  
    }
    Mat tempLabels;
    labels.copyTo(tempLabels, mask);
    labels = tempLabels;
}

下面进行验证:

#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
using namespace std;
using namespace cv;
int main()
{
    Mat src(5,5,CV_8UC1, Scalar(0));
    src.at<uchar>(0, 3) = 255;
    src.at<uchar>(1, 3) = 255;
    src.at<uchar>(0, 4) = 255;
    src.at<uchar>(4, 4) = 255;
    cout << "src: \n" << src << endl;
    Mat labels, stats, centroids;
    connectedComponentsWithStats(src, labels, stats, centroids);
    cout << "before, labels: \n" << labels << endl;
    cout << "before, stats: \n" << stats << endl;
    cout << "before, centroids: \n" << centroids << endl;

    selectShapeAccordingArea(labels, stats, centroids, 3, 4);
    cout << "after, labels: \n" << labels << endl;
    cout << "after, stats: \n" << stats << endl;
    cout << "after, centroids: \n" << centroids << endl;

    waitKey(0);
    return 0;
}

输出结果如下:


image.png

从输出结果来看,面积为一的连通域已经被过滤,labels矩阵中只剩下一个连通域,stats和centroids矩阵都保留了对应连通域的特征。

上一篇 下一篇

猜你喜欢

热点阅读