如何在 Canny 边缘检测后填补字母间的空隙

3
我正在尝试使用Tesseract进行阿拉伯语OCR,但是除非字母被填充为黑色,否则OCR无法正常工作。如何在Canny边缘检测后填充间隙?
这是一个示例图像和示例代码: enter image description here
import tesserocr
from PIL import Image
import pytesseract
import matplotlib as plt
import cv2
import imutils
import numpy as np

image = cv2.imread(r'c:\ahmed\test3.png')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

gray = cv2.bilateralFilter(gray,30,40,40)
#gray = cv2.GaussianBlur(gray,(1,1), 0)
gray =cv2.fastNlMeansDenoising(gray ,None, 4, 7, 21)

image = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
            cv2.THRESH_BINARY,11,2)
k = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 1))

blur = cv2.medianBlur(image,3)
erode = cv2.erode(blur, k)
dilat = cv2.dilate(erode,k)
cv2.imshow("gray", dilat)

#cv2.imshow("dilation", img_dilation)
#thresh = cv2.Canny(thresh, 70, 200)

#crop_img = gray[215:215+315, 783:783+684]
#cv2.imshow("cropped", crop_img)

#resize = imutils.resize(blur, width = 460)
#cv2.imshow("resize", resize)

text = pytesseract.image_to_string(dilat, lang='ara')
print(text)
with open(r"c:\ahmed\file.txt", "w", encoding="utf-8") as myfile:
    myfile.write(text)
cv2.waitKey(0)

结果: 在此输入图片描述 这是一个样例图片,无法使用阈值化或Canny算法处理。

为什么要使用Canny算法?如果您需要填充形状,为什么还要检测边缘呢? - Cris Luengo
@CrisLuengo,您能否在那个示例图像上发布一个带有建议解决方案的答案? - chris burgees
@CrisLuengo 如果我使用阈值处理,轮廓将会消失.. 请测试一下 :) - chris burgees
@CrisLuengo 我添加了最后一个样本图像,使用阈值处理和Canny算子都无法处理。 - chris burgees
1个回答

2
在这种情况下,由于文本是黑色的,最好是找到所有的黑色像素。
使用NumPy实现这一点的一种非常简单的方法如下:
import matplotlib.pyplot as pp
import numpy as np

image = pp.imread(r'/home/cris/tmp/Zuv3p.jpg')
bin = np.all(image<100, axis=2)

这个操作是找到所有三个通道值均低于100的像素。我随意选择了100作为阈值,可能有更好的选择方式。 :)
注:
1- 当使用彩色输入时,将其转换为灰度图像通常不是一个好主意,这会丢失很多信息。有时适用,但在这种情况下最好不要这样做。
2- 边缘检测确实很好,但通常是错误的方法。当需要查找边缘时,请使用边缘检测。如果不仅想要边缘,请使用其他方法。
编辑:如果出现np.all无法识别数据类型的情况(对我来说没有问题),您应该能够将其输入转换为正确的类型。
bin = np.all(np.array(image<100, dtype=np.bool), axis=2)

或者可能是这样。
bin = np.all(np.array(image<100, dtype=np.uint8), axis=2)

是的,但是还有一个上面的绿色文本也需要通过OCR捕获...您能编写完整的管道吗? - chris burgees
诀窍在于独立阈值化每个通道。每个通道可以看作是灰度图像。然后将阈值结果组合起来。这就是我在这里所做的:每个通道都使用“<100”进行阈值处理,然后使用逻辑AND(这就是“np.all”所做的)组合通道。 - Cris Luengo
@chrisburgees:找到一个阈值并不容易,特别是如果你需要它在许多不同的光照条件下工作。对此我没有好的建议,抱歉。模糊度不会影响您选择的阈值,但会影响OCR的质量。您应该尽量避免这种情况。您还应该尽量避免反射。您可以检测到那些过度曝光的像素。希望如果成像条件不好,您可以拒绝图像。 - Cris Luengo
你能修复np.all的语法吗?我想imshow它。 - chris burgees
@chrisburgees:编辑了答案,并提供了我最好的猜测来修复您的错误。我没有遇到这个错误,因此无法测试解决方案。按照编写的代码对我有效。 - Cris Luengo
显示剩余7条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接