如何去除重叠轮廓并将每个字符分离为单独的轮廓以进行字符提取?
How to remove overlapping contours and separate each character as an individual contour for character extraction?
我正在尝试使用 opencv
中的 MSER
从 Python 中的图像中提取字符。到目前为止,这是我的代码:
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组合成一个轮廓。我该如何预防?
这里没有使用 MSER
,而是使用阈值 + 轮廓过滤的简单方法。我们首先去除边界,然后去除 Otsu 的阈值以获得二值图像。这个想法是每个字母都应该是一个单独的轮廓。我们找到轮廓并绘制每个矩形。
删除边框->
二值图像->
结果
注意:在某些情况下,字母是连在一起的,所以要去除合并的字符,我们可以先使用imutils.resize()
放大图像,然后执行erosion or morphological opening 来分隔每个字符。但是,我无法获得很好的结果,因为即使使用最小尺寸的内核,文本也会消失。
代码
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()
我正在尝试使用 opencv
中的 MSER
从 Python 中的图像中提取字符。到目前为止,这是我的代码:
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组合成一个轮廓。我该如何预防?
这里没有使用 MSER
,而是使用阈值 + 轮廓过滤的简单方法。我们首先去除边界,然后去除 Otsu 的阈值以获得二值图像。这个想法是每个字母都应该是一个单独的轮廓。我们找到轮廓并绘制每个矩形。
删除边框->
二值图像->
结果
注意:在某些情况下,字母是连在一起的,所以要去除合并的字符,我们可以先使用imutils.resize()
放大图像,然后执行erosion or morphological opening 来分隔每个字符。但是,我无法获得很好的结果,因为即使使用最小尺寸的内核,文本也会消失。
代码
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()