Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python cv2/pytesseract数字识别的局部对比度增强_Python_Opencv_Ocr_Cv2_Python Tesseract - Fatal编程技术网

Python cv2/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

我想使用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))

# 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检查我的编辑,我添加了代码以获得最后一幅图像。