首页 > 解决方案 > 在python中应用轮廓后如何从图像中提取文本?

问题描述

所以我在一个大图像上应用了轮廓,并达到了图像的以下裁剪部分:

在此处输入图像描述

在此处输入图像描述

但是现在在不使用任何机器学习模型的情况下,我如何真正将图像转换为文本变量?我开始了解模板匹配,但我不明白如何从这里开始。我确实将字母和数字的图像(根据它们的图像值命名)存储在一个目录中,但是我如何匹配它们中的每一个并将文本作为字符串获取?我不想使用任何 ML 模型或库,如 pyTesseract。

我将不胜感激任何帮助。

编辑:

我尝试过的模板匹配代码。

def templateMatch(image):
    path = "location"

    for image_path in os.listdir(path + "/characters-images"):
        template = cv2.imread(os.path.join(path, "characters-images", image_path))
        template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)

        template = template.astype(np.uint8)
        image = image.astype(np.uint8)

        res = cv2.matchTemplate(template, image, cv2.TM_SQDIFF_NORMED)
        mn, _, mnLoc, _ = cv2.minMaxLoc(res)

        if res is not None:
            return image_path.replace(".bmp", "")


def match(image):
    plate = ""
    # mask = np.zeros(image.shape, dtype=np.uint8)
    # print(image.shape)
    image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    # print(image.shape)
    # print(image)
    thresh = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

    cnts = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    cnts = cnts[0] if len(cnts) == 2 else cnts[1]
    (cnts, _) = contours.sort_contours(cnts, method="left-to-right")

    for con in cnts:
        area = cv2.contourArea(con)

        if 800 > area > 200:
            x, y, w, h = cv2.boundingRect(con)
            # cv2.drawContours(mask, [c], 1, (255, 0, 0), 2)
            temp = thresh[y:y+h, x:x+w]

            character = templateMatching(temp)

            if character is not None:
                plate += character

    return plate

标签: pythonimageopencvimage-processingcomputer-vision

解决方案


我如何实际将图像获取到文本变量?我开始了解模板匹配,但我不明白如何从这里开始。

模板匹配用于在给定模板的图像中定位对象,而不是从图像中提取文本。将模板与图像中对象的位置匹配将无助于将文本作为字符串获取。有关如何应用动态比例变体模板匹配的示例,请看一下如何隔离轮廓内的所有内容,对其进行缩放,并测试与图像的相似性?Python OpenCV 线检测来检测图像中的 X 符号。我不明白为什么不想使用 OCR 库。如果您想从图像中提取文本作为字符串变量,您应该使用某种类型的深度/机器学习。PyTesseract 可能是最简单的。这是使用 PyTesseract 的解决方案


这个想法是使用 Otsu 的阈值获得二值图像,然后执行轮廓区域和纵横比过滤以提取字母/数字 ROI。从这里我们使用 Numpy 切片将每个 ROI 裁剪到空白蒙版上,然后使用 Pytesseract 应用 OCR。这是每个步骤的可视化:

二进制图像

检测到的 ROI 以绿色突出显示

空白掩码上的隔离 ROI 已准备好进行 OCR

我们使用--psm 6配置选项告诉 Pytesseract 假设一个统一的文本块。在此处查看更多配置选项。来自 Pytesseract 的结果:

XS NB 23

代码

import cv2
import numpy as np
import pytesseract

pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"

# Load image, create mask, grayscale, Otsu's threshold
image = cv2.imread('1.png')
mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

# Filter for ROI using contour area and aspect ratio
cnts = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.05 * peri, True)
    x,y,w,h = cv2.boundingRect(approx)
    aspect_ratio = w / float(h)
    if area > 2000 and aspect_ratio > .5:
        mask[y:y+h, x:x+w] = image[y:y+h, x:x+w]

# Perfrom OCR with Pytesseract
data = pytesseract.image_to_string(mask, lang='eng', config='--psm 6')
print(data)

cv2.imshow('thresh', thresh)
cv2.imshow('mask', mask)
cv2.waitKey()

推荐阅读