You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用OpenCV提取A4扫描件中任意朝向的最大类矩形支票?

非AI模型提取A4扫描图中倾斜支票的最优方案

问题分析

你当前的代码存在三个核心问题:

  • 未对矩形轮廓的尺寸、比例做过滤,导致所有微小四边形都被误提取
  • 使用RETR_TREE模式会获取过多层级的内部小轮廓
  • 没有针对倾斜矩形的透视校正处理,无法输出正立的支票图像

优化解决方案

核心思路

  1. 预处理图像以减少噪声干扰,强化支票边缘
  2. 筛选符合支票尺寸、比例特征的四边形轮廓
  3. 对倾斜轮廓做透视变换,输出校正后的正立支票

完整代码实现

import cv2
import numpy as np
from google.colab.patches import cv2_imshow

def extract_cheque(image_path):
    # 读取原始图像
    image = cv2.imread(image_path)
    orig_image = image.copy()
    img_height, img_width = image.shape[:2]

    # 预处理:模糊降噪+边缘检测
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    edges = cv2.Canny(blurred, 30, 150)

    # 形态学膨胀:连接断裂的支票边缘
    dilate_kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    dilated_edges = cv2.dilate(edges, dilate_kernel, iterations=2)

    # 只提取最外层大轮廓,跳过内部小轮廓
    contours, _ = cv2.findContours(dilated_edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # 按轮廓面积从大到小排序,优先处理大目标
    contours = sorted(contours, key=cv2.contourArea, reverse=True)

    for contour in contours:
        contour_area = cv2.contourArea(contour)
        # 过滤过小轮廓:只保留占图像面积1/20以上的区域
        if contour_area < (img_height * img_width) / 20:
            continue

        # 多边形逼近,提取四边形轮廓
        epsilon = 0.02 * cv2.arcLength(contour, True)
        approx_poly = cv2.approxPolyDP(contour, epsilon, True)

        if len(approx_poly) == 4:
            # 校验宽高比:匹配支票典型比例(1.5-2.5,旋转后为0.4-0.67)
            x, y, rect_w, rect_h = cv2.boundingRect(approx_poly)
            aspect_ratio = float(rect_w) / rect_h
            if (1.5 < aspect_ratio < 2.5) or (0.4 < aspect_ratio < 0.67):
                # 重新排列四点顺序:左上、右上、右下、左下
                pts = approx_poly.reshape(4, 2)
                target_rect = np.zeros((4, 2), dtype="float32")

                # 通过坐标和与差确定四点位置
                coord_sum = pts.sum(axis=1)
                target_rect[0] = pts[np.argmin(coord_sum)]
                target_rect[2] = pts[np.argmax(coord_sum)]

                coord_diff = np.diff(pts, axis=1)
                target_rect[1] = pts[np.argmin(coord_diff)]
                target_rect[3] = pts[np.argmax(coord_diff)]

                # 计算目标矩形的实际尺寸
                max_width = int(max(np.linalg.norm(target_rect[0]-target_rect[1]), 
                                   np.linalg.norm(target_rect[2]-target_rect[3])))
                max_height = int(max(np.linalg.norm(target_rect[1]-target_rect[2]), 
                                    np.linalg.norm(target_rect[3]-target_rect[0])))

                # 定义透视变换的目标坐标
                dst_coords = np.array([
                    [0, 0],
                    [max_width - 1, 0],
                    [max_width - 1, max_height - 1],
                    [0, max_height - 1]], dtype="float32")

                # 执行透视变换,校正倾斜
                transform_matrix = cv2.getPerspectiveTransform(target_rect, dst_coords)
                corrected_cheque = cv2.warpPerspective(orig_image, transform_matrix, (max_width, max_height))

                # 显示并返回校正后的支票
                cv2_imshow(corrected_cheque)
                # 可选:保存结果
                # cv2.imwrite('corrected_cheque.jpg', corrected_cheque)
                return corrected_cheque

    print("未检测到符合条件的支票轮廓")
    return None

# 调用函数处理图像
extract_cheque('/content/img.jpg')

关键优化说明

  • 预处理优化:高斯模糊减少噪声干扰,膨胀操作连接支票边缘的断裂部分,避免轮廓被拆分
  • 轮廓筛选:使用RETR_EXTERNAL模式只提取最外层轮廓,结合面积、宽高比过滤,精准定位支票区域
  • 透视校正:重新排列四边形顶点顺序,通过透视变换将倾斜支票转换为正立的矩形图像

内容的提问来源于stack exchange,提问作者Sadaf Shafi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 22:00:56