转:https://www.kancloud.cn/aollo/aolloopencv/272892

OpenCV中的轮廓

1.1什么是轮廓
轮廓可以简单认为成连续的点(连着边界)连在一起的曲线,具有相同的颜色或者灰度。轮廓在形状分析和物体的检测和识别中很有用。

  • 为了准确,要使用二值化图像。需要进行阀值化处理或者Canny边界检测。
  • 查找轮廓的函数会修改原始图像。如果之后想继续使用原始图像,应该将原始图像储存到其他变量中。
  • 在OpenCV中,查找轮廓就像在黑色背景中超白色物体。你应该记住,要找的物体应该是白色而背景应该是黑色。
    如何在一个二值图像中查找轮廓。
    函数cv2.findContours()有三个参数,第一个是输入图像,第二个是轮廓检索模式,第三个是轮廓近似方法。返回值有三个,第一个是图像,第二个是轮廓,第三个是(轮廓的)层析结构。轮廓(第二个返回值)是一个Python列表,其中储存这图像中所有轮廓。每一个轮廓都是一个Numpy数组,包含对象边界点(x,y)的坐标。
    1.2怎样绘制轮廓
    函数cv2.drawContours()可以被用来绘制轮廓。它可以根据你提供的边界点绘制任何形状。它的第一个参数是原始图像,第二个参数是轮廓,一个python列表,第三个参数是轮廓的索引(在绘制独立轮廓是很有用,当设置为-1时绘制所有轮廓)。接下来的参数是轮廓的颜色和厚度。
    在一幅图像上绘制所有的轮廓:
import numpy as np
import cv2img = cv2.imread('1024.jpg')
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
image ,contours,hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
#绘制独立轮廓,如第四个轮廓
#imag = cv2.drawContour(img,contours,-1,(0,255,0),3)
#但是大多数时候,下面方法更有用
imag = cv2.drawContours(img,contours,3,(0,255,0),3)while(1):cv2.imshow('img',img)cv2.imshow('imgray',imgray)cv2.imshow('image',image)cv2.imshow('imag',imag)if cv2.waitKey(1) == ord('q'):break
cv2.destroyAllWindows()

1.3轮廓的近似方法
之前提到轮廓是一个形状具有相同灰度值的边界,它会存储形状边界上所有的(x,y)坐标。实际上我们不需要所有的点,当需要直线时,找到两个端点即可。cv2.CHAIN_APPROX_SIMPLE可以实现。它会将轮廓上的冗余点去掉,压缩轮廓,从而节省内存开支。
下面用矩阵来演示,在轮廓列表中的每一个坐标上画一个蓝色圆圈。第一个显示使用cv2.CHAIN_APPROX_NONE的效果,一共734个点,第二个图是使用cv2.CHAIN_APPROX_SIMPLE的结果,只有4个点。

2.轮廓特征
2.1矩
图像的矩可以帮助我们计算图像的质心,面积等。
函数cv2.moments()会将计算得到的矩以一个字典的形式返回。

import numpy as np
import cv2img = cv2.imread('1024.jpg',0)
ret,thresh = cv2.threshold(img,127,255,0)
image,contours,hierarchy=cv2.findContours(thresh,1,2)
cnt=contours[0]
M=cv2.moments(cnt)
print(M)

根据这些矩的值,我们可以计算出对象的重心:

cx=int(M['m10']/M['m00'])
cy=int(M['m01']/M['m00'])

2.2轮廓面积
可以使用函数cv2.contourArea()计算得到,也可以用矩(0阶矩),M['m00']。

area=cv2.contourArea(cnt)

2.3轮廓周长
也被称为弧长。可以使用函数cv2.arcLength()计算得到。这个函数的第二参数可以用来指定对象的形状是闭合的(True),还是打开的(一条曲线)。

perimeter = cv2.arcLength(cnt,True)

2.4轮廓近似
将轮廓形状近似到另外一种由更少点组成的轮廓形状,新轮廓的点的数目由我们设定的准确度来决定,使用的Douglas-Peucker算法,可以自己Google。
假设我们要在一幅图像中查找一个矩形,但是由于图像的种种原因我们不能得到一个完美的矩形,而是一个“坏形状”,现在就可以使用这个函数来近似这个形状,第二个参数是epsilon,它是从原始轮廓到近似轮廓的最大距离,它是一个准确度参数。

epsilon=0.1*cv2.arcLength(cnt,True)
approx = cv2.approxPolyDP(cnt,epsilon,True)

2.5凸包
凸包与轮廓近似相似,但不同,虽然有些情况下它们给出的结果是一样的。函数cv2.convexHull()可以用来检测一个曲线是否具有凸性缺陷,并能纠正缺陷。一般来说,凸性曲线总是凸出来的,至少是平的。如果有地方凹进去了就被叫做凸性缺陷。例如下图中的手,红色曲线显示了手的凸包,凸性缺陷被双箭头标出来了。

hull = cv2.convexHull(points,hull,clockwise,returnPoints)

参数:

  • points我们要传入的轮廓
  • hull输出,通常不需要
  • clockwise方向标志,如果设置为True,输出的凸包是顺时针方向的,否则为逆时针方向。
  • returnPoints默认值为True。它会返回凸包上点的坐标,如果设置为False,就会返回与凸包点对应的轮廓上的点。
    要获得上图的凸包,可以用下面命令:
hull=cv2.convexHull(cnt)

但是如果你想获得凸性缺陷,需要把returnPoints设置为False。以上面矩形为例,首先我们找到他的轮廓从cnt。现在把returnPoints设置为True查找凸包,得到的就是矩形的四个角点。把returnPoints设置为False,得到的是轮廓点的索引。
2.6凸性检测
函数cv2.isContourConvex()可以检测一个曲线是不是凸的。它只能返回True或者False。

k=cv2.isContourConvex(cnt)

2.7边界矩形
直边界矩形,一个直矩形,没有旋转。不会考虑对象是否旋转。所以边界矩形的面积不是最小的。可以使用函数cv2.boundingRect()查找得到

#(x,y)为矩形左上角的坐标,(w,h)是矩形的宽和高
x,y,w,h=cv2.boundingRect(cnt)
img=cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),2)

旋转的边界矩形,这个边界矩形是面积最小的,因为它考虑了对象的旋转。用函数cv2.minAreaRect()。返回的是一个Box2D结构,其中包含矩形最上角角点坐标(x,y)矩形的宽和高(w,h)以及旋转角度。但是要绘制这个矩形需要矩形的4个角点,可以通过函数cv2.boxPoints()获得。
其中绿色的为直矩形,红色为旋转矩形。

2.8最小外接圆
函数cv2.minEnclosingCircle()可以帮我们找到一个对象的外接圆。它是所有能够包括对象的圆中面积最小的一个。

(x,y),radius = cv2.minEnclosingCircle(cnt)
center = (int(x),int(y))
radius = int(radius)
img = cv2.circle(img,center,radius,(0,255,0),2)

2.9椭圆拟合
使用函数cv2.ellipse(),返回值其实就是旋转边界矩形的内切圆。

ellipse = cv2.fitEllipse(cnt)
img = cv2.ellipse(img,ellipse,(0,255,0),2)

2.10直线拟合
可以根据一组点拟合出一条直线,同样我们也可以为图像中的白色点拟合出一条直线。

rows,cols = img.shape[:2]
[vx,vy,x,y]=cv2.fitLine(cnt,cv2.DIST_L2,0,0.01,0.01)
lefty=int((x*vy/vx)+y)
righty=int(((cols-x)*vy/vx)+y)
img = cv2.line(img,(cols-1,righty),(0,lefty),(0,255,0),2)

1.1长宽比
边界矩形的宽高比

x,y,w,h=cv2.boundingRect(cnt)
aspect_ratio = float(w)/h

2.Extent
轮廓面积与边界矩形面积的比

area=cv2.contourArea(cnt)
x,y,w,h=cv2.boundingRect(cnt)
rect_area=w*h
extent=float(area)/rect_area

3.Solidity
轮廓面积与凸包面积的比

area=cv2.contourArea(cnt)
hull=cv2.convexHull(cnt)
hull_area=cv2.contourArea(hull)
solidity=float(area)/hull_area

4.与轮廓面积相等的圆形的直径

area=cv2.contourArea(cnt)
equi_diameter=np.sqrt(4*area/np.pi)

5.方向
对象的方向,下面的方法还会返回长轴和短轴的长度

(x,y),(MA,ma),angle=cv2.fitEllipse(cnt)

6.掩模和像素点
有时我们需要构成对象的所有像素点

mask=np.zeros(imgray.shate,np.uint8)
#这里一定要使用参数-1,绘制填充的轮廓
cv2.drawContours(mask,[cnt],0,255,-1)
pixelpoints=np.transpose(np.nonzero(mask))

7.最大值和最小值及它们的位置
可以使用掩模图像得到这些参数

min_val,max_val,min_loc,max_loc=cv2.minMaxLoc(imgray,mask=mask)

8.平均颜色及平均灰度
同样使用相同的掩模来求得

mean_val=cv2.mean(im,mask=mask)

9.极点
一个对象最上,最下,最左,和最右的点

leftmost=tuple(cnt[cnt[:,:,0].argmin()[0])
rightmost=tuple(cnt[cnt[:,:,0].argmax()[0])
topmost=tuple(cnt[cnt[:,:,1].argmin()[0])
bottommost=tuple(cnt[cnt[:,:,1].argmax()[0])

OpenCV中的轮廓及性质相关推荐

  1. OpenCV-Python 中文教程15——OpenCV 中的轮廓

    OpenCV-Python 中文教程15--OpenCV 中的轮廓 一.初识轮廓 目标 • 理解什么是轮廓 • 学习找轮廓,绘制轮廓等 • 函数: cv2.findContours(), cv2.dr ...

  2. OpenCV中图像轮廓检测

    OpenCV中图像轮廓检测 通过之前的Canny方法可以得到图像的边界,但是我们无法得到边界的数学信息.所以就有了今天的图像轮廓检测. 在OpenCV中图像轮廓检测的API: findContours ...

  3. OpenCV 中的轮廓-轮廓的层次结构

    轮廓的层次结构 目标 现在我们要学习轮廓的层次结构了,比如轮廓之间的父子关系. 原理 在前面的内容中我们使用函数 cv2.findContours 来查找轮廓,我们需要传入一个参数:轮廓提取模式(Co ...

  4. OpenCV学习笔记(12)——OpenCV中的轮廓

    什么是轮廓 找轮廓.绘制轮廓等 1.什么是轮廓 轮廓可看做将连续的点(连着边界)连在一起的曲线,具有相同的颜色和灰度.轮廓在形态分析和物体的检测和识别中很有用. 为了更加准确,要使用二值化图像.在寻找 ...

  5. Opencv中的轮廓检测及应用

    在openCV中,我们可以对图片的轮廓进行检测,虽然轮廓的检测看起来很简单,只是对一个图形的边框进行描绘,但是,它在很多领域上都应用到了,例如:人脸识别.车辆检测.视频采集等,下面我会通过人脸识别和车 ...

  6. opencv中关于轮廓检测识别Contours及相关函数的介绍

    最近在用vs和opencv库在做图像处理的项目,关于轮廓识别部分,我查阅了一些资料, 现结合自己的理解整理出来,希望能对你有用. 1.contours概述 在利用openCV对图像进行处理时,我们可能 ...

  7. opencv中contourArea 轮廓面积计算

    轮廓线包含N个顶点,这些顶点的位置是对应像素的中心点,面积就是从这些个中心点开始算的. 黑点表示轮廓线的顶点,实线线就表示轮廓线,那么这个轮廓的面积计算方法就如图所示. 最后结果为3.5.

  8. (三)OpenCV中的图像处理之轮廓

    注释:本文翻译自OpenCV3.0.0 document->OpenCV-Python Tutorials,包括对原文档种错误代码的纠正 该章节分为以下四个小节: (一)     Contour ...

  9. opencv+Recorder︱OpenCV 中的 Canny 边界检测+轮廓、拉普拉斯变换

    本文来自于段力辉 译<OpenCV-Python 中文教程> 边缘检测是图像处理和计算机视觉中的基本问题,通过标识数字图像中亮度变化明显的点,来捕捉图像属性中的显著变化,包括深度上的不连续 ...

最新文章

  1. KS103超声波测距模块
  2. 怎么用IDEA快速查看类图关系?
  3. IE11下载文件时出现文件名乱码
  4. NYOJ 608 畅通工程
  5. linux查看证书位数,查看Linux系统是32位还是64位(getconf WORD_BIT误区)
  6. linux的文件搜索命令,Linux文件搜索命令find的用法 | 术与道的分享
  7. GAN —— 《Generative Adversarial Nets》
  8. error: unpacking of archive failed on file错误的解决
  9. Python3 openpyxl库
  10. 18.TCP使用的注意事项
  11. PHPstorm如何导入字体主题
  12. 我的RTOS 之二 --Threadx在skyeye上仿真測试(基于2410)
  13. 怎么接收xml报文_Benteler/本特勒 DESADV 报文生成过程
  14. 2017百度之星程序设计大赛 - 资格赛 1003
  15. Visio_Premium_project_vol版
  16. 蓝桥杯杨辉三角形java
  17. 微信公众号短链生成服务器,微信公众号短链接生成源码
  18. 【IIS小技巧】将IIS Express改成可以通过ip地址访问
  19. 微信小程序实现朋友圈图片展现形式
  20. hdu 4009 Transfer water(最小树形图模板)

热门文章

  1. 意大利警方逮捕了涉嫌盗窃莱昂纳多军事 国防数据的嫌疑人
  2. 企业申请专利的《五》大好处!
  3. TCP/IP协议学习记录之九:Traceroute程序
  4. ardupilot 核心IMU数据记录
  5. CATIA V5知识工程专辑讲解视频教程
  6. MySql深分页问题详解
  7. 微软的IntelliPoint和招商银行专业版是有冲突的!!!
  8. 从MTK的scat文件谈ROM和RAM的分配,管理和问题解决(拷贝)
  9. Linux操作系统上的文件共享
  10. plt.rcParams[]详解