Python实现孔填充与坐标转换
一、问题背景
在工业自动化、材料加工等领域,常需要在图像识别的闭合区域内生成等间距的孔位坐标。本文基于OpenCV库,提出一种从图像边界提取到物理坐标生成的完整解决方案,实现以下核心功能:
- 像素坐标到实际尺寸的转换
- 安全间距的孔位生成(孔与孔、孔与边界保持固定间距)
- 坐标系转换(图像左上角原点 → 笛卡尔坐标系中心原点)
- 标准化坐标文件输出
二、实现原理
1. 网格化生成算法
在区域的最小包围盒内生成等间距网格,筛选同时满足以下条件的点:
- 位于闭合区域内部
- 与边界保持至少一个孔间距的距离
2. 坐标转换公式
实现坐标系平移与Y轴翻转:
实际X = 像素X × 缩放系数 - 中心偏移X
实际Y = 中心偏移Y - 像素Y × 缩放系数
三、完整代码实现
import cv2
import numpy as npdef generate_holes(contour, img_width, img_height, scaling_factor, hole_spacing_actual):""" 生成符合间距要求的孔位坐标Args:contour: OpenCV提取的闭合轮廓img_width: 图像宽度(像素)img_height: 图像高度(像素)scaling_factor: 实际单位/像素(如0.1 mm/px)hole_spacing_actual: 实际孔间距(单位需与缩放系数一致)Returns:转换后的笛卡尔坐标列表"""# 计算像素间距hole_spacing_pixel = hole_spacing_actual / scaling_factor# 获取轮廓包围盒x_min, y_min, w, h = cv2.boundingRect(contour)# 生成网格坐标x_coords = np.arange(x_min, x_min + w + 1e-9, hole_spacing_pixel)y_coords = np.arange(y_min, y_min + h + 1e-9, hole_spacing_pixel)# 筛选有效点valid_points = []for x_p in x_coords:for y_p in y_coords:# 检测点是否在轮廓内且满足间距dist = cv2.pointPolygonTest(contour, (float(x_p), float(y_p)), True)if dist >= hole_spacing_pixel:valid_points.append((x_p, y_p))# 坐标系转换center_x = img_width * scaling_factor / 2center_y = img_height * scaling_factor / 2actual_points = []for (x_p, y_p) in valid_points:x_actual = x_p * scaling_factor - center_xy_actual = center_y - y_p * scaling_factor # Y轴翻转actual_points.append((round(x_actual, 2), round(y_actual, 2)))return actual_pointsdef main():# ====== 参数配置 ======IMG_PATH = "sample.png" # 输入图像路径SCALING_FACTOR = 0.1 # 实际单位/像素(例如:0.1 mm/px)HOLE_SPACING_ACTUAL = 10.0 # 实际孔间距(单位需与缩放系数一致)OUTPUT_FILE = "output.txt" # 输出文件名# ====== 图像处理 ====== # 读取图像并提取轮廓img = cv2.imread(IMG_PATH, cv2.IMREAD_GRAYSCALE)_, thresh = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 获取主轮廓main_contour = max(contours, key=cv2.contourArea)# ====== 生成孔位 ======img_height, img_width = img.shape[:2]holes = generate_holes(main_contour, img_width, img_height, SCALING_FACTOR, HOLE_SPACING_ACTUAL)# ====== 结果输出 ======with open(OUTPUT_FILE, 'w') as f:f.write(f"{HOLE_SPACING_ACTUAL}\n")for point in holes:f.write(f"{point[0]},{point[1]}\n")print(f"生成完成,有效孔位数量:{len(holes)}")if __name__ == "__main__":main()
四、代码说明
1. 关键函数
generate_holes()
:核心处理函数,完成网格生成、边界检测和坐标转换cv2.pointPolygonTest()
:OpenCV内置函数,检测点与轮廓的位置关系
2. 输入输出
- 输入要求:二值化图像(背景为黑,目标区域为白)
- 输出格式:
10.0 // 孔间距 -35.5,20.3 // X,Y坐标 -25.5,18.6 ... // 后续坐标点
3. 坐标系转换验证
原始图像坐标系(左上角原点)与转换后坐标系对比:
图像坐标(100,100) → 实际坐标( (100×0.1)-40, 30-(100×0.1) ) = (-30.0, 20.0)
(假设图像尺寸800x600,缩放系数0.1 mm/px)
五、使用流程
- 准备二值化图像,确保目标区域为白色闭合轮廓
- 设置参数:
SCALING_FACTOR
(标定参数)、HOLE_SPACING_ACTUAL
(工艺参数) - 运行程序,生成包含物理坐标的文本文件
本方案将图像处理与几何计算相结合,为自动化加工系统提供可直接使用的坐标数据,适用于PCB钻孔、激光切割等多种工业场景。通过调整参数配置,可快速适配不同精度要求的工程项目。