【问题标题】:opencv can't extract biggest contour in imageopencv无法提取图像中的最大轮廓
【发布时间】:2021-05-30 19:29:53
【问题描述】:

考虑这张图片:

我只想提取代表图像中最大轮廓的数字,但 opencv 总是显示原始图像和小于数字的小轮廓。所以当我运行这个函数时

def contouTreat(image):
  gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
  cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  cnts = cnts[0] if len(cnts) == 2 else cnts[1]
  (cnts, _) = contours.sort_contours(cnts, method="left-to-right")
  cv2.drawContours(image, cnts, -1, (0, 255, 0), 3)
  #cv2_imshow(image)
  ROI_number = 0
  arr=[]
  v=True 
  for c in cnts:
   area = cv2.contourArea(c)
   if area != image.shape[1]*image.shape[0]:
     x,y,w,h = cv2.boundingRect(c)
     #if minc != x:
     
     x,y,w,h = cv2.boundingRect(c)
     #if area < 800 and area > 200:
     #if area < 1620   and h>58 and w <50:
     #if  h>(70*image.shape[1])/100 and w>(60*image.shape[0])/100 :
     if v:
         ROI = image[y:y+h, x:x+w] 
         print(h)
         print(w)
     cv2_imshow(ROI)                 
 return None     
image=cv2.imread("/content/téléchargement (2).png")   
contouTreat(image)

我得到了这个结果:

【问题讨论】:

    标签: python python-3.x opencv computer-vision opencv-contour


    【解决方案1】:

    您在同一张图像上绘制轮廓,因此您将获得更大的 ROI,其中包含两个绘制的轮廓。

    建议的解决方案:
    在填充了零的临时图像上绘制每个轮廓,并从临时图像中裁剪 ROI。

    • 创建用零填充的临时图像:

       tmp_im = np.zeros_like(image)
      
    • 绘制一个填充白色的轮廓,并将其用作蒙版:

       cv2.drawContours(tmp_im, [c], 0, (255, 255, 255), cv2.FILLED)  # Draw white contour on black image
       tmp_im = cv2.bitwise_and(image, tmp_im)  # Apply bitwise with `image` - required in case there are black regions inside the contour.
      
    • 在轮廓周围画绿线(可能不需要):

       cv2.drawContours(tmp_im, [c], -1, (0, 255, 0), 3)  # Draw green line around the contour
      
    • 裁剪 ROI:

       ROI = tmp_im[y:y + h, x:x + w]
      

    完整的代码示例:

    import numpy as np
    import cv2
    from imutils import contours
    
    def contouTreat(image):
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
        cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        cnts = cnts[0] if len(cnts) == 2 else cnts[1]
        (cnts, _) = contours.sort_contours(cnts, method="left-to-right")
        cv2.drawContours(image, cnts, -1, (0, 255, 0), 3)
        #cv2_imshow(image)
        ROI_number = 0
        arr = []
        v = True 
        for c in cnts:
            area = cv2.contourArea(c)
            if area != image.shape[1] * image.shape[0]:
                x,y,w,h = cv2.boundingRect(c)
                   
                if v:
                    tmp_im = np.zeros_like(image)
                    cv2.drawContours(tmp_im, [c], 0, (255, 255, 255), cv2.FILLED)  # Draw white contour on black image
                    tmp_im = cv2.bitwise_and(image, tmp_im)  # Apply bitwise with `image` - required in case there are black regions inside the contour.
                    cv2.drawContours(tmp_im, [c], -1, (0, 255, 0), 3)  # Draw green line around the contour
    
                    ROI = tmp_im[y:y + h, x:x + w]
    
                    print(h)
                    print(w)
    
                cv2.imshow('ROI' + str(ROI_number), ROI)
                ROI_number += 1
    
        return None
    
    
    image = cv2.imread("telechargement.png")
    
    contouTreat(image)
    
    cv2.waitKey()
    cv2.destroyAllWindows()
    

    结果:

    ROI0:

    ROI1:

    【讨论】:

    • cv2 有一个小问题。Filled 会导致数字 8 和 9 填充空白,这会影响我的 mnist 训练模型的结果。
    • 对...在cv2.drawContours(tmp_im, [c], 0, (255, 255, 255), cv2.FILLED)之后添加tmp_im = cv2.bitwise_and(image, tmp_im)(我更新了帖子)
    猜你喜欢
    • 1970-01-01
    • 2011-11-27
    • 1970-01-01
    • 1970-01-01
    • 2020-05-08
    • 2013-12-17
    • 2014-04-24
    • 2012-11-15
    • 1970-01-01
    相关资源
    最近更新 更多