我真的是opencv的新手,也是python的初学者。
我有这张图片:
我想以某种方式应用适当的阈值以保留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
然后我将其相乘以增加数字和背景之间的对比度:
image = cv2.multiply(image, 1.5)
最后,我执行Binary + Otsu阈值处理:
_,thressed1 = cv2.threshold(image,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
您可以看到最终结果非常好,除了数字'7'引起很大的噪音。
如何改善最终结果?请在可能的情况下提供图片示例结果,不仅仅仅是代码片段就更好理解了。
答案 0 :(得分:3)
您可以尝试对具有不同内核(例如3、51)的灰度(模糊)图像进行中值模糊处理,对模糊结果进行划分并对其进行阈值处理。像这样:
#!/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)
结果:
答案 1 :(得分:1)
要完全删除烦人的图章似乎并不容易。
您可以通过以下方式使背景强度变平
计算低通图像(高斯滤波器,形态学闭合);过滤器的尺寸应比字符的尺寸大一点;
将原始图像除以低通图像。
然后您可以使用Otsu。
如您所见,结果并不完美。
答案 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:
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.