什么是轮廓?

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

• 为了更加准确,要使用二值化图像。在寻找轮廓之前,要进行阈值化处理 或者 Canny 边界检测。

• 查找轮廓的函数会修改原始图像。如果你在找到轮廓之后还想使用原始图 像的话,你应该将原始图像存储到其他变量中。

• 在 OpenCV 中,查找轮廓就像在黑色背景中超白色物体。你应该记住, 要找的物体应该是白色而背景应该是黑色。

如何在一个二值图像中查找轮廓?

函数 cv2.findContours()

输入参数:有三个,第一个是输入图像,第二个是 轮廓检索模式,第三个是轮廓近似方法。第三个参数设置为cv2.CHAIN_APPROX_NONE,所有的边界点 都会被存储;设置为cv2.CHAIN_APPROX_SIMPLE 将轮廓冗余的点去掉,压缩轮廓,节省内存开销。

返回值:有三个,第一个是图像,第二个 是轮廓,第三个是(轮廓的)层析结构。轮廓(第二个返回值)是一个 Python

列表,其中存储这图像中的所有轮廓。每一个轮廓都是一个 Numpy 数组,包 含对象边界点(x,y)的坐标。

im = cv2.imread('test.jpg')

imgray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY)

ret,thresh = cv2.threshold(imgray,127,255,0)

image, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

怎样绘制轮廓?

函数 cv2.drawContours() 可以被用来绘制轮廓。它可以根据你提供 的边界点绘制任何形状。它的第一个参数是原始图像,第二个参数是轮廓,一 个 Python 列表。第三个参数是轮廓的索引(在绘制独立轮廓是很有用,当设 置为 -1 时绘制所有轮廓)。接下来的参数是轮廓的颜色和厚度等。

img = cv2.drawContour(img, contours, -1, (0,255,0), 3)

img = cv2.drawContours(img, contours, 3, (0,255,0), 3)

轮廓形状拟合
1 边界矩形1.1 直边界矩形
一个直矩形(就是没有旋转的矩形)。它不会考虑对象是否旋转。 所以边界矩形的面积不是最小的。可以使用函数 cv2.boundingRect() 查找得到。 (x,y)为矩形左上角的坐标,(w,h)是矩形的宽和高。x,y,w,h  = cv2.boundingRect(array)array:轮廓点,常用contours[0]
(x,y)为矩形左上角的坐标,(w,h)是矩形的宽和高。
注:例子在最后1.2 旋转的边界矩形
这个边界矩形是面积最小的,因为它考虑了对象的旋转。用 到的函数为 cv2.minAreaRect()。
返回的是一个 Box2D 结构,其中包含 矩形左上角角点的坐标(x,y),矩形的宽和高(w,h),以及旋转角度。
但是 要绘制这个矩形需要矩形的 4 个角点,可以通过函数 cv2.boxPoints() 获 得。rect = cv2.minAreaRect(points)
points:轮廓点,常用contours[0]
rect:返回的是一个 Box2D 结构,其中包含 矩形左上角角点的坐标(x,y),矩形的宽和高(w,h),以及旋转角度。
但是 要绘制这个矩形需要矩形的 4 个角点,可以通过函数 cv2.boxPoints() 获得。2 最小外接圆
函数 cv2.minEnclosingCircle() 可以帮我们找到一个对象的外切圆。 它是所有能够包括对象的圆中面积最小的一个。(x, y), radius = cv2.minEnclosingCircle(points)points:轮廓点,常用contours[0]
(x, y):圆心
radius:半径3 椭圆拟合使用的函数为 cv2.ellipse(),返回值其实就是旋转边界矩形的内切圆。
ellipse = cv2.fitEllipse(points)(x,y),(a,b),angle = cv2.fitEllipse(points)

points:轮廓点,常用contours[0]
ellipse:可直接使用cv2.ellipse()画出椭圆
(x,y):椭圆中心
(a,b):长轴短轴
angle:旋转角度4 直线拟合
我们可以根据一组点拟合出一条直线,同样我们也可以为图像中的白色点 拟合出一条直线。[vx, vy, x, y] = cv2.fitLine(points, distType, param, reps, aeps, line)

points:二维点的数组
distType:距离类型
param:距离参数
reps:径向的精度参数
aeps:角度精度参数
line:输出直线
vx, vy:直线的方向
x, y:直线上一点轮廓性质
1 长宽比
边界矩形的宽高比2 Extent
轮廓面积与边界矩形面积的比。3 Solidity轮廓面积与凸包面积的比。4 Equivalent Diameter与轮廓面积相等的圆形的直径---------------------
作者:YukinoSiro
来源:CSDN
原文:https://blog.csdn.net/yukinoai/article/details/87892718
版权声明:本文为博主原创文章,转载请附上博文链接!import cv2
import numpy as np
from matplotlib import pyplot as pltfont = cv2.FONT_HERSHEY_SIMPLEX  # 设置字体样式img = cv2.imread('img/cat.jpg')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(imgray, 200, 255, 0)
image, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[0]# 极点
img0 = img.copy()
leftmost = tuple(cnt[cnt[:, :, 0].argmin()][0])
cv2.circle(img0, leftmost, 5, [0, 0, 255], -1)
rightmost = tuple(cnt[cnt[:, :, 0].argmax()][0])
cv2.circle(img0, rightmost, 5, [0, 0, 255], -1)
topmost = tuple(cnt[cnt[:, :, 1].argmin()][0])
cv2.circle(img0, topmost, 5, [0, 0, 255], -1)
bottommost = tuple(cnt[cnt[:, :, 1].argmax()][0])
cv2.circle(img0, bottommost, 5, [0, 0, 255], -1)
text1 = 'Leftmost: ' + str(leftmost) + ' Rightmost: ' + str(rightmost)
text2 = 'Topmost: ' + str(topmost) + ' Bottommost: ' + str(bottommost)
cv2.putText(img0, text1, (10, 30), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)
cv2.putText(img0, text2, (10, 60), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)# 直边界矩形拟合
img1 = img.copy()
x, y, w, h = cv2.boundingRect(cnt)
area = cv2.contourArea(cnt)
aspect_ratio = float(w)/h  # 长宽比
rect_area = w*h
extent = float(area)/rect_area  # 轮廓面积与边界矩形面积的比。
hull = cv2.convexHull(cnt)
hull_area = cv2.contourArea(hull)
solidity = float(area)/hull_area  # 轮廓面积与凸包面积的比。
cv2.rectangle(img1, (x, y), (x+w, y+h), (0, 255, 0), 2)
text1 = 'Aspect Ration: ' + str(round(aspect_ratio, 4))
text2 = 'Extent:  ' + str(round(extent, 4))
text3 = 'Solidity: ' + str(round(solidity, 4))
cv2.putText(img1, text1, (10, 30), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)
cv2.putText(img1, text2, (10, 60), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)
cv2.putText(img1, text3, (10, 90), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)# 最小矩形拟合
img2 = img.copy()
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)  # 获得矩形角点
area = cv2.contourArea(box)
width = rect[1][0]
height = rect[1][1]
cv2.polylines(img2, [box], True, (0, 255, 0), 3)
text1 = 'Width: ' + str(int(width)) + ' Height: ' + str(int(height))
text2 = 'Rect Area: ' + str(area)
cv2.putText(img2, text1, (10, 30), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)
cv2.putText(img2, text2, (10, 60), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)# 圆拟合
img3 = img.copy()
(x, y), radius = cv2.minEnclosingCircle(cnt)
center = (int(x), int(y))
radius = int(radius)
area = cv2.contourArea(cnt)
equi_diameter = np.sqrt(4*area/np.pi)
cv2.circle(img3, center, radius, (0, 255, 0), 2)
text1 = 'Center: (' + str(int(x)) + ', ' + str(int(y)) + ') '
text2 = 'Diameter: ' + str(2*radius)
cv2.putText(img3, text1, (10, 30), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)
cv2.putText(img3, text2, (10, 60), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)# 椭圆拟合
img4 = img.copy()
ellipse = cv2.fitEllipse(cnt)
(x, y), (a, b), angle = cv2.fitEllipse(cnt)
cv2.ellipse(img4, ellipse, (0, 255, 0), 2)
text1 = 'x: ' + str(int(x)) + ' y: ' + str(int(y))
text2 = 'a:  ' + str(int(a)) + ' b:  ' + str(int(b))
text3 = 'angle: ' + str(round(angle, 2))
cv2.putText(img4, text1, (10, 30), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)
cv2.putText(img4, text2, (10, 60), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)
cv2.putText(img4, text3, (10, 90), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)# 直线拟合
img5 = img.copy()
rows, cols = img.shape[:2]
[vx, vy, x, y] = cv2.fitLine(cnt, cv2.DIST_L2, 0, 0.01, 0.01)
slope = -float(vy)/float(vx)  # 直线斜率
lefty = int((x*slope) + y)
righty = int(((x-cols)*slope)+y)
cv2.line(img5, (cols-1, righty), (0, lefty), (0, 255, 0), 2)
text1 = 'Center: (' + str(int(x)) + ', ' + str(int(y)) + ') '
text2 = 'Slope: ' + str(round(slope, 2))
cv2.putText(img5, text1, (10, 30), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)
cv2.putText(img5, text2, (10, 60), font, 0.5, (0, 255, 0), 1, cv2.LINE_AA, 0)plt.subplot(231), plt.imshow(cv2.cvtColor(img0, cv2.COLOR_BGR2RGB)), plt.title('Pole')
plt.subplot(232), plt.imshow(cv2.cvtColor(img1, cv2.COLOR_BGR2RGB)), plt.title('Rectangle')
plt.subplot(233), plt.imshow(cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)), plt.title('Rectangle')
plt.subplot(234), plt.imshow(cv2.cvtColor(img3, cv2.COLOR_BGR2RGB)), plt.title('Circle')
plt.subplot(235), plt.imshow(cv2.cvtColor(img4, cv2.COLOR_BGR2RGB)), plt.title('Ellipse')
plt.subplot(236), plt.imshow(cv2.cvtColor(img5, cv2.COLOR_BGR2RGB)), plt.title('Line')
plt.show()

(openCV 十九)轮廓Contours形状拟合相关推荐

  1. opencv笔记二十九(轮廓发现)findContours(t2, contour, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));

    API: cv::findContours( //发现轮廓 InputOutputArray  binImg, // 输入图像,非0的像素被看成1,0的像素值保持不变,8-bit OutputArra ...

  2. 《OpenCv视觉之眼》Python图像处理十九:Opencv图像处理实战四之通过OpenCV进行人脸口罩模型训练并进行口罩检测

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

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

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

  4. OpenCV C++案例实战二十九《遥感图像分割》

    OpenCV C++案例实战二十九<遥感图像分割> 前言 一.准备数据 二.K-Means分类 三.效果显示 四.源码 总结 前言 本案例基于k-means机器学习算法进行遥感图像分割.主 ...

  5. OpenCV C++案例实战十九《制作电子相册查看器》

    OpenCV C++案例实战十九<制作电子相册查看器> 前言 一.图片读取 二.图片展示 三.键盘控制 四.效果显示 五.源码 总结 前言 本文将使用OpenCV C++ 制作电子相册查看 ...

  6. OpenCV系列之轮廓分层 | 二十五

    目标 这次我们学习轮廓的层次,即轮廓中的父子关系. 理论 在前几篇关于轮廓的文章中,我们已经讨论了与OpenCV提供的轮廓相关的几个函数.但是当我们使用cv.findcontour()函数在图像中找到 ...

  7. opencvsharp_基于轮廓的形状匹配中匹配坐标与旋转角度

    本篇博客不讲理论! 需要看理论的这里附上三个博客: ① 一步一步实现多尺度多角度的形状匹配算法(C++版本) ② 图像的矩,以及利用矩求图像的重心,方向 ③ OpenCV学习(十九) :图像的矩:mo ...

  8. 数字图像处理:第十九章 立体视觉

    第十九章 立体视觉 目录 1.    引言 2.    双目立体视觉(BinocularStereo Vision) 2.1 双目立体视觉模型 2.2 匹配基元 2.3 匹配算法 2.4 双目立体视觉 ...

  9. Python+OpenCV:图像轮廓

    Python+OpenCV:图像轮廓 轮廓是什么? 轮廓可以简单地解释为一条连接所有连续点(沿边界)的曲线,具有相同的颜色和强度. 轮廓线是形状分析.目标检测和识别的重要工具. 为了获得更好的精度,可 ...

最新文章

  1. Win7 64位的SSDTHOOK(1)---SSDT表的寻找
  2. springboot + ApplicationListener
  3. 爆料人透露苹果正开发可折叠iPhone:两块独立屏幕连接 无刘海
  4. C++模板函数/类示例
  5. Sourcetree使用 - git图形化工具(三)
  6. 一步步写俄罗斯方块(二)
  7. SSD Single shot detection 单发多框检测 实现 多尺度锚框 动手学深度学习v2
  8. 计算机在食品科学中的应用统计学,响应面法及其在食品中的应用
  9. 帆软之使用FineTube将其他来源数据同步至简道云表单(多图预警)
  10. “我的一剂良药”之开源指北
  11. 杨涛:正解“街区制、密路网”
  12. 邮政挂号信终于可以网上查询了
  13. 声纹技术(三):声纹识别技术
  14. CCF CSP 认证相关
  15. 2021年中国苹果及苹果加工品进出口情况:我国苹果干进出口均价均有所上涨[图]
  16. GITC--2014全球互联网技术大会正式开始售票
  17. 编写strcpy函数
  18. 发那科机器人网段_FANUC机器人以太网通讯手册
  19. 360安全服务器组件怎样禁止,如何禁用360安全浏览器服务组件?如何正确的操作...
  20. 调查显示,“大辞职潮”对经理层打击最为严重,工作倦怠成为离职的关键原因 | 美通社头条...

热门文章

  1. 使用Office Deployment Tool离线安装Office 365
  2. 放一块超实用的黑板,让房间文艺又暖心
  3. 关于ParallelsDesktop10在win7虚拟机重启后分辨率无法保存的问题
  4. 程序员如何做自媒体?3年原创20w粉丝,来怒答一波~
  5. Linux——(3-vim and 用户权限 组)
  6. 有哪些可以直接PS图片的在线工具呀
  7. JQueryAjax
  8. 尼尔 斗技场 机器人_尼尔机械纪元竞技场ex难度全关卡打法流程图文攻略 准备工作-游侠网...
  9. scp命令在两台linux之间传输文件
  10. 获取java项目路径_Java获取项目路径