首页 文章

从圆形边框内提取文本

提问于
浏览
2

我正在尝试使用Python和OpenCV开发一个脚本来检测扫描仪器图上的一些突出显示的区域,并使用Tesseract的OCR功能输出文本 . 我的工作流程首先检测感兴趣区域的一般附近,然后应用处理步骤除去文本块(线条,边框,噪声)之外的所有内容 . 然后将处理后的图像输入Tesseract的OCR引擎 .

此工作流程适用于大约一半的图像,但由于文本触摸边框而导致其余部分失败 . 我将在下面展示一些我的意思的例子:

步骤1:使用具有荧光笔颜色范围的InRange创建遮罩,找到感兴趣的区域 .

第2步:轮廓感兴趣的区域,裁剪并保存到文件 .

---参考代码从这里开始---

步骤3:阈值图像并应用Canny边缘检测

步骤4:使用cv2.approxPolyDP对边缘进行轮廓加工并将其过滤为圆形,并查看顶点大于8的边缘 . 第一个或第二个最大轮廓通常对应于内边缘 .

步骤5:使用蒙版和按位操作,轮廓内的所有内容都转移到白色背景图像 . 应用膨胀和腐蚀来使图像去噪并产生最终图像,该图像被馈送到OCR引擎中 .

import cv2
import numpy as np 
import pytesseract 
pytesseract.pytesseract.tesseract_cmd = 'C:/Program Files (x86)/Tesseract-OCR/tesseract'

d_path = "Test images\\"

img_name = "cropped_12.jpg"

img = cv2.imread(d_path + img_name)  # Reads the image

## Resize image before calculating contour 
height, width = img.shape[:2]
img = cv2.resize(img,(2*width,2*height),interpolation = cv2.INTER_CUBIC)  

img_orig = img.copy()           # Makes copy of original image  

img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)    # Convert to grayscale

#  Apply threshold to get binary image and write to file
_, img = cv2.threshold(img,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)


# Edge detection 
edges = cv2.Canny(img,100,200)

# Find contours of mask threshold 
_, contours, hierarchy = cv2.findContours(edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

# Find contours associated w/ polygons with 8 sides or more 
cnt_list = []
area_list = [cv2.contourArea(c) for c in contours]
for j in contours:
    poly_pts = cv2.approxPolyDP(j,0.01*cv2.arcLength(j,True),True)
    area = cv2.contourArea(j)
    if (len(poly_pts) > 8) & (area == max(area_list)):
        cnt_list.append(j)

cv2.drawContours(img_orig, cnt_list, -1, (255,0,0), 2)

# Show contours 
cv2.namedWindow('Show',cv2.WINDOW_NORMAL)
cv2.imshow("Show",img_orig)
cv2.waitKey()
cv2.destroyAllWindows()

# Zero pixels outside circle 
mask = np.zeros(img.shape).astype(img.dtype)
cv2.fillPoly(mask, cnt_list, (255,255,255))
mask_inv = cv2.bitwise_not(mask)

a = cv2.bitwise_and(img,img,mask = mask)
wh_back = np.ones(img.shape).astype(img.dtype)*255
b = cv2.bitwise_and(wh_back,wh_back,mask = mask_inv)

res = cv2.add(a,b)

# Get rid of noise 
kernel = np.ones((2, 2), np.uint8)
res = cv2.dilate(res, kernel, iterations=1)
res = cv2.erode(res, kernel, iterations=1)

# Show final image 
cv2.namedWindow('result',cv2.WINDOW_NORMAL)
cv2.imshow("result",res)
cv2.waitKey()
cv2.destroyAllWindows()

代码工作时,这些是输出的图像:Working

但是,在文本接触圆形边框的情况下,代码假定文本的一部分是较大轮廓的一部分并忽略最后一个字母 . 例如:Not working

是否有任何处理步骤可以帮助我绕过这个问题?或者也许是另一种方法?我已经尝试过使用霍夫圆形变换试图检测边界,但它们非常挑剔并且不能像轮廓一样好用 .

我是OpenCV和Python的新手,所以任何帮助都会受到赞赏 .

2 回答

  • 0

    如果霍夫圆变换不适合你,我认为你最好选择近似边界形状 . 我所知道的最好的方法是:Douglas-Peucker算法,通过减少图片的周长,使你的轮廓变得更简单 .

    您可以从OpenCV检查此参考文件,以查看可以应用于您的边界的后期处理类型 . 他们还提到Douglas-Peucker:OpenCV boarder processing

  • 0

    只是一种预感 . OTSU阈值化后 . 侵蚀和扩张图像 . 这将导致非常薄的关节消失 . 相同的代码如下 .

    kernel = np.ones((5,5),np.uint8)
    th3 = cv2.erode(th3, kernel,iterations=1)
    th3 = cv2.dilate(th3, kernel,iterations=1)
    

    让我知道事情的后续 . 如果这不起作用我还有更多想法 .

相关问题