【问题标题】:How to extract only characters from image?如何从图像中只提取字符?
【发布时间】:2018-11-08 02:15:45
【问题描述】:

我有这种类型的图像,我只想从中提取字符。

二值化后,我得到这张图片

img = cv2.imread('the_image.jpg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 11, 9)

然后在这张图片上找到轮廓。

(im2, cnts, _) = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
for contour in cnts[:2000]:
    x, y, w, h = cv2.boundingRect(contour)
    aspect_ratio = h/w
    area = cv2.contourArea(contour)
    cv2.drawContours(img, [contour], -1, (0, 255, 0), 2) 

我来了

我需要一种方法来过滤轮廓,以便它只选择字符。所以我可以找到边界框并提取 roi。

我可以找到轮廓并根据区域的大小对其进行过滤,但是源图像的分辨率并不一致。这些图像是从移动相机拍摄的。

盒子的边界也是断开的。我无法准确地检测到这些框。

编辑:

如果我取消选择纵横比小于 0.4 的框。然后它在某种程度上起作用。但我不知道它是否适用于不同分辨率的图像。

for contour in cnts[:2000]:
    x, y, w, h = cv2.boundingRect(contour)
    aspect_ratio = h/w
    area = cv2.contourArea(contour)

    if aspect_ratio < 0.4:
        continue
    print(aspect_ratio)
    cv2.drawContours(img, [contour], -1, (0, 255, 0), 2)

【问题讨论】:

  • 我对此进行了研究。但是因为它们可以用英语解释。就像,找到轮廓,扩大直线以关闭它们。这就是为什么,我没有包含任何代码。此外,代码将毫无意义。因为它不起作用。
  • 原图不是这样的。我使用adaptiveThreshold 将其从rgb 转换为二进制。我还尝试了关闭/打开操作来尝试关闭那些断开的线路。我需要一种方法来解决这个问题。
  • 所有这些都是对您的问题有用的信息,否则您可能会发现人们只是建议您尝试这些方法。您需要展示您尝试过的内容以及失败的地方,这样您可以获得更好的答案
  • 我有两个可能的建议。一种是使用线检测器(如 Hough)来检测边界框并将它们分成更小的图像。您也可以尝试在查找轮廓中使用cv2.CV_RETR_EXTERNAL 来删除外部的轮廓,但是您会得到一个围绕整个图像的轮廓......并且一些数字会触及框(或者至少看起来像它)并且可能不行。您可以尝试使用cv2.CV_RETR_TREE 并降低一些层次结构,直到您只得到数字
  • 没有一个数字与盒子相连,因此将数字提取为 blob 然后对其进行分类应该非常简单。一般来说,您可能会使用一种通过某些特征的存在来识别字符的方法,这样您就不必依赖分隔字符。但是对于这个问题的任何解决方案对于 StackOverflow 来说都太过分了。你应该做一些自己的研究,阅读论文并对手写 OCR 有所了解

标签: python opencv image-processing computer-vision mnist


【解决方案1】:

没那么难……

import cv2

img = cv2.imread('img.jpg')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imshow('gray', gray)

ret, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)
cv2.imshow('thresh', thresh)

im2, ctrs, hier = cv2.findContours(thresh.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
sorted_ctrs = sorted(ctrs, key=lambda ctr: cv2.boundingRect(ctr)[0])

for i, ctr in enumerate(sorted_ctrs):
    x, y, w, h = cv2.boundingRect(ctr)

    roi = img[y:y + h, x:x + w]

    area = w*h

    if 250 < area < 900:
        rect = cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
        cv2.imshow('rect', rect)

cv2.waitKey(0)

结果

您可以根据需要调整代码(这里可以使用原始图像保存 ROI;为了最终进行 OCR 识别,您必须以二进制格式保存它们 - 有比按区域排序更好的方法)

来源:Extract ROI from image with Python and OpenCV 和我的一些知识。

开个玩笑,看看我的问题/答案。

【讨论】:

    猜你喜欢
    • 2012-09-14
    • 2016-07-21
    • 1970-01-01
    • 1970-01-01
    • 2019-04-21
    • 1970-01-01
    • 2021-01-01
    • 2013-02-03
    相关资源
    最近更新 更多