纯净、安全、绿色的下载网站

首页|软件分类|下载排行|最新软件|IT学院

当前位置:首页IT学院IT技术

OpenCV 轮廓拟合 OpenCV-Python实现轮廓拟合

一天一篇Python库   2021-06-08 我要评论
想了解OpenCV-Python实现轮廓拟合的相关内容吗一天一篇Python库在本文为您仔细讲解OpenCV 轮廓拟合的相关知识和一些Code实例欢迎阅读和指正我们先划重点:OpenCV,轮廓拟合下面大家一起来学习吧

前言

什么是轮廓?

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

  • 为了更加准确要使用二值化图像在寻找轮廓之前要进行阈值化处理 或者 Canny 边界检测
  • 查找轮廓的函数会修改原始图像如果你在找到轮廓之后还想使用原始图 像的话你应该将原始图像存储到其他变量中
  • 在 OpenCV 中查找轮廓就像在黑色背景中超白色物体你应该记住 要找的物体应该是白色而背景应该是黑色

在计算轮廓时可能并不需要实际的轮廓而仅需要一个接近于轮廓的近似多边形比如矩形其实都是差不多的轮廓都是长宽不相等且平行的四边形那么只要提供一个近似的轮廓我们就可以区分形状

在OpenCV中它给我们提供了cv2.boundingRect()函数来绘制轮廓的矩形边界其完整定义如下:

def boundingRect(array):

array:前面已经介绍过array是一个灰度图像或者轮廓

该函数返回3个值时是矩形边界的左上角顶点的坐标值以及矩形边界的宽与高返回4个值时是矩形左上角顶点的x坐标y坐标以及宽高

绘制椭圆的矩形边界

现在我们还是使用前面的一张椭圆图形如下图所示:

椭圆

得到图形之后我们使用上面的函数计算该图像轮廓的4值代码如下:

import cv2

img = cv2.imread("26_1.jpg")

# 转换为灰度图像
gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
x, y, w, h = cv2.boundingRect(contours[0])
print(x, y, w, h)

运行之后控制台输出如下内容:

输出值

这里我们得到了椭圆的矩形左上角坐标为(53120)其宽高分别为272与84

既然我们已经得到了其矩形边界的坐标以及宽高那么我们可以开始绘制其矩形边界前面提取轮廓绘制用的是cv2.drawContours()函数这里同样也是

代码如下:

import cv2
import numpy as np

img = cv2.imread("26_1.jpg")
cv2.imshow("img1",img)
# 转换为灰度图像
gray= cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
x, y, w, h = cv2.boundingRect(contours[0])
rect=np.array([[[x,y],[x+w,y],[x+w,y+h],[x,y+h]]])#1
cv2.drawContours(img,[rect],-1,(255,255,255),2)#1

cv2.imshow("img2",img)

cv2.waitKey()
cv2.destroyAllWindows()

运行之后其椭圆的矩形边界就被我们标记出来了效果如下:

矩形边界

当然这里我们还可以使用另一个函数cv2.rectangle()来绘制矩形边界值需要更换上面代码中注释1的两个代码具体如下所示:

cv2.rectangle(img, (x, y), (x + w, y + h), (255, 255,255),2)

最小包围矩形框

在OpenCV中它还提供了cv2.minAreaRect()来绘制最小包围矩形框其完整定义如下:

def minAreaRect(points):

其中points参数是轮廓返回值为矩形特征信息包括矩形的中心(x,y)宽高以及旋转角度

特别注意minAreaRect函数的返回值并不能直接代入drawContours()函数中因此我们必须将其转换为符合要求的结构才能接着操作通过cv2.boxPoint()函数就可以转换为符合drawContours()的结构参数

还是上面那张图不过我们用旋转后的椭圆原图代码如下:

import cv2
import numpy as np

img = cv2.imread("26_4.jpg")

cv2.imshow("img1",img)
# 转换为灰度图像
gray= cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
rect= cv2.minAreaRect(contours[0])
print(rect)
points=cv2.boxPoints(rect)
print(points)
points=np.int0(points)
print(points)
cv2.drawContours(img,[points],0,(255,255,255),2)

cv2.imshow("img2",img)

cv2.waitKey()
cv2.destroyAllWindows()

运行之后图像效果以及控制台的输出信息如下:

最小轮廓

值的转换过程

这里我们可以清楚的看到minAreaRect()函数返回值的转换过程先通过boxPoints()函数转换为drawContours()函数能接受的参数格式然后通过取整转换为具体的像素坐标值

最小包围圆形框

既然有最小包围矩形框那么一定就有最小包围圆形框在OpenCV中它给我们提供cv2.minEnclosingCircle()函数来绘制最小包围圆形框

函数的完整定义如下:

def minEnclosingCircle(points): 

这里的参数与上面的points参数一致但是其返回值并不相同毕竟绘制圆形肯定与绘制矩形的参数肯定不一样

它有两个返回值一个是圆形的中心坐标(x,y)一个是圆形的半径r下面我们直接来绘制上面椭圆的最小包围圆形框具体代码如下所示:

import cv2
import numpy as np

img = cv2.imread("26_4.jpg")

cv2.imshow("img1", img)
# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
(x, y), r = cv2.minEnclosingCircle(contours[0])
center = (int(x), int(y))
r = int(r)
cv2.circle(img, center, r, (255, 255, 255), 2)

cv2.imshow("img2", img)

cv2.waitKey()
cv2.destroyAllWindows()

运行之后效果如下所示:

最小圆形框

最优拟合椭圆

在OpenCV中它给我们提供了cv2.fitEllipse()函数绘制最优拟合椭圆其完整的定义如下:

def fitEllipse(points):

其中points参数与前文一致而它的返回值是RotatedRect类型这是因为该函数返回的是拟合椭圆的外接矩形包括矩形的质心宽高旋转角度等信息这些信息正好与椭圆的中心点轴长度旋转角度一致

下面我们来使用该函数绘制最优拟合椭圆这里我们选取如上图所示的一张矩形图具体代码如下:

import cv2

img = cv2.imread("27.jpg")

cv2.imshow("img1", img)
# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
ellipse = cv2.fitEllipse(contours[0])

cv2.ellipse(img, ellipse, (0, 0, 255), 3)

cv2.imshow("img2", img)

cv2.waitKey()
cv2.destroyAllWindows()

运行之后效果如下所示:

最优拟合椭圆

最优拟合直线

在OpenCV中它还提供了cv2.fitLine()函数绘制最优拟合直线其完整定义如下:

def fitEllipse(points):

points:与前文一样是轮廓

distType:距离类型拟合直线时要使输入点到拟合直线的距离之和最小详细参数定义参考开发文档这里不在赘述

param:距离参数与所选距离类型有关当该参数为0时自动选择最优值

reps:用于表示拟合直线所需要的径向精度通常该值被设定为0.01

aeps:用于表示拟合直线所需要的角度精度通常该值被设定为0.01

对于二维直线返回值line为4维前两维代表拟合出的直线的方向后两位代表直线上的一点

下面我们来直接使用代码绘制最优拟合直线

import cv2

img = cv2.imread("27.jpg")

cv2.imshow("img1", img)
# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
ellipse = cv2.fitEllipse(contours[0])

cv2.ellipse(img, ellipse, (0, 0, 255), 3)

cv2.imshow("img2", img)

cv2.waitKey()
cv2.destroyAllWindows()

运行之后效果如下所示:

直线拟合

对于绘制直线来说我们需要获取绘制直线的起点以及终点这里lefty为起点righty为终点

最小外包三角形

在OpenCV它还提供了cv2.minEnclosingTriangle()函数来绘制最小外包三角形其完整定义如下:

def minEnclosingTriangle(points, triangle=None):

其中points与前文类似其返回值triangle为外包三角形的三个顶点集

下面我们直接构建最小外包三角形具体代码如下:

import cv2

img = cv2.imread("27.jpg")

cv2.imshow("img1", img)
# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

area, trg1 = cv2.minEnclosingTriangle(contours[0])
print(area)
print(trg1)
for i in range(0, 3):
    cv2.line(img, tuple(trg1[i][0]), tuple(trg1[(i + 1) % 3][0]), (0, 255, 0), 2)

cv2.imshow("img2", img)

cv2.waitKey()
cv2.destroyAllWindows()

运行之后效果如下:

三角形

需要注意的是在cv2中没有直接绘制三角形的函数所以我们通过绘制三条直线绘制三角形minEnclosingTriangle()函数第一个返回值为三角形面积第二返回值是三点坐标

逼近多边形

在OpenCV中它还提供了cv2.approxPolyDP()函数构建指定边数的逼近多边形其完整定义如下:

def approxPolyDP(curve, epsilon, closed, approxCurve=None): 

curve:轮廓

epsilon:精度原始轮廓的边界点与逼近多边形边界之间的最大距离

closed:布尔类型为True时表示逼近多边形是封闭的为False时biao表示毕竟多边形是不封闭的

approxCurve为该函数的返回值是逼近多边形的点集

下面我们来实现各类逼近多边形的绘制代码如下:

import cv2

img = cv2.imread("24.jpg")

list=[0.1,0.09,0.055,0.05,0.02]

cv2.imshow("img", img)
# 转换为灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, hierarchy = cv2.findContours(binary, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

for i, val in enumerate(list):
    epsilon = val * cv2.arcLength(contours[0], True)
    approx = cv2.approxPolyDP(contours[0], epsilon, True)
    cv2.drawContours(img, [approx], 0, (0, 255, 0), 2)

    cv2.imshow("img"+str(i), img)

cv2.waitKey()
cv2.destroyAllWindows()

运行之后效果如下:

逼近多边形

cv2.approxPolyDP()函数采用的是Douglas-Peucker算法该算法的原理是首先从轮廓中找到距离最远的两个点并将两个点相连接下来在轮廓上找到一个离当前直线最远的点并将该点与原有直线连成一个封闭的多边形此时得到一个三角形以此类推四边形五边形六边形等当前多边形的距离都小于函数cv2.approxPolyDP()的参数epsilon的值时就停止迭代


相关文章

猜您喜欢

  • SpringBoot jackson格式化时间 SpringBoot利用jackson格式化时间的三种方法

    想了解SpringBoot利用jackson格式化时间的三种方法的相关内容吗程序员小杰在本文为您仔细讲解SpringBoot jackson格式化时间的相关知识和一些Code实例欢迎阅读和指正我们先划重点:jackson格式化时间,jackson使用,springboot,jackson下面大家一起来学习吧..
  • Axios二次封装 项目中Axios二次封装实例Demo

    想了解项目中Axios二次封装实例Demo的相关内容吗丰子楷在本文为您仔细讲解Axios二次封装的相关知识和一些Code实例欢迎阅读和指正我们先划重点:axios二次封装教程,axios二次封装及调用,封装axios下面大家一起来学习吧..

网友评论

Copyright 2020 www.fresh-weather.com 【世纪下载站】 版权所有 软件发布

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 点此查看联系方式