opencv 轮廓

一、话说轮廓

关于轮廓,我们一定能想起前面的边缘检测,但直接进行边缘检测后会出现一个尴尬的情况:只计算出了边缘,但对机器来说不知道哪些是物体的轮廓,而很多时候我们确实肥肠希望能找出物体的轮廓。

轮廓检测能较好的化解这一尴尬的情况。对于轮廓,官方指导中给出了这样的解释:

“轮廓可以理解为图像中具有相同颜色或密度的位于边界的连续点的集合,轮廓是形状分析和对象识别的有利工具。”

在OpenCV中,我们常用findContours函数来计算轮廓,每个独立的轮廓都是以Numpy array的点坐标的形式呈现。

为了在图像中显示出计算出的轮廓,我们使用drawContours函数。通常这个函数会配合findContours使用。

轮廓检测的一般步骤:

  • 图像预处理,为达到良好的精度,通常要使用二值化图像,因此常用阈值化处理或边缘检测对图像进行预处理
  • 使用findContours计算轮廓
  • 使用drawContours或其他方法画出轮廓

API:

image, contours, hierarchy=cv2.findContours(image, mode, method[, contours[, hierarchy[, offset]]])
  • image:源图像,8位单通道图像,非0像素值均按像素值为1处理
  • contours:轮廓信息,每个轮廓由点集组成,而所有的轮廓构成了contours列表
  • hierarchy:可选参数,表示轮廓的层次信息(拓扑信息,有种树结构的感觉),每个轮廓元素contours[i]对应4个hierarchy元素hierarchy[i][0]~hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓和内嵌轮廓的编号,若无对应项,则该参数为负值
  • mode:轮廓检索模式
  • method:轮廓逼近方法

关于轮廓的检索模式,有:

  • cv2.RETR_EXTERNAL:只检测最外层轮廓,并置hierarchy[i][2]=hierarchy[i][3]=-1
  • cv2.RETR_LIST:提取所有轮廓并记录在列表中,轮廓之间无等级关系
  • cv2.RETR_CCOMP:提取所有轮廓并建立双层结构(顶层为连通域的外围轮廓,底层为孔的内层边界)
  • cv2.RETR_TREE:提取所有轮廓,并重新建立轮廓层次结构

关于轮廓的逼近方法,有:

  • cv2.CHAIN_APPROX_NONE:获取每个轮廓的每个元素,相邻像素的位置差不超过1,即连续的点,但通常我们并不需要所有的点
  • cv2.CHAIN_APPROX_SIMPLE:压缩水平方向、垂直方向和对角线方向的元素,保留该方向的终点坐标,如矩形的轮廓可用4个角点表示,这是一种常用的方法,比第一种方法能得出更少的点
  • cv2.CHAIN_APPROX_TC89_L1和cv2.CHAIN_APPROX_TC89_KCOS:对应Tch-Chain链逼近算法
image=cv2.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])
  • image:目标输出图像,可理解为画布
  • contours:所有的输入轮廓,可直接传入findContours函数中的contours参数
  • contourIdx:轮廓绘制的指示变量,即绘制哪个轮廓,若为负值则绘制所有轮廓
  • 剩余参数均有对应的默认值,可查看API

二、相关的函数

  • minAreaRect:寻找最小包围矩形,即外接矩形,也是会旋转的矩形框
  • minEnclosingCircle:寻找最小包围圆形
  • fitEllipse:用椭圆拟合二维点集
  • approxPolyDP:逼近多边形曲线
  • boundingRect:返回外部边界矩形,即四平八稳的矩形框
# retval:(x,y,w,h)四个参数 其中w和h为宽和高
retval=cv2.boundingRect(points)
# retval:((x,y),(w,h),angle)依次为中心坐标 矩形的宽高和旋转角度
retval=cv2.minAreaRect(points)
retval=cv2.fitEllipse(points)
  • points:点集
center, radius=cv2.minEnclosingCircle(points)
  • center、radius:圆心和半径
  • points:点集
approxCurve=cv2.approxPolyDP(curve, epsilon, closed[, approxCurve])

这里强调下常用的minAreaRect函数。通常将返回值(Box2D结构)传入boxPoints函数得到旋转矩形四个顶点的坐标,这个封装在cv2里的boxPoints函数最初的版本是封装在cv里的BoxPoints(不在cv2里),如果要使用BoxPoints则需要安装OpenCV 2.xx版本,所以我们直接调用cv2.boxPoints函数即可。

三、实验代码

	Mat src = imread("D:\\cv_study\\随机练\\duola.jpg");
	Mat dst, gray;
	cvtColor(src, gray, CV_BGR2GRAY);
	threshold(gray, gray, 80, 255, THRESH_BINARY);
	vector<vector<Point>>contours;
	vector<Vec4i>h;
	findContours(gray, contours, h, RETR_TREE, CHAIN_APPROX_NONE);
	drawContours(src, contours, 1, Scalar(0, 0, 255), 3);

	Rect rect = boundingRect(contours[1]);
	rectangle(src, rect, Scalar(255, 0, 0), 2);

	RotatedRect r = fitEllipse(contours[1]);
	ellipse(src, r, Scalar(255, 0, 0), 3);

	RotatedRect r = minAreaRect(contours[1]);
	Point2f P[4];
	r.points(P);
	for (int j = 0; j <= 3; j++)
	{
		line(src, P[j], P[(j + 1) % 4], Scalar(255), 2);
	}

opencv中没有直接画出旋转矩形的函数,这里只能用循环语句讲矩形用线的形式画出来。

	Point2f p1;
	float p2;
    minEnclosingCircle(contours[1],p1,p2);
	circle(src, p1, p2, Scalar(0, 255, 0), 2);

以上的实验画出了包围轮廓的矩形,圆形,椭圆。以上就是今天的内容,希望大家批评指正。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值