python - Opencv连接最近的矩形轮廓

标签 python opencv computer-vision

我名为“img”的输入图像如下:

enter image description here

我有以下代码来检测该图像上的轮廓:

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
grad = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

_, bw = cv2.threshold(grad, 0.0, 255.0, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))
connected = cv2.morphologyEx(bw, cv2.MORPH_CLOSE, kernel)

contours, hierarchy = cv2.findContours(connected.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)


mask = np.zeros(bw.shape, dtype=np.uint8)


for idx in range(len(contours)):
    x, y, w, h = cv2.boundingRect(contours[idx])

    cv2.rectangle(img, (x, y), (x+w-1, y+h-1), (255, 255, 255), 2)
    print(w,x,y)

我得到以下输出:

enter image description here

我的问题是如何在图像的最后 3 条线上连接最近的轮廓。在输出中,我想要 3 个矩形框覆盖 mrz 的 3 行。我已经提到了https://dsp.stackexchange.com/questions/2564/opencv-c-connect-nearby-contours-based-on-distance-between-them/2618#2618但这种方法似乎计算成本很高,我想要一些简单的

最佳答案

下面是一个相对简单的解决方案。评论解释了其背后的想法。

import cv2, numpy as np

img = cv2.imread("test.jpg", cv2.IMREAD_GRAYSCALE)

kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
grad = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

_, bw = cv2.threshold(grad, 0.0, 255.0, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))
connected = cv2.morphologyEx(bw, cv2.MORPH_CLOSE, kernel)

contours, hierarchy = cv2.findContours(connected.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)[-2:]

# y-coordinate of midline of rectangle
def ymid(y, h): return y+int(h/2)

# identify lines (l=0, 1, ...) based on ymid() and estimate line width
ym2l, l, l2w, rects = {}, 0, {}, []
for cont in contours:
    x, y, w, h = cv2.boundingRect(cont)
    rects.append([x, y, w, h])
    ym = ymid(y, h)
    if ym not in ym2l:
        for i in range(-2, 3):   # range of ymid() values allowed for same line 
            if ym+i not in ym2l:
                ym2l[ym+i] = l
        l2w[l] = w
        l += 1
    else:
        l2w[ym2l[ym]] += w

# combine rectangles for "good" lines (those close to maximum width)
maxw, l2r = max(l2w.values()), {}
for x, y, w, h in rects:
    l = ym2l[ymid(y, h)]
    if l2w[l] > .9*maxw:
        if l not in l2r:
            l2r[l] = [x, y, x+w, y+h]
        else:
            x1, y1, X1, Y1 = l2r[l]
            l2r[l] = [min(x, x1), min(y, y1), max(x+w, X1), max(y+h, Y1)]

for x, y, X, Y in l2r.values():
    cv2.rectangle(img, (x, y), (X-1, Y-1), (255, 255, 255), 2)

cv2.imshow("img", img)
cv2.waitKey(0)

结果如下: rectangles

关于python - Opencv连接最近的矩形轮廓,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54897721/

相关文章:

python - 如果第一行为 0,则从 DataFrame 中选择列

java - 更改特定像素周围 24 个像素的最佳方法是什么?

computer-vision - 使用 VLFEAT 实现词袋对象识别

python - 培训OpenCV的透明背景

python - 在 Python 中进行协同程序尾调用时,使用或避免协同程序是否更符合 Pythonic(和/或性能)?

python - 加载pickled数据时cPickle EOFError

node.js - 无法使用 npm 安装 opencv

.net - 计算机视觉库

python - 获取按列年份分组的索引值集

python - 如果与黑白图像一起使用,OpenCV findContours() 会报错