问题描述
我有这段代码,可以在图像中绘制轮廓,但是我只需要外部轮廓即可.
I have this code, that draws contours in my image, but I need only the external contours:
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().
这是我的原始图片:
This is my original image:
这是获得的具有轮廓的图像:
This is the obtained image with the contours:
在这种情况下,我只需要为每个实体检测10个轮廓1,但它可以检测到450个轮廓.
In this case I just only need to detect 10 contours 1 for each entity, but it detects 450 contours.
推荐答案
这是一种使用阈值处理+形态运算+轮廓滤波的方法
Here's an approach using thresholding + morphological operations + contour filtering
首先我们将其转换为灰度,然后将Otsu的阈值转换为二进制图像(左),然后使用轮廓区域过滤去除虚线(右)
First we convert to grayscale then Otsu's threshold for a binary image (left) then remove dotted lines using contour area filtering (right)
从这里开始,执行morph close操作以删除文本,然后反转图像(左).我们找到轮廓并填充所有小于黑色阈值的轮廓(右)
From here we perform morph close to remove the text then invert the image (left). We find contours and fill all contours smaller than a threshold to black (right)
接下来,我们再次反转并使用大矩形核执行变形打开操作,以去除小的边缘和尖峰
Next we invert again and perform morph open with a large rectangle kernel to remove the small edges and spikes
最后我们找到轮廓以得到结果
Finally we find contours to get our result
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()
这篇关于仅获取图像中的外部轮廓的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!