python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python OpenCV文档图像自动矫正

Python利用OpenCV实现文档图像自动矫正的方法

作者:Westward-sun.

在日常生活中,用手机拍摄的文档照片往往因为拍摄角度而产生透视畸变,原本方正的纸张变成了不规则的四边形,导致文字歪斜,影响阅读和OCR识别,本文将基于你提供的完整Python代码,深入解析利用OpenCV实现自动文档矫正的每一步,需要的朋友可以参考下

1. 引言

在日常生活中,用手机拍摄的文档照片往往因为拍摄角度而产生透视畸变——原本方正的纸张变成了不规则的四边形,导致文字歪斜,影响阅读和OCR识别。透视变换技术可以将图像中任意四边形区域“拉正”为矩形,完美解决这一问题。本文将基于你提供的完整Python代码,深入解析利用OpenCV实现自动文档矫正的每一步,从图像预处理、轮廓检测到透视变换,并详细讲解核心函数的原理与参数含义。

2. 透视变换核心原理

透视变换是一种将图像从一个平面投影到另一个平面的几何变换。它用一个 3×3 的单应性矩阵 描述,需要至少4对对应点才能求解。在文档矫正场景中,这4对点就是原始图像中文档的四个顶点和矫正后矩形的四个顶点。OpenCV提供了两个核心函数:

3. 环境准备

4. 代码逐段详解

4.1 导入库

import numpy as np
import cv2

4.2 辅助函数

4.2.1 图像显示函数cv_show

def cv_show(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

4.2.2 图像等比例缩放函数resize

def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
    dim = None
    (h, w) = image.shape[:2]
    if width is None and height is None:
        return image
    if width is None:
        r = height / float(h)
        dim = (int(w * r), height)
    else:
        r = width / float(w)
        dim = (width, int(h * r))
    resized = cv2.resize(image, dim, interpolation=inter)
    return resized

4.2.3 顶点排序函数order_points

def order_points(pts):
    # 一共4个坐标点
    rect = np.zeros(shape=(4, 2), dtype="float32")  # 用来存储排序之后的坐标位置
    # 按顺序找到对应坐标0123分别是 左上,右上,右下,左下
    s = pts.sum(axis=1)  # 对pts矩阵的每一行进行求和操作。(x+y)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]
    diff = np.diff(pts, axis=1)  # 对pts矩阵的每一行进行求差操作。(y-x)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    return rect

4.2.4 透视变换核心函数four_point_transform

def four_point_transform(image, pts):
    # 获取输入坐标点
    rect = order_points(pts)
    (tl, tr, br, bl) = rect
    # 计算输入的w和h值
    widthA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
    widthB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
    maxWidth = max(int(widthA), int(widthB))
    heightA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
    heightB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
    maxHeight = max(int(heightA), int(heightB))
    # 变换后对应坐标位置
    dst = np.array([[0, 0], [maxWidth - 1, 0],
                            [maxWidth - 1, maxHeight - 1], [0, maxHeight - 1]], dtype="float32")
    # 获取透视变换矩阵
    M = cv2.getPerspectiveTransform(rect, dst)
    # 执行透视变换
    warped = cv2.warpPerspective(image, M, dsize=(maxWidth, maxHeight))
    # 返回变换后结果
    return warped

步骤解析:

4.3 主程序流程

4.3.1 读取图像并显示原图

image = cv2.imread('fapiao.jpg')
cv_show('image', image)

4.3.2 缩放图像以加快处理

ratio = image.shape[0] / 500.0  # 计算缩小比率
orig = image.copy()
image = resize(orig, height=500)
cv_show('1', image)

结果展示:

4.3.3 轮廓检测

print("STEP 1: 轮廓检测")
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  # 读取灰度图

edged = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]  # 自动寻找阈值二值化
cnts = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)[-2]
image_contours = cv2.drawContours(image.copy(), cnts, -1, color=(0, 0, 255), thickness=1)
cv_show('image_contours', image_contours)

结果展示:

4.3.4 获取最大轮廓并近似为四边形

print("STEP 2: 获取最大轮廓")
screenCnt = sorted(cnts, key=cv2.contourArea, reverse=True)[0]  # 获取面积最大的轮廓
print(screenCnt.shape)
peri = cv2.arcLength(screenCnt, closed=True)  # 计算轮廓周长
screenCnt = cv2.approxPolyDP(screenCnt, 0.05 * peri, closed=True)  # 轮廓近似
print(screenCnt.shape)
image_contour = cv2.drawContours(image.copy(), [screenCnt], -1, (0, 255, 0), thickness=2)

cv2.imshow("image_contour", image_contour)
cv2.waitKey(0)

结果展示:

4.3.5 透视变换

###############
# 透视变换
warped = four_point_transform(orig, screenCnt.reshape(4, 2) * ratio)
cv2.imwrite('invoice_new.jpg', warped)
cv2.namedWindow('xx', cv2.WINDOW_NORMAL)
cv2.imshow("xx", warped)
cv2.waitKey(0)

运行结果展示:

5. 运行结果

输入图像 fapiao.jpg 是一张倾斜拍摄的发票,程序将依次显示:

矫正后的图像将呈现标准的矩形,文字方向变正,极大方便后续OCR识别。

6. 总结与注意事项

6.1 总结

本文通过一个完整的OpenCV案例,详细讲解了如何利用透视变换自动矫正倾斜的文档图像。核心步骤包括:

代码结构清晰,函数封装良好,便于复用和扩展。

6.2 注意事项

通过理解和掌握这段代码,你可以轻松将其应用到车牌矫正、名片扫描、增强现实等更多场景中。如果在实践中遇到问题,欢迎留言交流!

以上就是Python利用OpenCV实现文档图像自动矫正的方法的详细内容,更多关于Python OpenCV文档图像自动矫正的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文