3

我想在图像中的水印周围画一个框。我已经提取了水印并找到了轮廓。然而,轮廓不是围绕水印绘制的。轮廓是在我的完整图像上绘制的。请帮助我正确的代码。

轮廓坐标的输出为:

[array([[[  0,   0]],

       [[  0, 634]],

       [[450, 634]],

       [[450,   0]]], dtype=int32)]

输出图像为:

在此处输入图像描述

我的代码片段如下:

img = cv2.imread('Watermark/w3.png')

gr = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
bg = gr.copy()

closing = cv2.morphologyEx(bg, cv2.MORPH_CLOSE, kernel)  #dilation followed by erosion
#plt.imshow(cv2.subtract(img,opening))
plt.imshow(closing)

_,contours, hierarchy = cv2.findContours(closing, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print(contours)
print(len(contours))

if len(contours)>0 :
    cnt=contours[len(contours)-1]
    cv2.drawContours(closing, [cnt], 0, (0,255,0), 3)
    
plt.imshow(closing)
4

1 回答 1

3

该函数findContours难以找到您的框轮廓,因为预计会在二进制图像上运行。从文档中:

为了获得更好的准确性,请使用二值图像。所以在寻找轮廓之前,应用阈值或精确边缘检测。

在 OpenCV 中,寻找轮廓就像从黑色背景中寻找白色物体。所以请记住,要找到的对象应该是白色的,背景应该是黑色的。

因此,在cvtColor应用功能后threshold确保您有黑色背景。

...
img = cv2.imread('sample.png')
gr = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, bg = cv2.threshold(gr, 127, 255, cv2.THRESH_BINARY_INV)
...

如果你findContours在这个二进制图像上运行,你会发现多个框

在此处输入图像描述 在此处输入图像描述

要在整个文本周围获得一个框,您可以在创建单个 blobiterations的函数上搜索参数 的数量。morphologyEx

...
kernel = np.ones((3,3))
closing = cv2.morphologyEx(bg, cv2.MORPH_CLOSE, kernel, iterations=5)
...

因此,在创建 blob 后,应用findContours您已经拥有的并使用minAreaRect找到旋转的矩形,其最小面积包含所传递的点集。

...
contours, hierarchy = cv2.findContours(closing, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))

for i in range(len(contours)):
    rect = cv2.minAreaRect(contours[i])
    box = cv2.boxPoints(rect)
    box = np.int0(box)
    cv2.drawContours(img,[box],0,(127,60,255),2)

cv2.imwrite("output_box.png", img)

在此处输入图像描述 在此处输入图像描述

于 2020-09-06T17:18:07.507 回答