欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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)