Python cv2/pytesseract数字识别的局部对比度增强
我想使用pytesseract从图像中读取数字。图片如下所示:Python cv2/pytesseract数字识别的局部对比度增强,python,opencv,ocr,cv2,python-tesseract,Python,Opencv,Ocr,Cv2,Python Tesseract,我想使用pytesseract从图像中读取数字。图片如下所示: # Set kernel (structuring element) size: kernelSize = 3 # Set operation iterations: opIterations = 3 # Get the structuring element: maxKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernelSize, kernelSize)) # P
# Set kernel (structuring element) size:
kernelSize = 3
# Set operation iterations:
opIterations = 3
# Get the structuring element:
maxKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernelSize, kernelSize))
# Perform closing:
closingImage = cv2.morphologyEx(filteredImage, cv2.MORPH_CLOSE, maxKernel, None, None, opIterations, cv2.BORDER_REFLECT101)
# Invert image to obtain black numbers on white background:
closingImage = 255 - closingImage
数字是虚线的,为了能够使用PyteSeract,我需要白色背景上的黑色连接数字。为此,我考虑使用腐蚀和扩展作为预处理技术。正如您所看到的,这些图像是相似的,但在某些方面有很大的不同。例如,第一幅图像中的点比背景暗,而第二幅图像中的点更白。这意味着,在第一幅图像中,我可以使用腐蚀获得黑色连接线,在第二幅图像中,我可以使用放大获得白色连接线,然后反转颜色。这将导致以下结果:
使用适当的阈值,第一个图像可以很容易地用pytesseract读取。不管是谁,第二张图片更狡猾。问题是,例如,“4”的部分比三个周围的背景暗。因此,一个简单的阈值是行不通的。我需要像局部阈值或局部对比度增强这样的东西。这里有人有主意吗
编辑:
OTSU、平均阈值和高斯阈值导致以下结果:
您的图像分辨率很低,但您可以尝试一种称为增益分割的方法。其思想是,您尝试构建一个背景模型,然后根据该模型对每个输入像素进行加权。在图像的大部分时间内,输出增益应相对恒定 执行增益分割后,您可以尝试通过应用区域过滤器和形态学来改善图像。我只试过你的第一张照片,因为它是“最差的” 以下是获得增益分割图像的步骤:
close
操作,使用一个大的结构元素(我使用的是一个大小为15
的矩形内核)
255
,执行增益调整。将此值与每个输入图像像素加权threshold
这个图像可以得到字符的二进制掩码阈值
通过大津,但添加一点偏差import numpy as np
import cv2
# image path
path = "C:/opencvImages/"
fileName = "iA904.png"
# Reading an image in default mode:
inputImage = cv2.imread(path+fileName)
# 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)
# Perform gain division
gainDivision = np.where(localMax == 0, 0, (inputImage/localMax))
# Clip the values to [0,255]
gainDivision = np.clip((255 * gainDivision), 0, 255)
# Convert the mat type from float to uint8:
gainDivision = gainDivision.astype("uint8")
# Convert RGB to grayscale:
grayscaleImage = cv2.cvtColor(gainDivision, cv2.COLOR_BGR2GRAY)
这就是增益分割带给您的:
请注意,照明更加平衡。现在,让我们应用一点对比度增强:
# Contrast Enhancement:
grayscaleImage = np.uint8(cv2.normalize(grayscaleImage, grayscaleImage, 0, 255, cv2.NORM_MINMAX))
这样,前景和背景之间的对比度会增加一点:
现在,让我们尝试对该图像设置阈值,以获得一个漂亮的二进制掩码。正如我所建议的,尝试Otsu的阈值化,但在结果上增加(或减少)一点偏差。如前所述,此步骤取决于输入的质量:
# Threshold via Otsu + bias adjustment:
threshValue, binaryImage = cv2.threshold(grayscaleImage, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)
threshValue = 0.9 * threshValue
_, binaryImage = cv2.threshold(grayscaleImage, threshValue, 255, cv2.THRESH_BINARY)
您将得到以下二进制掩码:
将其倒置,过滤掉小斑点。我将区域设置为10
像素的阈值:
# Invert image:
binaryImage = 255 - binaryImage
# Perform an area filter on the binary blobs:
componentsNumber, labeledImage, componentStats, componentCentroids = \
cv2.connectedComponentsWithStats(binaryImage, connectivity=4)
# Set the minimum pixels for the area filter:
minArea = 10
# Get the indices/labels of the remaining components based on the area stat
# (skip the background component at index 0)
remainingComponentLabels = [i for i in range(1, componentsNumber) if componentStats[i][4] >= minArea]
# Filter the labeled pixels based on the remaining labels,
# assign pixel intensity to 255 (uint8) for the remaining pixels
filteredImage = np.where(np.isin(labeledImage, remainingComponentLabels) == True, 255, 0).astype("uint8")
这是最后一个二进制掩码:
如果您计划将此图像发送到OCR
,可能需要先应用一些形态学。也许是一个
结束
来尝试连接组成字符的点。另外,一定要训练你的OCR
分类器,使其字体接近你实际想要识别的字体。这是尺寸3
矩形
关闭
操作后的(反转)遮罩,使用3
迭代:
编辑:
要获取最后一幅图像,请按如下方式处理过滤后的输出:
# Set kernel (structuring element) size:
kernelSize = 3
# Set operation iterations:
opIterations = 3
# Get the structuring element:
maxKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (kernelSize, kernelSize))
# Perform closing:
closingImage = cv2.morphologyEx(filteredImage, cv2.MORPH_CLOSE, maxKernel, None, None, opIterations, cv2.BORDER_REFLECT101)
# Invert image to obtain black numbers on white background:
closingImage = 255 - closingImage
你试过大津阈值了吗?谢谢你的主意,我刚刚试过,但似乎不起作用。我也试过高斯阈值和平均阈值,但它们并没有达到预期的效果!非常感谢,我一定会尝试你建议的所有东西:)@spadel很高兴我能帮忙,我的朋友!不知何故,我无法再现最后一步(关闭操作)。我尝试了以下方法:
kernel=cv2.getStructuringElement(cv2.MORPH\u RECT,(3,3))closing=cv2.morphologyEx(filteredImage,cv2.MORPH\u CLOSE,kernel)
,但没有效果。我试着对过滤后的二值图像及其逆图像进行应用。@spadel检查我的编辑,我添加了代码以获得最后一幅图像。