首页 > 解决方案 > Fill empty enclosed parts from image

问题描述

Before

After

I'm looking for an algorithm that would produce the result I'm showing above. I tried so far some dilatation and erosion from PIL but the results are not the ones I'm looking for because I'm losing some essential details of the letters. Furthermore, they tend to be very bold afterwards, and erosion doesn't help. My second try was some type of flood algorithm, but I can't think of anything useful, as some letters have gaps, and I don't know how to deal with this. I would highly appreciate if you could guide me towards some idea of algorithm in order to solve this problem.

标签: pythonimage-processingpython-imaging-library

解决方案


正如上面提到的 Mark Setchell,您可以使用cv2.findContours然后使用层次结构来查找字母的孔。

首先,我找到图像中的所有轮廓。

为了找到字母的洞,我使用层次结构来获取没有子元素的轮廓(最内轮廓),然后用黑色填充白色(称为蒙版图像)。我还应用了一个区域阈值来去除字母内的小黑点并只保留孔。阈值是area>int(w*h/200)w,h是图像的长度和宽度。

我用黑色填充灰色图像中的轮廓。然后我只是添加灰度图像和蒙版图像)以获得最终结果。

这是代码。

import cv2
import numpy as np

img = cv2.imread("1.png")

print(img.shape)
w = img.shape[0]
h = img.shape[1]

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_,thresh = cv2.threshold(gray,128,255,cv2.THRESH_BINARY_INV)

im2, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours,-1,(0,0,255),1)

mask = np.zeros(gray.shape, dtype="uint8")

for i in range(len(contours)):
    area = cv2.contourArea(contours[i])
    print(hierarchy[0][i][2])
    if(hierarchy[0][i][2]==-1 and area>int(w*h/200)): #contour has no child
        cv2.fillPoly(mask, pts =[contours[i]], color=255)
    cv2.fillPoly(gray, pts =[contours[i]], color=0)

res = mask + gray

cv2.imshow("img", img)    
cv2.imshow("gray", gray)      
cv2.imshow("mask", mask)
cv2.imshow("res", res)

cv2.waitKey()
cv2.destroyAllWindows() 

在此处输入图像描述


推荐阅读