如何仅从图像中提取外部轮廓(OpenCV) [英] How to extract only outer contours from an image (OpenCV)

查看:83
本文介绍了如何仅从图像中提取外部轮廓(OpenCV)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用简单的 OpenCV 等高线方法从下面的图像中提取数字,但是我在等高线上重叠了边界框

cv2.RETR_EXTERNAL 应该仅返回层次结构中的外部轮廓,但是从下面的输出中可以看出,它不起作用

代码:

从matplotlib中的

 导入pyplot作为plt导入cv2img = cv2.imread('image.png',0)_,轮廓,_ = cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)imgRGB = cv2.cvtColor(img.copy(),cv2.COLOR_GRAY2RGB)对于轮廓中的c:x,y,w,h = cv2.boundingRect(c)cv2.rectangle(imgRGB,(x,y),(x + w,y + h),(0,255,0),2)无花果= plt.figure()斧= fig.add_subplot(111)ax.imshow(imgRGB,cmap ='gray') 

要求:

  opencv-python == 3.4.5.20matplotlib == 3.1.2 

解决方案

在查找轮廓之前,您需要先模糊然后应用阈值.您需要执行此操作,因为如果直接在灰度图像上找到轮廓,则会有细小颗粒被拾取为轮廓.这是一个简单的过程:

  • 加载图像,灰度,高斯模糊,大津的阈值
  • 找到轮廓并使用

    提取/保存的投资回报率

    代码

      import cv2从imutils导入轮廓图片= cv2.imread('1.png')原始= image.copy()灰色= cv2.cvtColor(图像,cv2.COLOR_BGR2GRAY)模糊= cv2.GaussianBlur(灰色,(3,3),0)阈值= cv2.threshold(灰色,0,255,cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]cnts = cv2.findContours(阈值,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)如果len(cnts)== 2,则cnts = cnts [0]否则,cnts [1](cnts,_)= outlines.sort_contours(cnts,method ="left-to-right")num = 0对于C中的cnts:x,y,w,h = cv2.boundingRect(c)cv2.rectangle(image,(x,y),(x + w,y + h),(36,255,12),1)投资报酬率=原始[y:y + h,x:x + w]cv2.imwrite('ROI _ {}.png'.format(num),ROI)num + = 1cv2.imshow('image',image)cv2.waitKey() 

    I am trying to extract digits from the below image using simple OpenCV contours approach, but I am getting overlapping bounding boxes over contours

    cv2.RETR_EXTERNAL should return only outer contours in the hierarchy but it’s not working as can be seen from the below output

    Code:

    from matplotlib import pyplot as plt
    import cv2
    
    img = cv2.imread('image.png', 0)
    
    _, contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    
    imgRGB = cv2.cvtColor(img.copy(), cv2.COLOR_GRAY2RGB)
    
    for c in contours:
        x,y,w,h = cv2.boundingRect(c)
        cv2.rectangle(imgRGB, (x, y), (x+w, y+h), (0,255,0), 2)
    
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.imshow(imgRGB, cmap='gray')
    

    Requirements:

    opencv-python==3.4.5.20
    matplotlib==3.1.2
    

    解决方案

    You need to blur then apply a threshold before finding contours. You need to do this because if you find contours directly on the grayscale image, there are tiny particles which are picked up as contours. Here's a simple process:

    • Load image, grayscale, Gaussian blur, Otsu's threshold
    • Find contours and sort using imutils.contours.sort_contours() with the left-to-right parameter
    • Obtain bounding box then extract ROI using Numpy slicing

    Here's the detected bounding boxes highlighted in green

    Extracted/saved ROIs

    Code

    import cv2
    from imutils import contours
    
    image = cv2.imread('1.png')
    original = image.copy()
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (3,3), 0)
    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")
    num = 0
    for c in cnts:
        x,y,w,h = cv2.boundingRect(c)
        cv2.rectangle(image, (x, y), (x + w, y + h), (36,255,12), 1)
        ROI = original[y:y+h, x:x+w]
        cv2.imwrite('ROI_{}.png'.format(num), ROI)
        num += 1
    
    cv2.imshow('image', image)
    cv2.waitKey()
    

    这篇关于如何仅从图像中提取外部轮廓(OpenCV)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆