适当的图像阈值处理,以使用opencv

时间:2018-09-22 18:46:58

标签: python opencv image-processing ocr image-thresholding

我真的是opencv的新手,也是python的初学者。

我有这张图片:

original bmp 24bit image

我想以某种方式应用适当的阈值以保留6位数字。

更大的图景是,我打算尝试在每个数字级别(kNearest.findNearest)上使用k最近邻居算法对每个数字分别对图像进行手动OCR

问题是我无法充分清理数字,尤其是带有蓝色水印的'7'数字。

到目前为止,我已经尝试过以下步骤:

我正在从磁盘读取图像

# IMREAD_UNCHANGED is -1
image = cv2.imread(sys.argv[1], cv2.IMREAD_UNCHANGED)

然后,我只保留蓝色通道以消除数字'7'周围的蓝色水印,有效地将其转换为单个通道图像

image = image[:,:,0] 
# openned with -1 which means as is, 
# so the blue channel is the first in BGR

single channel - red only - image

然后我将其相乘以增加数字和背景之间的对比度:

image = cv2.multiply(image, 1.5)

multiplied image to increase contrast

最后,我执行Binary + Otsu阈值处理:

_,thressed1 = cv2.threshold(image,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

binary Oahu thresholded image

您可以看到最终结果非常好,除了数字'7'引起很大的噪音。

如何改善最终结果?请在可能的情况下提供图片示例结果,不仅仅仅是代码片段就更好理解了。

4 个答案:

答案 0 :(得分:3)

您可以尝试对具有不同内核(例如3、51)的灰度(模糊)图像进行中值模糊处理,对模糊结果进行划分并对其进行阈值处理。像这样:

enter image description here


#!/usr/bin/python3
# 2018/09/23 17:29 (CST) 
# (中秋节快乐)
# (Happy Mid-Autumn Festival)

import cv2 
import numpy as np 

fname = "color.png"
bgray = cv2.imread(fname)[...,0]

blured1 = cv2.medianBlur(bgray,3)
blured2 = cv2.medianBlur(bgray,51)
divided = np.ma.divide(blured1, blured2).data
normed = np.uint8(255*divided/divided.max())
th, threshed = cv2.threshold(normed, 100, 255, cv2.THRESH_OTSU)

dst = np.vstack((bgray, blured1, blured2, normed, threshed)) 
cv2.imwrite("dst.png", dst)

结果:

enter image description here

答案 1 :(得分:1)

要完全删除烦人的图章似乎并不容易。

您可以通过以下方式使背景强度变平

  • 计算低通图像(高斯滤波器,形态学闭合);过滤器的尺寸应比字符的尺寸大一点;

  • 将原始图像除以低通图像。

然后您可以使用Otsu。

enter image description here

如您所见,结果并不完美。

答案 2 :(得分:0)

为什么不仅仅将图像中的值保持在某个阈值之上?

赞:

import cv2
import numpy as np

img = cv2.imread("./a.png")[:,:,0]  # the last readable image

new_img = []
for line in img:
    new_img.append(np.array(list(map(lambda x: 0 if x < 100 else 255, line))))

new_img = np.array(list(map(lambda x: np.array(x), new_img)))

cv2.imwrite("./b.png", new_img) 

看起来很棒:

您可能甚至可以更进一步地使用阈值并获得更好的结果。

答案 3 :(得分:0)

I tried a slightly different approach then Yves on the blue channel:Blue channel

  • Apply median filter (r=2):

Filtered image

  • Use Edge detection (e.g. Sobel operator):

Edges detected

  • Automatic thresholding (Otsu)

Thresholded image

  • Closing of the image

Closed image

This approach seems to make the output a little less noisy. However, one has to address the holes in the numbers. This can be done by detecting black contours which are completely surrounded by white pixels and simply filling them with white.