Opencv8:halcon中select_shape_proto的opencv实现

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:处理结果

        

                        

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值