相机标定、镜头畸变矫正或外参时常需要一张标准棋盘格,于是就有如下脚本。
脚本主要做的事情就是:先设定标定板的内角点数量(例如此脚本是9×6,注意这指的是黑白格交界处的角点数,而实际方格数要在此基础上各加1变成10×7)以及每个方格的物理边长(毫米),再把A4纸张(210×297mm)和打印分辨率DPI(例如是300)换算成像素尺寸(用mm_to_pix = dpi/25.4完成mm到px的转换),创建一张A4像素大小的白底灰度图,然后计算棋盘格再像素空间的宽高并将其再A4上居中,最后按行遍历每个方格位置,用(r+c)%2控制黑白相间,把对应的像素区域涂成黑色,从而得到一张可以直接打印的A4棋盘格图片,最终可以保存为一张PNG图片。去打印的时候只需要选择“实际大小/100%/不缩放”,打印出来的每格边长就能接近设置的毫米尺寸。
import numpy as np
import cv2
from math import floor
#======== 可根据需要修改的参数 ========#
# 棋盘格参数(用于 cv2.findChessboardCorners 的内角点个数)
inner_rows = 6 # 内角点行数(垂直方向)
inner_cols = 9 # 内角点列数(水平方向)
square_size_mm = 20 # 每个方格的边长(毫米)
# 纸张参数(A4)
a4_width_mm = 210
a4_height_mm = 297
# 打印分辨率
dpi = 300
#===================================#
mm_to_pix = dpi / 25.4 # 1英寸=25.4mm
paper_w_px = int(round(a4_width_mm * mm_to_pix))
paper_h_px = int(round(a4_height_mm * mm_to_pix))
# 棋盘格的总方格数 = 内角点数 + 1
board_cols = inner_cols + 1
board_rows = inner_rows + 1
board_w_mm = board_cols * square_size_mm
board_h_mm = board_rows * square_size_mm
board_w_px = int(round(board_w_mm * mm_to_pix))
board_h_px = int(round(board_h_mm * mm_to_pix))
# 创建白色 A4 底图
img = np.ones((paper_h_px, paper_w_px), dtype=np.uint8) * 255
# 让棋盘居中
start_x = (paper_w_px - board_w_px) // 2
start_y = (paper_h_px - board_h_px) // 2
square_size_px = square_size_mm * mm_to_pix
for r in range(board_rows):
for c in range(board_cols):
# 生成黑白相间的棋盘格
if (r + c) % 2 == 0:
x0 = int(round(start_x + c * square_size_px))
y0 = int(round(start_y + r * square_size_px))
x1 = int(round(start_x + (c + 1) * square_size_px))
y1 = int(round(start_y + (r + 1) * square_size_px))
img[y0:y1, x0:x1] = 0
# 保存为 PNG(300DPI 时像素 ~ 2480x3508)
output_name = f"chessboard_A4_{dpi}dpi_{inner_cols}x{inner_rows}_{square_size_mm}mm.png"
cv2.imwrite(output_name, img)
print("保存文件:", output_name)
print("内角点尺寸(用于 OpenCV 标定):", (inner_cols, inner_rows))
print("单格边长(mm):", square_size_mm)
效果图如下:
