首页 文章

OpenCV Python:语音气泡形状的闭合轮廓逼近

提问于
浏览
1

我有一个像讲话泡泡的形状 . 我只想检测这个形状的椭圆,就像绿色环绕的图像一样 .

我尝试了封闭的形态,但也消除了气泡的某些部分 . 我使用了一个矩阵为20,20的内核 . 形状变得更加矩形 . 也许我必须更改内核矩阵更像这样:

0 1 0
1 1 1
0 1 0

我也试图绘制一个凸包,但它也没有效果 . 并且内部凸壳是不可能的 . 这是我绘制凸包的代码:

for i in range (max_index):
    hull = cv2.convexHull(contours[i])
    cv2.drawContours(image, [hull], 0, (0, 255, 0), 2)

我使用参数 cv2.RETR_EXTERNALcv2.CHAIN_APPROX_NONE 检索了轮廓

1 回答

  • 3

    这是我能得到的最好的:

    这不是最聪明的方法 . 尽管代码冗长,但我在这里做的事实上很简单 .

    首先,我得到灰色图像并添加大量模糊,并以您尝试的相同方式,应用阈值并查找轮廓 . 然后我拿出最大的轮廓,找到适合这个轮廓的椭圆 fitEllipse . 这都是 getEllipse 函数 .

    在第一轮中,椭圆将会歪斜,因为尾部会挡住 . 所以,我使用这个不太好的椭圆来处理原始图像并再试一次 .

    函数grayEllipse按椭圆过滤图像 . 因此,我使用第一次尝试的椭圆来处理原始图像并突出显示第一个椭圆内的点 . 我在第二轮中使用此图像作为输入 .

    通过重复这个过程,我第二次得到的最后一个椭圆就不那么歪斜了 .

    这是代码:

    import cv2
    import numpy as np
    
    
    def getEllipse(imgray):
    
    
        ret, thresh = cv2.threshold(imgray, 20, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
        _, contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    
        maxArea = 0
        best = None
        for contour in contours:
            area = cv2.contourArea(contour)
            if area > maxArea :
                maxArea = area
                best = contour
    
        ellipse = cv2.fitEllipse(best)
        el = np.zeros(imgray.shape)
        cv2.ellipse(el, ellipse,(255,255,255),-1)
    
        return el
    
    def grayEllipse(el, img):
        el = np.dstack((el,el,el))
        el = el*img
        el = el/(255)
        el = el.astype('uint8')
        imgray = cv2.cvtColor(el, cv2.COLOR_BGR2LAB)[...,0]
        return imgray
    
    
    image = cv2.imread("./baloon.png", cv2.IMREAD_COLOR)
    img = image.copy()
    imgray = cv2.cvtColor(image, cv2.COLOR_BGR2LAB)[...,0]
    imgray = cv2.GaussianBlur(imgray, (79,79), 0)
    el = getEllipse(imgray)
    imgray = grayEllipse(el, img.copy())
    imgray = cv2.GaussianBlur(imgray, (11,11), 0)
    el = getEllipse(imgray)
    imgray = grayEllipse(el, img.copy())
    
    ret, thresh = cv2.threshold(imgray, 20, 255, cv2.THRESH_BINARY|cv2.THRESH_OTSU)
    _, contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
    
    maxArea = 0
    best = None
    for contour in contours:
        area = cv2.contourArea(contour)
        if area > maxArea :
            maxArea = area
            best = contour
    
    ellipse = cv2.fitEllipse(best)
    cv2.ellipse(image, ellipse, (0,255,0),3)
    
    while True:
      cv2.imshow("result", image)
      k = cv2.waitKey(30) & 0xff
      if k == 27:
          break
    

相关问题