虽然Canny.之类的边缘检测算法可以根据像素间的差异检测出轮廓边界的像素,但是它并没有将轮廓作为一个整体进行处理。下一步是要将这些边缘像素合成轮廓。 轮廓层次 在了解到底如何提取轮廓之前,有必要花一些时间来理解轮廓到底是什么以及一组轮廓之间如何互相关联。 图中有五块颜色区域(分别标记为A,B,C,D,E), 每块区域的外部边界和内部边界都各自组成轮廓。因此共有9条轮廓。每条轮廓都由一组输出列表表示(右上角图一轮廓参数)。 # 轮廓近似法 contours[, # 检测到的轮廓。 如果为 1,则函数绘制轮廓和所有嵌套轮廓。 如果为 2,则函数绘制轮廓、所有嵌套轮廓、所有嵌套到嵌套的轮廓,依此类推。仅当存在可用层次结构时才考虑此参数。
当分析一张图像的时候,针对轮廓,我们也许有很多事情要做。毕竟,所有轮廓都是或即将是我们想要进行识别或操作的。另外相关的还有多种对轮廓的处理,如描述轮廓,简化或拟合轮廓,匹配轮廓到模板,等等。 本文记录 OpenCV 中的轮廓分析的相关操作。 多边形逼近 当我们绘制一个多边形或进行形状分析时,通常需要使用多边形逼近一个轮廓,使顶点数变少。 Douglas-Peucker(DP) 逼近算法 该算法首先从轮廓(图B)中挑出两个最远的点,将两点相连(图C)。然后在原来的轮廓上寻找一个离线段距离最远的点, 将该点加入逼近后的新轮廓中。 从这里可以看出,将该精度设置为轮廓周长或外包矩形周长等表示轮廓总长度的值的几分之一比较合适。 这可能包括长度或其他一些反应轮廓整体大小的量度。另一个有用的特性是轮廓矩(contour moment)可以用来概括轮廓的总形状特性,这部分我们在下一节讨论。
一个跟轮廓相关的最常用到的功能是如何匹配多条轮廓。我们或许需要比较两条计算好的轮廓,或者比较一条轮廓和一个抽象模板。这两种情况都会在本文讨论。 矩 相关介绍 比较两条轮廓最简洁的方法之一是比较它们的轮廓矩。轮廓矩代表了一条轮廓、一幅图像、一组点集的某些高级特征。下面的所有讨论对轮廓、图像、点集都同样适用,简便起见,将它们统称为对象。 当处理轮廓时,结果是轮廓的长度。 将m_{10}和m_{01}相加再除以mo,能得到整个对象的平均x值和y值。 cv2.moments 计算多边形或光栅化形状的所有矩,最高可达三阶。 官方文档 仅适用于来自 Python 绑定的轮廓矩计算: 注意,输入数组的 numpy 类型应该是 np.int32或 np.float32。 官方文档 函数使用 cv2.matchShapes( contour1, # 第一个轮廓或灰度图像。 contour2, # 第二轮廓或灰度图像。
在OpenCV中,轮廓检测和轮廓筛选是图像处理中常用的技术,用于识别和分析图像中物体的形状。以下是详细的分步说明: 一、轮廓检测(Contour Detection) 1. 调用cv2.findContours()检测轮廓 该函数返回轮廓的坐标点和层级关系。 cv2.CHAIN_APPROX_NONE:保留所有轮廓点。 二、轮廓筛选(Contour Filtering) 1. 基于面积筛选 过滤掉面积过小或过大的轮廓。 层级结构处理 场景:需区分嵌套轮廓(如字母“O”的内外轮廓)。 医学图像分析:分割细胞或器官轮廓。 机器人导航:识别障碍物边界。 通过灵活组合轮廓特征(面积、形状、凸性等),可以高效筛选出符合需求的轮廓,为后续处理提供基础。
#将灰度图片转换为二值图片 contours,hierarchy=cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)#计算图像轮廓 temp) cnt=contours[i] mask=np.zeros(gray.shape,np.uint8) cv2.drawContours(mask,[cnt],0,255,-1)#绘制图像空心轮廓 [115 225] [115 226] [115 227]] 算法:实心轮廓是通过获取特定对象的掩模图像及其对应的像素点位置信息来获取实心轮廓,应用在图像噪声消除等领域。 函数cv2.drawContours()的轮廓宽度参数thickness设置不为-1,即获取图像的空心轮廓。
#将灰度图片转换为二值图片 contours,hierarchy=cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)#计算图像轮廓 contoursImg=[] for i in range(n): print("contours["+str(i)+"]面积=",cv2.contourArea(contours[i]))#计算轮廓面积 4.0 contours[16]面积= 3263.0 contours[17]面积= 9103.5 contours[18]面积= 6578.5 contours[19]面积= 8974.5 算法:轮廓面积是估算图像轮廓部分和起始点连线构成的封闭部分的像素数量 retval=cv2.contourArea(contour[, oriented])) contour表示图像轮廓 oriented表示布尔型值,如果为True,则返回值包含正/负号,表示轮廓是顺时针还是逆时针 ,默认值是False,表示返回retval是绝对值 注意:轮廓面积的单位是像素。
#将灰度图片转换为二值图片 contours,hierarchy=cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)#计算图像轮廓 temp) cnt=contours[i] mask=np.zeros(gray.shape,np.uint8) cv2.drawContours(mask,[cnt],0,255,2)#绘制图像空心轮廓 [115 225] [115 226] [115 227]] 算法:空心轮廓是通过获取特定对象的掩模图像及其对应的像素点位置信息来获取空心轮廓,应用在图像噪声消除等领域。 函数cv2.drawContours()的轮廓宽度参数thickness设置为-1,即获取图像的实心轮廓。
目标 了解轮廓概念 寻找并绘制轮廓 OpenCV函数:cv2.findContours(), cv2.drawContours() 教程 啥叫轮廓 轮廓是一系列相连的点组成的曲线,代表了物体的基本外形。 谈起轮廓不免想到边缘,它们确实很像。简单的说,轮廓是连续的,边缘并不全都连续(下图)。 经验之谈:寻找轮廓是针对白色物体的,一定要保证物体是白色,而背景是黑色,不然很多人在寻找轮廓时会找到图片最外面的一个框。 ,一般使用cv2.RETR_TREE,表示提取所有的轮廓并建立轮廓间的层级。 to clipboardErrorCopied 小结 轮廓特征非常有用,使用cv2.findContours()寻找轮廓,cv2.drawContours()绘制轮廓。
外部的轮廓为父轮廓,内部的轮廓为子轮廓,按照上述关系分类,一幅图像中所有轮廓之间就建立了父子关系。 ) image表示输入图像 mode表示图像轮廓的检索模式 method表示图像轮廓的近似方法 image=cv2.drawContours(image, contours, contourIdx, 表示绘制轮廓边缘 color表示绘制颜色 thickness表示画笔粗细,可选参数 lineType表示绘制线型,可选参数 hierarchy表示图像轮廓的层次信息 maxLevel表示图像轮廓的层次深度 offset表示偏移参数 例子: 绘制所有轮廓: cv.drawContours(img, contours, -1, (0, 255, 0), 3) 绘制单个轮廓: cv.drawContours( 3) 注意:轮廓就像从黑色背景中找到白色物体,通常情况下,预先对图像进行阈值分割或边缘检测得到二值图像。
threshold(gray,235,255,cv2.THRESH_BINARY)#将灰度图片转换为二值图片 contours,hierarchy=cv2.findContours(thresh,2,1)#计算图像轮廓 (轮廓)的最短距离(垂线距离),又称点和多边形的关系测试。 ,表示计算点到轮廓的距离。 如果点在轮廓的外部,返回值为负数;如果点在轮廓上,返回值为0;如果点在轮廓内部,返回值为正数。如果为False,不表示计算距离,表示点相对于轮廓的位置关系,返回值为-1、0和1。 如果点在轮廓的外部,返回值为-1;如果点在轮廓上,返回值为0;如果点在轮廓内部,返回值为1
: CV_RETR_EXTERNAL只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略 CV_RETR_LIST 检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系 ,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1 CV_RETR_CCOMP 检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层 ,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层 CV_RETR_TREE, 检测所有轮廓,所有轮廓建立一个等级树结构。 外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。 用CV_RETR_TREE效果 此时找到的所有轮廓。
轮廓属性outline outline属性是用来设置一个或多个单独的轮廓属性的简写属性 , 例如 。 轮廓有下面几个属性: { outline-style: solid; outline-width: 10px; outline-color: red; } 他们有一种简写形式: { outline: 10px solid red; } 轮廓的特点 轮廓不占据空间,它们被描绘于内容之上。 可以做到下图的效果: 我发现,当设置 outline-offset 为负值的时候,轮廓会出现在div的内部,如果继续扩大其负值,最终轮廓会收缩成一个“➕”加号,正好可以作为文件上传样式中间的加号。 #545454; outline-offset: -66px; border: 2px solid #545454; } outline-offset: -66px; 是关键,它表示轮廓距
plt.figure(figsize=(5,5)) plt.imshow(denoised_equalized, cmap='gray') plt.axis('off') plt.show() 算法:轮廓内核处理是突出显示像素值之间的差异
学习计算轮廓特征,如面积、周长、最小外接矩形等。图片等可到文末引用处下载。 目标 计算物体的周长、面积、质心、最小外接矩形等 OpenCV函数:cv2.contourArea(), cv2.arcLength(), cv2.approxPolyDP() 等 教程 在计算轮廓特征之前 轮廓周长 perimeter = cv2.arcLength(cnt, True) # 585.7Copy to clipboardErrorCopied 参数2表示轮廓是否封闭,显然我们的轮廓是封闭的 ,比如M['m00']表示轮廓面积,与前面cv2.contourArea()计算结果是一样的。 小结 常用的轮廓特征: cv2.contourArea()算面积,cv2.arcLength()算周长,cv2.boundingRect()算外接矩。
注意到轮廓的存储格式为std::vector>,他说明整个轮廓是若干条轮廓按一定顺序组成的,而每个轮廓中的点也是有顺序的。 参数为:画板,轮廓,轮廓指示(这里画出所有轮廓),颜色,线粗 drawContours(result,contours,-1,Scalar(0),2); imshow("提取外围轮廓",result , //获取轮廓的方法(这里获取所有轮廓) CV_CHAIN_APPROX_NONE); //轮廓近似的方法(这里不近似,获取全部轮廓 //画出轮廓 [ i ][ 3 ],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,该值设置为负数。 如果想获得一点与多边形封闭轮廓的信息,可以调用pointPolygonTest函数,这个函数返回值为该点距离轮廓最近边界的距离,为正值为在轮廓内部,负值为在轮廓外部,0表示在边界上。
步骤简述 使用OpenCV绘制矩形轮廓框,一般包括如下步骤: 转换为灰度图; 进行阈值处理; 进行中值滤波; 在原始图像上绘制矩形框。 附图解析 原始图像: 第一步,转换为灰度图: 第二步,经过阈值处理: 第三步,中值滤波后: 最后一步,在原始图像上绘制矩形框: 生成的记录文件(矩形轮廓框四个端点的平面坐标 /origin.jpg') # 文档路径,用于记录轮廓框坐标 txt_file = open('. threshold(src=pic, thresh=200, maxval=255, type=1) # 中值滤波,去除椒盐噪声 pic = cv2.medianBlur(pic, 5) # 边缘检测,得到的轮廓列表 _1, contours, _2 = cv2.findContours(pic, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 根据轮廓列表,循环在原始图像上绘制矩形边界
OpenCV 入门教程:轮廓特征和轮廓匹配 导语 轮廓特征和轮廓匹配是图像处理中用于描述和比较轮廓的技术。通过提取轮廓的形状、面积、周长等特征,并进行比较和匹配,我们可以实现目标识别、形状分析等应用。 在本文中,我们将以轮廓特征和轮廓匹配为中心,为你介绍使用 OpenCV 进行轮廓处理的基本步骤和实例。 ❤️ ❤️ ❤️ ❤️ ❤️ 一、轮廓特征 轮廓特征是指从轮廓中提取的描述性信息,用于对轮廓进行定量分析。以下是一些常见的轮廓特征: 1 面积( Area ):表示轮廓包围的区域的面积大小。 二、轮廓匹配 轮廓匹配是比较两个轮廓之间的相似度或差异度的技术。通过计算轮廓的形状、面积、周长等特征的差异,并进行比较,我们可以判断轮廓之间的相似性或不相似性。 ,并通过边缘检测和轮廓寻找获取轮廓。
#将灰度图片转换为二值图片 contours,hierarchy=cv2.findContours(binary,cv2.RETR_LIST,cv2.CHAIN_APPROX_SIMPLE)#计算图像轮廓 )#提取轮廓特征 print("轮廓"+str(i)+"的面积:%d"%cv2.moments(contours[i])['m00']) cv2.waitKey() cv2.destroyAllWindows 19的面积:8974 算法:图像轮廓的矩是一个轮廓、一幅图像、一组点集的全局特征,包括几何特征,例如大小、位置、角度、形状等。 如果两个图像轮廓的矩一致,那么两个图像轮廓一致。在图像位置发生变化时,虽然图像轮廓的面积、周长等特征不变,但是更高阶的特征会随着位置的变化而发生变化。 零阶矩“m00”的含义最为直观表示图像轮廓的面积。
在计算机视觉中,轮廓检测是另一个比较重要的任务。它包含的操作有计算矩形边界、圆形边界、多边形边界等等。 我们以下面的黑猫图为例来讲解如何利用OpenCV进行轮廓检测。 ? 此时,我们可以检测轮廓点集(图中绿色的外边界点) #2个返回值,分别是轮廓的点集(contours)和各层轮廓的索引(hierarchy) # openCV 4 , 否则注意版本差异! 之后,我们可以循环求得图形各部分的矩形轮廓线: for c in contours: #对于每一个轮廓 #无倾斜的 边界矩形框 x, y, w, h = cv2.boundingRect 图中有些过小的轮廓也显示出来了,我们可以加点尺寸限制,将它们过滤掉: W,H = img0.shape[0], img0.shape[1] for c in contours: #对于每一个轮廓 通常我们会计算凸多边线轮廓: #凸轮廓需要先加上下面这句 hull = cv2.convexHull(c) # 计算凸轮廓多变形时需要先处理轮廓 ?
从图中看得出来: 轮廓0/1/2是最外层的轮廓,我们可以说它们处于同一轮廓等级:0级 轮廓2a是轮廓2的子轮廓,反过来说2是2a的父轮廓,轮廓2a算一个等级:1级 同样3是2a的子轮廓,轮廓3处于一个等级 Parent] Next:与当前轮廓处于同一层级的下一条轮廓 举例来说,前面图中跟0处于同一层级的下一条轮廓是1,所以Next=1;同理,对轮廓1来说,Next=2;那么对于轮廓2呢? Previous:与当前轮廓处于同一层级的上一条轮廓 跟前面一样,对于轮廓1来说,Previous=0;对于轮廓2,Previous=1;对于轮廓1,没有上一条轮廓了,所以Previous=-1。 First Child:当前轮廓的第一条子轮廓 比如对于轮廓2,第一条子轮廓就是轮廓2a,所以First Child=2a;对轮廓3a,First Child=4。 Parent:当前轮廓的父轮廓 比如2a的父轮廓是2,Parent=2;轮廓2没有父轮廓,所以Parent=-1。