OpenCV-Python 形状轮廓拟合
程序员文章站
2022-05-28 14:28:21
...
版权声明:本文为CSDN博主「-牧野-」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/dcrmg/article/details/89927816
本文在原文的基础加了些许函数参数及其功能解释,方便阅读
"""
threshold(src, thresh, maxval, type[, dst])->ret,dst
src::灰度图
thresh:阈值
maxval:最大值
type:阈值类型
对于最后一个参数,常见的阈值类型有:
THRESH_BINARY=0,THRESH_BINARY_INV,THRESH_TRUNC,THRESH_TOZERO,THRESH_TOZERO_INV,THRESH_OTSU,THRESH_TRIANGLE,THRESH_MASK
THRESH_OTSU:适合于双峰图像,该参数可自动根据图片的直方图计算出合适的阈值(对于非双峰图,这种方法得到的结果可能不理想)
此时 多传入一个参数cv2.THRESH_OTSU,并且把阈值thresh设为0,算法会找到最优阈值,并作为第一个返回值ret返回。
https://blog.csdn.net/weixin_35732969/article/details/83779660
THRESH_TRIANGLE:实现自动全局阈值寻找的方法,当图像的直方图只有一个波峰,这个时候使用TRIANGLE方法寻找阈值是比较好的一个选择。
https://zhuanlan.zhihu.com/p/64622926
返回:第一个retVal(得到的阈值值),第二个就是阈值化后的图像。
"""
"""
cv2.findContours(image, mode, method[, contours[, hierarchy[, offset ]]])
image:寻找轮廓的图像
mode:轮廓检索模式
cv2.RETR_EXTERNAL 表示只检测外轮廓
cv2.RETR_LIST 检测的轮廓不建立等级关系
cv2.RETR_CCOMP 建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
cv2.RETR_TREE 建立一个等级树结构的轮廓。
contours:轮廓近似方法
cv2.CHAIN_APPROX_NONE 存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1
cv2.CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS 使用teh-Chinl chain 近似算法
返回值:
一个是轮廓本身,还有一个是每条轮廓对应的属性。
"""
```python
# 形状轮廓拟合
import cv2
import numpy as np
im = cv2.imread('test2.jpg')
imgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) #转为 二值化图像
ret,thresh = cv2.threshold(imgray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) # 大津阈值
# https://blog.csdn.net/hjxu2016/article/details/77833336
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) #cv2.RETR_EXTERNAL 定义只检测外围轮廓
cnts = contours[0]
for cnt in cnts:
# 外接矩形框,没有方向角
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(im, (x, y), (x + w, y + h), (0, 255, 0), 2)
# 最小外接矩形框,有方向角
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
cv2.drawContours(im, [box], 0, (0, 0, 255), 2)
# 最小外接圆
(x, y), radius = cv2.minEnclosingCircle(cnt)
center = (int(x), int(y))
radius = int(radius)
cv2.circle(im, center, radius, (255, 0, 0), 2)
# 椭圆拟合
"""
https://blog.csdn.net/qq_33950926/article/details/111409635
ellipse 为元组类型,其里面的参数为:
(x, y) 代表椭圆中心点的位置
(a, b) 代表长短轴长度,应注意a、b为长短轴的直径,而非半径
angle 代表了中心旋转的角度
"""
ellipse = cv2.fitEllipse(cnt)
print("椭圆的中心点为:" + str(ellipse[0]))
cv2.ellipse(im, ellipse, (255, 255, 0), 2)
# 直线拟合
rows, cols = im.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)
im = cv2.line(im, (cols - 1, righty), (0, lefty), (0, 255, 255), 2)
cv2.imshow('a_result',im)
cv2.waitKey(0)
上一篇: 太喜欢夏天了
下一篇: Linux自动同步时间