Opencv8:halcon中select_shape_proto()的opencv实现【overlaps_abs】
(1)select_shape_proto()函数简介:
select_shape_proto()是Halcon中函数,用来在区域集合中依据区域与pattern之间的相互关系筛选区域,本文中实现的是我应用较多的overlaps_abs模式,筛选依据为重叠面积的数值。
其他关于select_shape_proto()函数的相关内容写在另一篇博客中,在此处不赘述。
https://blog.csdn.net/weixin_39504171/article/details/94551925
(2)select_shape_proto()函数的实现思路:
第一步,调用connectedComponents()函数对输入二值图像进行连通域分析,connectedComponents()函数的输出结果将连通域用灰度值形式进行标号,如区域1灰度值均为1,区域2灰度值均为2...;
第二步,遍历连通域中区域,实现方式为:当提取集合中序号为i的区域时,只需要将connectedComponents()函数的输出结果进行灰度范围为[i,i]的阈值分割即可;
第三步:对区域与pattern图像做与操作(bitwise_and()),对与操作的结果进行面积判断,如果符合设置的范围,则此区域满足要求。
(3)select_shape_proto()的opencv实现:
重点在于SelectShapeProto()函数,其他相关函数可自行替换,为方便直接复制了自己封装的版本。
#include <opencv2/opencv.hpp>
#include <iostream>
#include <vector>
#include "FunctionsHalcon.h"
using namespace cv;
using namespace std;
【1】指定范围的阈值分割
Mat ThresholdHalcon(Mat image, int threadmin, int threadmax)
{
Mat imageResult = Mat::zeros(image.size(), CV_32S);
int nr = image.rows;
int nc = image.cols;
for(int i=0;i<nr;i++)
{
for (int j=0;j < nc;j++)
{
if( (image.at<int>(i,j) >= threadmin) && (image.at<int>(i, j)<= threadmax))
{
imageResult.at<int>(i, j) = 255;
}
else
{
imageResult.at<int>(i, j) = 0;
}
}
}
return imageResult;
}
//【2】二值化,填充模式绘制轮廓
Mat ContoursThreshold(Mat &image,Mat &imageThreshold,vector<vector<Point>> &contours, vector<Vec4i> &hierarchy,int thread1,Scalar&color)
{
//阈值分割提取轮廓
threshold(image, imageThreshold, thread1, 255, THRESH_BINARY);
findContours(imageThreshold, contours, hierarchy, RETR_CCOMP, CHAIN_APPROX_SIMPLE, Point());
//轮廓分级提取,并填充绘制
Mat imageresult = Mat::zeros(image.size(), CV_8UC3);
int idx = 0;
for (idx = 0; idx >= 0; idx = hierarchy[idx][0])
{
//drawContours(imageresult, contours, idx, color, 1, 8, hierarchy);
drawContours(imageresult, contours, idx, color, 1);
}
return imageresult;
}
//【3】AreaCenter:计算连通域面积
void AreaCenter( const Mat& imageThreshold, vector<int> &area, vector<int> &rows, vector<int> &cols)
{
Mat labels = Mat::zeros(imageThreshold.size(), CV_32S);
Mat stats, centroids;
int num_labels = connectedComponentsWithStats(imageThreshold, labels, stats, centroids, 8, 4);
for (int i = 1; i < num_labels; i++)
{
Vec2d pt = centroids.at<Vec2d>(i, 0);
int x = stats.at<int>(i, CC_STAT_LEFT);
int y = stats.at<int>(i, CC_STAT_TOP);
int area1 = stats.at<int>(i, CC_STAT_AREA);
area.push_back(area1);
rows.push_back(pt[0]);
cols.push_back(pt[1]);
}
}
//【4】相互关系轮廓筛选【重叠面积】
void SelectShapeProto(const Mat& thresholdImage, const Mat& PatternImage, Mat &ResultImage, int FeatureMin, int FeatureMax)
{
Mat labels = Mat::zeros(thresholdImage.size(), CV_32S);
int num_labels = connectedComponents(thresholdImage, labels, 8, CV_32S);
for (int i = 1; i <= num_labels; i++)
{
Mat labeli = Mat::zeros(thresholdImage.size(), CV_32S);
labeli= ThresholdHalcon(labels, i, i);
Mat imageAnd = Mat::zeros(thresholdImage.size(), CV_8UC1);
bitwise_and(labeli, PatternImage, imageAnd);
Mat And;
imageAnd.convertTo(And, CV_8UC1);
vector<int> area;
vector<int> rows;
vector<int> cols;
AreaCenter(And, area, rows, cols);
int areaIntersection=0;
for (auto i = area.begin();i != area.end();i++)
{
areaIntersection = areaIntersection + *i;
}
if (FeatureMin < areaIntersection && areaIntersection < FeatureMax)
{
bitwise_or(labeli, ResultImage, ResultImage);
}
}
}
int main(int argc, char *argv[])
{
//【1】图像读取
Mat image = imread("8.png", 0);
Mat imagepanel = imread("9.png", 0);
//【2】图像分割
Mat imageThreshold;
vector<vector<Point>>contours;
vector<Vec4i>hierarchy;
ContoursThreshold(image, imageThreshold,contours, hierarchy, 10, Scalar(255,255,255));
ContoursThreshold(imagepanel, imagepanel, contours, hierarchy, 10, Scalar(255, 255, 255));
//【3】select_shape_proto调用
Mat imageResult = Mat::zeros(imageThreshold.size(), CV_32S);
Mat Threshold;
imageThreshold.convertTo(Threshold, CV_32S);
SelectShapeProto(imagepanel, Threshold, imageResult, 100, 100000000);
imageResult.convertTo(imageResult, CV_8UC1);
//【4】结果显示
imshow(" window1", image);
imshow(" window2", imagepanel);
imshow(" window3", imageResult);
waitKey(0);
return 0;
}
(4)处理结果:
①图片1:源图像
②图片2:pattern
③图片3:处理结果