使用 Python 和 OpenCV 改善图像偏移

Improving image deskew using Python and OpenCV

我生成的用于检测和纠正偏斜的代码给出了不一致的结果。我目前正在开展一个项目,该项目利用图像上的 OCR 文本提取(通过 Python 和 OpenCV),因此如果需要准确的结果,消除倾斜是关键。我的代码使用 cv2.minAreaRect 来检测偏斜。

我使用的图像完全相同(将来也会如此),所以我不确定是什么导致了这些不一致。我在应用我的代码的地方包含了两组前后图像(包括来自 cv2.minAreaRect 的偏斜值),一组显示成功去除偏斜并显示偏斜未被去除(看起来它增加了更多偏斜) .

图像 1 之前 (-87.88721466064453)

Image 1 After (成功去歪斜)

图像 2 之前 (-5.766754150390625)

Image 2 After(去歪斜不成功)

我的代码如下。注意:我处理过的图像比我在这里包含的图像多得多。到目前为止检测到的偏斜一直在 [-10, 0) 或 (-90, -80] 范围内,所以我试图在我的代码中考虑到这一点。

    img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    img_gray = cv2.bitwise_not(img_gray)
    
    thresh = cv2.threshold(img_gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
    coords = np.column_stack(np.where(thresh > 0))
    angle = cv2.minAreaRect(coords)[-1] 
      
    if (angle < 0 and angle >= -10):
        angle = -angle #this was intended to undo skew for values in [-10, 0) by simply rotating using the opposite sign
    else:
        angle = (90 + angle)/2  
     
    (h, w) = img.shape[:2]
    center = (w // 2, h // 2)
    
    M = cv2.getRotationMatrix2D(center, angle, 1.0)
    deskewed = cv2.warpAffine(img, M, (w, h), flags = cv2.INTER_CUBIC, borderMode = cv2.BORDER_REPLICATE)

我浏览了各种帖子和文章以找到合适的解决方案,但没有成功。 This post 对理解偏斜值最有帮助,但即便如此我也无法深入了解。

可以在Python Wand 中找到一个非常好的文本歪斜校正工具,它使用ImageMagick。它基于 Radon 变换。

表格 1:

表格 2:

from wand.image import Image
from wand.display import display


with Image(filename='form1.png') as img:
    img.deskew(0.4*img.quantum_range)
    img.save(filename='form1_deskew.png')
    display(img)

with Image(filename='form2.png') as img:
    img.deskew(0.4*img.quantum_range)
    img.save(filename='form2_deskew.png')
    display(img)

表格 1 校正:

表格 2 校正:

我已经在这里回答了这个问题:

以下是可以帮助您校正图像的一段代码:

import numpy as np
from skimage import io
from skimage.transform import rotate
from skimage.color import rgb2gray
from deskew import determine_skew
from matplotlib import pyplot as plt

def deskew(_img):
    image = io.imread(_img)
    grayscale = rgb2gray(image)
    angle = determine_skew(grayscale)
    rotated = rotate(image, angle, resize=True) * 255
    return rotated.astype(np.uint8)

def display_before_after(_original):
    plt.subplot(1, 2, 1)
    plt.imshow(io.imread(_original))
    plt.subplot(1, 2, 2)
    plt.imshow(deskew(_original))

display_before_after('img_35h.jpg')

之前:

之后:

参考和来源:http://aishelf.org/deskew/