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

如何在OpenCV数独检测程序中添加图像变换(Warping)功能?

解决数独图像透视变换问题

核心思路

要实现透视变换,关键是获取数独网格的四个顶点,并将其映射到一个正方形的目标区域。cv2.warpPerspective 需要的变换矩阵可以通过 cv2.getPerspectiveTransform 计算,而这个函数需要有序的源点和目标点。

修改后的完整代码

import cv2
import numpy as np
import matplotlib.pyplot as plt

def order_points(pts):
    # 初始化有序坐标列表:[左上, 右上, 右下, 左下]
    rect = np.zeros((4, 2), dtype="float32")
    
    # 左上点的x+y和最小,右下点的x+y和最大
    s = pts.sum(axis=1)
    rect[0] = pts[np.argmin(s)]
    rect[2] = pts[np.argmax(s)]
    
    # 右上点的x-y差最小,左下点的x-y差最大
    diff = np.diff(pts, axis=1)
    rect[1] = pts[np.argmin(diff)]
    rect[3] = pts[np.argmax(diff)]
    
    return rect

def detect_and_warp_sudoku(image):
    # 转灰度图
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    # 自适应阈值处理
    thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
    
    # 查找轮廓
    contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    
    # 筛选面积最大的轮廓(数独网格)
    contour_with_max_area = max(contours, key=cv2.contourArea)
    
    # 轮廓近似为四边形
    peri = cv2.arcLength(contour_with_max_area, True)
    approx = cv2.approxPolyDP(contour_with_max_area, 0.02 * peri, True)
    
    # 获取数独四个顶点
    if len(approx) == 4:
        sudoku_corners = approx.reshape(4, 2).astype("float32")
    else:
        # 若无法检测到四边形,退化为 bounding rect
        x, y, w, h = cv2.boundingRect(contour_with_max_area)
        sudoku_corners = np.array([[x, y], [x+w, y], [x+w, y+h], [x, y+h]], dtype="float32")
    
    # 对顶点排序
    ordered_corners = order_points(sudoku_corners)
    
    # 定义目标正方形尺寸(可根据需求调整)
    dst_size = 450
    dst_points = np.array([[0, 0], [dst_size-1, 0], [dst_size-1, dst_size-1], [0, dst_size-1]], dtype="float32")
    
    # 计算透视变换矩阵
    M = cv2.getPerspectiveTransform(ordered_corners, dst_points)
    
    # 应用透视变换
    warped_image = cv2.warpPerspective(image, M, (dst_size, dst_size))
    
    return warped_image

# 加载图像并处理
image = cv2.imread('sudoku.jpg')
warped_sudoku = detect_and_warp_sudoku(image)

# 显示结果
plt.imshow(cv2.cvtColor(warped_sudoku, cv2.COLOR_BGR2RGB))
plt.title('Warped Sudoku')
plt.show()

cv2.imshow('Warped Sudoku', warped_sudoku)
cv2.waitKey(0)
cv2.destroyAllWindows()

关键步骤解析

  1. 轮廓近似:
    使用 cv2.approxPolyDP 将复杂轮廓简化为四边形,0.02 * peri 是近似精度(周长的2%),确保能准确捕捉数独的四个角。

  2. 顶点排序:
    通过计算坐标的和与差,将四个顶点按左上、右上、右下、左下的顺序排列,这是生成正确变换矩阵的前提。

  3. 透视变换矩阵计算:
    cv2.getPerspectiveTransform 接收有序的源顶点和目标正方形顶点,生成将源区域映射到目标区域的变换矩阵。

  4. 应用变换:
    cv2.warpPerspective 用生成的矩阵将数独网格变换为正上方视角的正方形图像,方便后续的数字识别和求解。

注意事项

  • 如果图像中数独网格倾斜严重,确保轮廓检测能准确捕捉到网格边界(可调整阈值参数或增加边缘检测步骤)。
  • 目标尺寸 dst_size 可根据需求调整,建议设置为9的倍数(比如450=9*50),方便后续分割每个单元格。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 19:30:38