2

我正在尝试使用MSERin实现从 Python 中的图像中提取字符opencv。这是我到目前为止的代码:

import cv2
import numpy as np

# create MSER object
mser = cv2.MSER_create()
# convert image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# detect the regions
regions,_ = mser.detectRegions(gray)
# find convex hulls of the regions
hulls = [cv2.convexHull(p.reshape(-1, 1, 2)) for p in regions]
# initialize threshold area of the contours
ThresholdContourArea = 10000
# initialize empty list for the characters and their locations
char = []
loc =[]
# get the character part of the image and it's location if the area of contour less than threshold
for contour in hulls:
    if cv2.contourArea(contour) > ThresholdContourArea:
        continue
    # get the bounding rectangle around the contour
    bound_rect = cv2.boundingRect(contour)
    loc.append(bound_rect)
    det_char = gray[bound_rect[1]:bound_rect[1]+bound_rect[3],bound_rect[0]:bound_rect[0]+bound_rect[2]]
    char.append(det_char)

但是这种方法为同一个字母提供了多个轮廓,并且在某些地方,多个单词被放入一个轮廓中。这是一个例如:原始图像:

在此处输入图像描述

添加轮廓后:

在此处输入图像描述

这里第一个 T 周围有多个轮廓,两个 rs 组合成一个轮廓。我该如何防止呢?

4

1 回答 1

1

而不是使用MSER,这是一个使用阈值 + 轮廓过滤的简单方法。我们首先去除边界,然后去除 Otsu 的阈值以获得二值图像。这个想法是每个字母应该是一个单独的轮廓。我们找到轮廓并绘制每个矩形。

移除边框->二值图像->结果

注意:在某些情况下,字母是相连的,为了去除合并的字符,我们可以先放大图像,imutils.resize()然后使用腐蚀形态学打开来分离每个字符。但是,我无法获得很好的结果,因为即使使用最小尺寸的内核,文本也会消失。

代码

import cv2
import imutils

# Load image, grayscale, Otsu's threshold
image = cv2.imread('1.png')
image = imutils.resize(image, width=500)

# Remove border
kernel_vertical = cv2.getStructuringElement(cv2.MORPH_RECT, (1,50))
temp1 = 255 - cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernel_vertical)
horizontal_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (50,1))
temp2 = 255 - cv2.morphologyEx(image, cv2.MORPH_CLOSE, horizontal_kernel)
temp3 = cv2.add(temp1, temp2)
result = cv2.add(temp3, image)

# Convert to grayscale and Otsu's threshold
gray = cv2.cvtColor(result, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Find contours and filter using contour area
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    x,y,w,h = cv2.boundingRect(c)
    cv2.rectangle(result, (x, y), (x + w, y + h), (36,255,12), 2)

cv2.imshow('thresh', thresh)
cv2.imshow('result', result)
cv2.waitKey()
于 2019-12-31T03:12:34.297 回答