利用opencv的重心算法找出图中居中的区域

最近在工作中遇到一个需求,就是在一张图中找出最居中的一个图形区域;假定一张图中有很多个不连接的图形区域,先将整张图进行二值化处理,然后通过找出所有区域,并计算每个区域的重心,然后与整张图的重心进行比较,利用两个重心的距离来确定最居中的那个区域。
大致代码如下(C++)

//image 二值图
//width 宽度
//height  高度
//data 图像数组
int GetArea(cv::Mat image,int width,int height,int *data)
{
	Moments image_moments  = moments(image);//求image整图重心
	int image_moments_x = int(image_moments.m10 / image_moments.m00);
	int image_moments_y = int(image_moments.m01 / image_moments.m00);
	int largest_area = 0;
	int largest_contour_index = 0;
	int least_distance = INT_MAX;
	vector<vector<Point>> contours;
	findContours(image,contours,ERTR_CCOMP,CHAIN_APPROX_SIMPLE);//找出所有轮廓
	
	for(size_t i = 0;i < contours.size();i++)
	{
		Moments contour_moments = moments(contours[i]);//轮廓重心
		int cx = int(contour_moments.m10 / contour_moments.m00);
		int cy = int(contour_moments.m01 / contour_moments.m00);
		int distance = sqrt((cx-image_moments_x)*(cx-image_moments_x)+(cy-image_moments_y)*(cy-image_moments_y));//两点距离公式
		if(distance < least_distance)
		{
			least_distance = distance;
			largest_contour_index = i;
			largest_area = contourArea(contours[i]);
		}		
	}
	
	Mat mat(height,width,CV_8UC1,Scalar(0));//根据高度创建一张临时图mat
	drawContours(mat,contours,largest_contour_index,Scalar(255),CV_FILLED);//在mat中绘制找到的轮廓
	for(int h = 0;h< height;h++)
	{
		for(int w = 0;w < width ;w++)
		{
			if(*mat.data == 0)
			{
				data[w+h * width] = 0;//将data中其它轮廓值为0,只保留找到的轮廓,并返回data
			}
			mat.data+;
		}
	}
}

相关函数说明
moments() : 计算轮廓的质心
利用opencv的重心算法找出图中居中的区域

drawContours() 在图像中绘制外部和内部的轮廓。
利用opencv的重心算法找出图中居中的区域

drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(),int maxLevel=INT_MAX, Point offset=Point())
image: 是最终需要被填充的图像;
contours:是得到的一系列点的集合;
contourIdx:是指定某个contours的点集;
color:被填充的颜色,单色可以设置为Scalar(255)等;
thickness: 所画Contour的线条宽度,如果为负或CV_FILLED则绘制所有的Contours;
lineType: 线的连通性;
hierarchy:可选层次信息结构,这里面是findContours所的到的基于Contours的层级信息;
maxLevel: 绘制轮廓的最大等级。如果等级为0,绘制单独的轮廓。如果为1,绘制轮廓及在其后的相同的级别下轮廓。如果值为2,所有的轮廓。如果等级为2,绘制所有同级轮廓及所有低一级轮廓,诸此种种。如果值为负数,函数不绘制同级轮廓,但会升序绘制直到级别为abs(max_level)-1的子轮廓
offset:照给出的偏移量移动每一个轮廓点坐标.当轮廓是从某些感兴趣区域(ROI)中提取的然后需要在运算中考虑ROI偏移量时,将会用到这个参数。

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2022年6月15日
下一篇 2022年6月15日

相关推荐