改进图片以检测区域内的字符

Improve a picture to detect the characters within an area

我的目标是检测这类图像上的字符。

我需要改进图像以便 Tesseract 能够更好地识别,可能需要执行以下步骤:

这是我得到的输出图像,它不适合 OCR:

OCR 问题:

欢迎提出任何其他提高识别度的建议

我认为移除颜色比裁剪更好。

可以用opencv来完成见:

这是一种继续进行的方法...

转换为 HSV,然后从每个角开始,向图片的中间前进,寻找离每个角最近的像素,该像素有点饱和,并且色调与您周围的蓝色矩形相匹配。这将为您提供标记为红色的 4 点:

现在使用透视变换将每个点移动到角落,使图像呈直线。我使用了 ImageMagick,但您应该能够看到我将坐标 (210,51) 处的左上角红点转换为 (0,0) 处新图像的左上角。同样,位于 (1754,19) 的右上角红点会移动到 (2064,0)。终端中的 ImageMagick 命令是:

convert wordsearch.jpg \
  -distort perspective '210,51,0,0 1754,19,2064,0 238,1137,0,1161 1776,1107,2064,1161' result.jpg

结果是:

下一个问题是光线不均匀 - 即左下角比图像的其余部分暗。为了抵消这一点,我克隆了图像并对其进行模糊处理以去除高频(只是一个盒子模糊,或者盒子平均就可以)所以它现在代表缓慢变化的照明。然后我从中减去图像,这样我就有效地去除了背景变化,只留下高频的东西——比如你的字母。然后我将结果归一化,使白人变白,黑人变黑,阈值为 50%。

convert result.jpg -colorspace gray \( +clone -blur 50x50 \) \
   -compose difference -composite  -negate -normalize -threshold 50% final.jpg

如果您知道字体和字母,或者如果您不知道,则结果应该适合模板匹配。

以下是我识别字符的步骤:

(1) detect the blue in hsv space, approx the inner blur contour and sort the corner points:
(2) find persprctive transform matrix and do perspective transform
(3) threshold it (and find characters)
(4) use `mnist` algorithms to recognize the chars

step (1) find the corners of the blur rect

Choosing the correct upper and lower HSV boundaries for color detection with`cv::inRange` (OpenCV)

step (2) crop

step (3) threshold (and find the chars)

step (4) on working...

这里有一个稍微不同的方法,使用 pyvips

如果图像只是旋转(即很少或没有透视),您可以使用 FFT 来找到旋转的角度。漂亮、规则的字符网格将在变换上产生一组清晰的线条。它应该非常坚固。这是对整个图像进行 FFT,但如果您想要更快的速度,可以先将其缩小一点。

import sys
import pyvips

image = pyvips.Image.new_from_file(sys.argv[1])

# to monochrome, take the fft, wrap the origin to the centre, get magnitude
fft = image.colourspace('b-w').fwfft().wrap().abs()

制作:

要找到直线的角度,从极坐标转为直角坐标并寻找水平线:

def to_rectangular(image):
    xy = pyvips.Image.xyz(image.width, image.height)
    xy *= [1, 360.0 / image.height]
    index = xy.rect()
    scale = min(image.width, image.height) / float(image.width)
    index *= scale / 2.0
    index += [image.width / 2.0, image.height / 2.0]
    return image.mapim(index)

# sum of columns, sum of rows
cols, rows = to_rectangular(fft).project()

制作:

投影为:

然后就是找峰旋转:

# blur the rows projection a bit, then get the maxpos
v, x, y = rows.gaussblur(10).maxpos()

# and turn to an angle in degrees we should counter-rotate by
angle = 270 - 360 * y / rows.height

image = image.rotate(angle)

为了裁剪,我再次进行水平和垂直投影,然后搜索 B > G 的峰。

cols, rows = image.project() 

h = (cols[2] - cols[1]) > 10000
v = (rows[2] - rows[1]) > 10000

# search in from the edges for the first non-zero value
cols, rows = h.profile()
left = rows.avg()

cols, rows = h.fliphor().profile()
right = h.width - rows.avg()
width = right - left

cols, rows = v.profile()
top = cols.avg()

cols, rows = v.flipver().profile()
bottom = v.height - cols.avg()
height = bottom - top

# move the crop in by a margin
margin = 10
left += margin
top += margin
width -= 2 * margin
height -= 2 * margin

# and crop!
image = image.crop(left, top, width, height)

制作:

最后去除背景,用大半径模糊并减去:

image = image.colourspace('b-w').gaussblur(70) - image

制作: