OpenCV-Python 形状轮廓拟合

版权声明:本文为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)


猜你喜欢

转载自blog.csdn.net/qq_38828370/article/details/119759530