You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Python将数独棋盘图像调整为完美正方形?

如何用Python将数独棋盘图像调整为完美正方形?

嗨,我来帮你搞定这个问题!要把非正方形的数独棋盘图像转换成完美正方形,最靠谱的方法是先校正可能存在的透视倾斜,再把数独区域精准转换成标准正方形——毕竟咱们要切81个小格子,必须保证棋盘是正的、四边等长才行。下面用Python结合OpenCV来实现,步骤清晰又好懂:

核心思路

数独棋盘本身是正方形,只是拍摄时可能会有角度倾斜、边缘裁剪不当的问题。我们要先从图像里定位出数独的完整轮廓,再通过透视变换把它拉成正的正方形,这样后续分割成81个小单元格就没问题了。

具体实现步骤

  1. 图像预处理:突出数独轮廓
    先把彩色图像转成灰度图,再做二值化处理,让数独的线条和背景区分开,方便后续找轮廓。

  2. 定位数独棋盘的轮廓
    找出图像里所有的轮廓,筛选出面积最大的那个(大概率就是数独棋盘),然后用多边形近似得到棋盘的四个顶点。

  3. 排序顶点并计算正方形尺寸
    把四个顶点按「左上→右上→右下→左下」的顺序排好,然后计算棋盘的最大边长(因为数独是正方形,所以取宽和高中的最大值作为目标正方形的边长)。

  4. 透视变换得到完美正方形
    用透视变换矩阵把不规则的数独区域映射成标准正方形。

完整代码示例

import cv2
import numpy as np

def get_sudoku_square(image_path):
    # 1. 读取图像并预处理
    img = cv2.imread(image_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    # 二值化(自适应阈值,适配不同光照)
    thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
    
    # 2. 寻找数独轮廓
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    # 筛选面积最大的轮廓
    sudoku_contour = max(contours, key=cv2.contourArea)
    
    # 3. 获取并排序四个顶点
    epsilon = 0.02 * cv2.arcLength(sudoku_contour, True)
    approx = cv2.approxPolyDP(sudoku_contour, epsilon, True)
    # 确保是四个顶点的矩形
    if len(approx) != 4:
        raise ValueError("无法检测到数独棋盘的四个顶点,请检查图像清晰度")
    
    # 把顶点转换成(x,y)坐标并排序
    points = approx.reshape(4, 2).astype(np.float32)
    # 按x+y从小到大排序(左上点最小)
    points = points[np.argsort(points.sum(axis=1))]
    # 右上和左下按x坐标排序
    if points[1][0] < points[2][0]:
        points[1], points[2] = points[2], points[1]
    top_left, top_right, bottom_right, bottom_left = points
    
    # 4. 计算目标正方形的边长
    width = int(max(np.linalg.norm(top_right - top_left), np.linalg.norm(bottom_right - bottom_left)))
    height = int(max(np.linalg.norm(bottom_left - top_left), np.linalg.norm(bottom_right - top_right)))
    square_size = max(width, height)
    
    # 目标正方形的四个顶点
    dst_points = np.array([
        [0, 0],
        [square_size - 1, 0],
        [square_size - 1, square_size - 1],
        [0, square_size - 1]
    ], dtype=np.float32)
    
    # 透视变换
    M = cv2.getPerspectiveTransform(points, dst_points)
    sudoku_square = cv2.warpPerspective(img, M, (square_size, square_size))
    
    return sudoku_square

# 使用示例
square_sudoku = get_sudoku_square("your_sudoku_image.png")
# 保存处理后的正方形图像
cv2.imwrite("square_sudoku.png", square_sudoku)

额外小贴士

  • 如果你的图像没有透视倾斜,只是比例不对,也可以直接用cv2.resize调整成正方形,但透视校正的方法更通用,能应对大多数拍摄角度的问题。
  • 预处理时的二值化参数可以根据你的图像微调,比如调整自适应阈值的窗口大小,让数独轮廓更清晰。

备注:内容来源于stack exchange,提问作者Ernest Vandenbulcke

火山引擎 最新活动