Bootstrap

如何进行文档类图像的校正?

可以使用OpenCV实现的图像校正算法,包含透视校正和旋转校正的步骤,并附有详细注释。

具体如下:

import cv2
import numpy as np

def order_points(pts):
    """
    将四个点按左上、右上、右下、左下顺序排列
    """
    rect = np.zeros((4, 2), dtype="float32")
    # 按x坐标排序,分左右两组
    x_sorted = pts[np.argsort(pts[:, 0]), :]
    left = x_sorted[:2, :]
    right = x_sorted[2:, :]
    # 左组按y坐标排序(左上,左下)
    left = left[np.argsort(left[:, 1]), :]
    (tl, bl) = left
    # 右组按y坐标排序(右上,右下)
    right = right[np.argsort(right[:, 1]), :]
    (tr, br) = right
    return np.array([tl, tr, br, bl], dtype="float32")

def perspective_correction(img):
    """
    透视校正:检测图像中的四边形并进行透视变换
    """
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    # 自适应阈值处理增强边缘
    edged = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_MEAN_C, 
                                 cv2.THRESH_BINARY, 11, 2)
    # 查找轮廓
    contours, _ = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    contours = sorted(contours, key=cv2.contourArea, reverse=True)[:5]  # 取面积前5的轮廓

    for contour in contours:
        peri = cv2.arcLength(contour, True)
        approx = cv2.approxPolyDP(contour, 0.02 * peri, True)
        if len(approx) == 4:  # 检测到四边形
            ordered_pts = order_points(approx.reshape(4, 2))
            # 计算目标图像尺寸
            (tl, tr, br, bl) = ordered_pts
            width_top = np.linalg.norm(tr - tl)
            width_bottom = np.linalg.norm(br - bl)
            height_left = np.linalg.norm(bl - tl)
            height_right = np.linalg.norm(br - tr)
            max_width = max(int(width_top), int(width_bottom))
            max_height = max(int(height_left), int(height_right))
            # 目标四点坐标
            dst = np.array([
                [0, 0],
                [max_width - 1, 0],
                [max_width - 1, max_height - 1],
                [0, max_height - 1]], dtype="float32")
            # 计算变换矩阵并应用
            M = cv2.getPerspectiveTransform(ordered_pts, dst)
            warped = cv2.warpPerspective(img, M, (max_width, max_height))
            return warped
    return None  # 未找到四边形

def rotate_correction(image):
    """
    旋转校正:检测直线角度并旋转图像
    """
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    edges = cv2.Canny(gray, 50, 150, apertureSize=3)
    lines = cv2.HoughLines(edges, 1, np.pi / 180, 200)  # 霍夫变换检测直线
    
    if lines is None:
        return image
    
    angles = []
    for line in lines:
        rho, theta = line[0]
        # 计算直线角度(转换为度数)
        angle = np.degrees(theta) - 90  # 转换为相对于垂直线的角度
        angles.append(angle)
    
    median_angle = np.median(angles)
    # 仅在校正角度超过阈值时旋转
    if abs(median_angle) > 0.5:
        (h, w) = image.shape[:2]
        center = (w // 2, h // 2)
        M = cv2.getRotationMatrix2D(center, median_angle, 1.0)
        corrected = cv2.warpAffine(image, M, (w, h), borderMode=cv2.BORDER_REPLICATE)
        return corrected
    return image

def main(image_path):
    # 读取图像
    img = cv2.imread(image_path)
    if img is None:
        print("Error: 无法读取图像")
        return
    
    # 可选:镜头畸变校正(需提供相机参数)
    # img = cv2.undistort(img, camera_matrix, dist_coeffs)
    
    # 透视校正
    perspective_img = perspective_correction(img)
    if perspective_img is not None:
        # 旋转校正
        final_img = rotate_correction(perspective_img)
    else:
        # 直接旋转校正原图
        final_img = rotate_correction(img)
    
    # 显示结果
    cv2.imshow("Original", img)
    if perspective_img is not None:
        cv2.imshow("Perspective Corrected", perspective_img)
    cv2.imshow("Final Corrected", final_img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

if __name__ == "__main__":
    import sys
    if len(sys.argv) != 2:
        print("Usage: python image_correction.py <image_path>")
    else:
        main(sys.argv[1])

算法说明:

  1. 透视校正

    • 通过自适应阈值处理和轮廓检测找到图像中的四边形区域
    • 使用透视变换将四边形区域转换为正视图
    • 适用于文档、标牌等包含明显四边形结构的图像
  2. 旋转校正

    • 使用Canny边缘检测和霍夫变换检测直线
    • 计算直线角度的中位数作为图像倾斜角度
    • 根据倾斜角度旋转图像实现水平校正
  3. 畸变校正

    • 代码中已预留镜头畸变校正接口(需取消注释并提供相机标定参数)
    • 使用cv2.undistort()函数实现径向和切向畸变校正

使用说明:

  1. 安装依赖:pip install opencv-python numpy
  2. 运行命令:python image_correction.py <图片路径>
  3. 按任意键关闭窗口

该算法能有效校正大多数文档类图像的透视畸变和旋转问题,实际效果取决于图像中的特征检测质量,可通过调整阈值参数优化结果。

;