【问题标题】:Obtain only external contours in image仅获取图像中的外部轮廓
【发布时间】:2020-03-14 03:40:34
【问题描述】:

我有这段代码,它在我的图像中绘制轮廓,但我只需要外部轮廓:

import cv2
import numpy as np

camino= "C:/Users/Usuario/Documents/Deteccion de Objetos/123.jpg"
img = cv2.imread("C:/Users/Usuario/Documents/Deteccion de Objetos/123.jpg")

grises= cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)

bordes= cv2.Canny(grises, 100, 250)

ctns = cv2.findContours(bordes, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
ctns = ctns[0] if len(ctns)==2 else ctns[1]
for c in ctns:
    cv2.drawContours(img,[c], -1,(0,0,255),2)

print ('Numero de contornos es ', len(ctns))
texto= 'Contornos encontrados ' + str(len(ctns))

cv2.putText(img, texto, (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.7,  
    (255, 0, 0), 1)


cv2.imshow('Bordes', bordes)
cv2.imshow('Imagen', img)
cv2.waitKey(0)
cv2.destroyAllWindows().

这是我的原图:

这是获得的带有轮廓的图像:

在这种情况下,我只需要为每个实体检测 10 个轮廓 1,但它会检测 450 个轮廓。

【问题讨论】:

    标签: python image opencv image-processing contour


    【解决方案1】:

    这是一种使用阈值+形态学运算+轮廓过滤的方法

    首先我们转换为灰度,然后转换为二值图像的 Otsu 阈值(左),然后使用轮廓区域过滤去除虚线(右)

    从这里我们执行 morph close 以删除文本然后反转图像(左)。我们找到轮廓并将所有小于阈值的轮廓填充为黑色(右)

    接下来我们再次反转并使用大矩形内核执行变形打开以去除小边缘和尖峰

    最后我们找到轮廓来得到我们的结果

    import cv2
    
    image = cv2.imread('1.jpg')
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blur = cv2.GaussianBlur(gray, (5,5), 0)
    thresh = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
    
    # Remove dotted lines
    cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    for c in cnts:
        area = cv2.contourArea(c)
        if area < 5000:
            cv2.drawContours(thresh, [c], -1, (0,0,0), -1)
    
    # Fill contours
    close_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
    close = 255 - cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, close_kernel, iterations=6)
    cnts = cv2.findContours(close, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    for c in cnts:
        area = cv2.contourArea(c)
        if area < 15000:
            cv2.drawContours(close, [c], -1, (0,0,0), -1)
    
    # Smooth contours
    close = 255 - close
    open_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (20,20))
    opening = cv2.morphologyEx(close, cv2.MORPH_OPEN, open_kernel, iterations=3)
    
    # Find contours and draw result
    cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    for c in cnts:
        cv2.drawContours(image, [c], -1, (36,255,12), 3)
    
    cv2.imshow('thresh', thresh)
    cv2.imshow('opening', opening)
    cv2.imshow('image', image)
    cv2.waitKey()
    

    【讨论】:

    • 您好,您的代码适用于某些图像,但现在我需要对其他模式(如 sqlserver phpmyadmin 等)执行相同操作,您能帮帮我吗?这是查询:stackoverflow.com/questions/59852382/…
    • 尝试调整内核大小和迭代次数。很难找到适用于所有图像的解决方案
    【解决方案2】:

    您可以尝试将洪水填充与一些变形运算符结合使用。

    【讨论】:

      猜你喜欢
      • 2012-11-15
      • 2020-05-08
      • 2020-07-22
      • 2019-03-27
      • 2016-06-25
      • 2019-03-23
      • 2019-08-15
      • 2014-11-02
      • 2018-06-21
      相关资源
      最近更新 更多