【问题标题】:How to transcript text from image in the highlighted areas?如何从突出显示区域的图像中转录文本?
【发布时间】:2021-05-26 18:18:14
【问题描述】:

如何使用 Python 中的 Tesseract 转录下图中突出显示区域的文本?

【问题讨论】:

  • 为什么不在高光处裁剪图像?
  • 问题应该是如何从图像中裁剪这些区域。但这可以通过多种方式完成,您需要针对特定​​的用例。例如,除此之外的图像是什么样的?
  • 或者你最初是如何选择这些词的?为什么不选择其他词?
  • 这只是一个例子。以防万一,所有图像都相似并且具有相同的突出显示区域。我只想知道,如何从这些区域转录文本?
  • 你的意思是像pytesseract.image_to_string(image[100:350, 50: 100])这样的东西吗?

标签: python opencv tesseract python-tesseract


【解决方案1】:

假设您对突出显示的区域有不同的颜色,而其余图像中不存在这种颜色 - 就像示例中突出显示的突出红色一样 - 您可以使用 HSV color space 合并 cv2.inRange 来使用颜色阈值.

因此,您需要为色调、饱和度和值设置适当的下限和上限。在给定的示例中,我们正在检测红色。所以,一般来说,我们需要两组限制,因为红色处于色调圆柱体的 0°/180°“转向”处。为了克服这一点,并且只使用一组限制,我们将获得的色调通道移动 90°,并取模 180°。此外,我们有高饱和度和相当明亮的红色,所以我们可能会看到饱和度水平高于 80%,价值水平高于 50%。我们得到这样一个面具:

最后要做的是从生成的掩码中获取轮廓,获取相应的边界矩形,然后在内容上运行pytesseract(灰度化,使用Otsu 进行阈值化以获得更好的OCR 性能)。我的建议是在这里也使用-psm 6 选项。

这是包含结果的完整代码:

import cv2
import numpy as np
import pytesseract

# Read image
img = cv2.imread('E5PY2.jpg')

# Convert to HSV color space, and split channels
h, s, v = cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV))

# Shift hue channel to detect red area using only one range
h_2 = ((h.astype(int) + 90) % 180).astype(h.dtype)

# Mask highlighted boxes using color thresholding
lower = np.array([ 70, int(0.80 * 255), int(0.50 * 255)])
upper = np.array([110, int(1.00 * 255), int(1.00 * 255)])
highlighted = cv2.inRange(cv2.merge([h_2, s, v]), lower, upper)

# Find contours w.r.t. the OpenCV version; retrieve bounding rectangles
cnts = cv2.findContours(highlighted, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
rects = [cv2.boundingRect(cnt) for cnt in cnts]

# Iterate bounding boxes, and OCR
for x, y, w, h in rects:

    # Grayscale, and threshold using Otsu
    work = cv2.cvtColor(img[y:y+h, x:x+w], cv2.COLOR_BGR2GRAY)
    work = cv2.threshold(work, 0, 255, cv2.THRESH_OTSU)[1]

    # Pytesseract with -psm 6
    text = pytesseract.image_to_string(work, config='--psm 6')\
        .replace('\n', '').replace('\f', '')
    print('X: {}, Y: {}, Text: {}'.format(x, y, text))
    # X: 468, Y: 1574, Text: START MEDITATING
    # X: 332, Y: 1230, Text: Well done. By signing up, you’ve taken your first
    # X: 358, Y: 182, Text: Welcome

警告:我使用来自 Mannheim University Library 的特殊版本的 Tesseract。

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.19041-SP0
Python:        3.9.1
PyCharm:       2021.1.1
NumPy:         1.20.3
OpenCV:        4.5.2
pytesseract:   5.0.0-alpha.20201127
----------------------------------------

【讨论】:

  • 谢谢,但我没有高亮区域,只有边框
  • 我知道。建议的方法找到这些边界,并获得其中的区域以在那里进行 OCR。我不得不问:您是否阅读并理解了提供的代码?如果结果(最后三行,cmets)不是您所期望的,那么您应该在问题中明确说明您的实际目标是什么。
  • 嗨。您能否提供有关此代码的更多信息------------------h_2 = ((h.astype(int) + 90) % 180).astype(h.dtype ) ------------------------work = cv2.cvtColor(img[y:y+h, x:x+w], cv2.COLOR_BGR2GRAY) work = cv2.threshold(work, 0, 255, cv2.THRESH_OTSU)[1]
  • @Oleg 1) 请查看有关 HSV 颜色空间的链接 Wikipedia 文章。在 0° 到 20° 以及 340° 到 360° 的色调值处可以找到红色。因此,您需要两组边界来检测红色,因此需要两个 cv2.inRange 调用。为了简化这一点,我将所有色调值移动了 90°,这样就可以在 70° 到 110° 之间找到红色。 2)这是切片(裁剪为 ROI),以及颜色转换为灰度,这是以下阈值处理所必需的。 3) 这是使用Otsu's method 的阈值。
【解决方案2】:

从上到下。这些框大约位于(x1y1x2y2

  • 0.2564, 0.1070, 0.6293, 0.166
  • 0.2377, 0.6826, 0.7645, 0.703
  • 0.331, 0.88, 0.6713, 0.913

相对于宽度和高度。完整的代码就像

import cv2
import pytesseract

image = cv2.imread('E5PY2.jpg')
coords = [[0.2564, 0.1070, 0.6293, 0.166],
          [0.2377, 0.6826, 0.7645, 0.703],
          [0.331, 0.88, 0.6713, 0.913]]
h, w, c = image.shape
for idx, (x1, y1, x2, y2) in enumerate(coords):
    x1 = int(x1 * w)
    x2 = int(x2 * w)
    y1 = int(y1 * h)
    y2 = int(y2 * h)
    print(pytesseract.image_to_string(image[y1:y2, x1:x2]))

【讨论】:

  • 谢谢,但是你是怎么找到坐标的?
猜你喜欢
  • 2013-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-13
  • 2019-05-26
  • 2013-05-25
  • 1970-01-01
相关资源
最近更新 更多