[英]Opencv, Python - How to remove the gray pixels around the date text
我正在尝试使用 Python/OpenCV 消除日期周围的灰色“噪音”,以帮助OCR
(光学字符识别)识别日期。
原始图像如下所示: https://static.mothership.sg/1/2017/03/10-Feb-MC-1.jpg
我试过的 python 脚本如下所示。 但是,我还有其他类似的图像,其中对比度或照明条件会有所不同。
import cv2
import numpy as np
img = cv2.imread("mc.jpeg")
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
alpha = 3.5
beta = -2
new = alpha * img + beta
new = np.clip(new, 0, 255).astype(np.uint8)
cv2.imwrite("cleaned.png", new)
我还尝试了Thresholding
和/或adaptiveThresholding
阈值,有一段时间,我能够将日期与灰色背景分开。 有时这是非常具有挑战性的。 我想知道是否有一种自动方法来确定阈值?
以下是我希望实现的示例。
Otsu 的二值化会根据图像直方图自动计算阈值。
# Otsu's thresholding after Gaussian filtering
blur = cv2.GaussianBlur(img,(5,5),0)
ret,Otsu = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)
cv2.imwrite("Otsu's_thresholding", Otsu)
看到这个链接
您可以尝试构建背景的 model,然后通过该 model 对每个输入像素进行加权。 output 增益在大部分图像中应该是相对恒定的。 这些是此方法的步骤:
close
操作, structuring element
很大(我使用的是大小为15
的矩形 kernel )255
来执行增益调整。 用每个输入图像像素加权这个值。threshold
这个图像以获得文本的二进制掩码这是代码:
import numpy as np
import cv2
# image path
path = "C:/opencvImages/sheet01.jpg"
# Read an image in default mode:
inputImage = cv2.imread(path)
# Remove small noise via median:
filterSize = 5
imageMedian = cv2.medianBlur(inputImage, filterSize)
# Get local maximum:
kernelSize = 15
maxKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernelSize, kernelSize))
localMax = cv2.morphologyEx(imageMedian, cv2.MORPH_CLOSE, maxKernel, None, None, 1, cv2.BORDER_REFLECT101)
# Adjust image gain:
height, width, depth = localMax.shape
# Create output Mat:
outputImage = np.zeros(shape=[height, width, depth], dtype=np.uint8)
for i in range(0, height):
for j in range(0, width):
# Get current BGR pixels:
v1 = inputImage[i, j]
v2 = localMax[i, j]
# Gain adjust:
tempArray = []
for c in range(0, 3):
currentPixel = v2[c]
if currentPixel != 0:
gain = 255 / v2[c]
gain = v1[c] * gain
else:
gain = 0
# Gain set and clamp:
tempArray.append(np.clip(gain, 0, 255))
# Set pixel vec to out image:
outputImage[i, j] = tempArray
# Convert RGB to grayscale:
grayscaleImage = cv2.cvtColor(outputImage, cv2.COLOR_BGR2GRAY)
# Threshold:
threshValue = 110
_, binaryImage = cv2.threshold(grayscaleImage, threshValue, 255, cv2.THRESH_BINARY)
# Write image:
imageFilename = "C:/opencvImages/binaryMask2.png"
cv2.imwrite(imageFilename, binaryImage)
我得到以下测试完整图像的结果:
和裁剪的文本:
请注意,增益调整操作不是矢量化的。 脚本很慢,主要是因为我从Python
开始并且不知道正确的Numpy
语法来加速这个操作。 我已经使用C++
很长时间了,所以请随时进一步改进代码。
编辑:
请注意,您的结果只能与您输入的质量一样好。 查看您的输入并问自己“对于自动化流程来说,这是一个好的输入吗?” (自动化流程通常不是很智能)。 您发布的第二张图片质量非常低。 不仅模糊,而且分辨率低,并且有压缩伪影。 所有这些因素都会阻碍自动化处理。
话虽如此,您可以在原始文件中包含以下改进:尝试在灰度 output 上normalize
亮度对比度:
grayscaleImage = np.uint8(cv2.normalize(grayscaleImage, grayscaleImage, 0, 255, cv2.NORM_MINMAX))
您的灰度图像来自:
对此:
稍微暗一点,对比度有所改善。 让我们尝试通过Otsu thresholding
自动计算最佳阈值:
threshValue, binaryImage = cv2.threshold(grayscaleImage, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
它为您提供:
但是,如果我们向 Otsu 的阈值添加bias
,我们可以调整结果,如下所示:
threshValue, binaryImage = cv2.threshold(grayscaleImage, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
bias = 0.9
threshValue = bias * threshValue
_, binaryImage = cv2.threshold(grayscaleImage, threshValue, 255, cv2.THRESH_BINARY)
这是使用此方法可以获得的这些图像的最佳质量。 如果您发现这些建议和技巧有用,请至少为我的回答投票。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.