我正在尝试使用简单的OpenCV
轮廓方法从下面的图像中提取数字,但我在轮廓上得到重叠的边界框
cv2.RETR_EXTERNAL
应该只返回层次结构中的外部轮廓,但从下面的输出可以看出它不起作用
代码:
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')
要求:
opencv-python==3.4.5.20
matplotlib==3.1.2
最佳答案
您需要进行模糊处理,然后在找到轮廓之前应用阈值。您需要这样做,因为如果您直接在灰度图像上找到轮廓,则会有微小的颗粒被拾取为轮廓。这是一个简单的过程:
- 加载图像、灰度、高斯模糊、Otsu 阈值
- 使用
imutils.contours.sort_contours()
查找轮廓并排序使用从左到右
参数 - 获取边界框,然后使用 Numpy 切片提取 ROI
这是检测到的边界框,以绿色突出显示
提取/保存的 ROI
代码
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()
关于python - 如何从图像中仅提取外部轮廓(OpenCV),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59858377/