使用Python与OpenCV检测图像中矩形板角点坐标的实现咨询
矩形板角点检测实现方案
核心流程
在已经生成的Canny边缘检测结果基础上,不需要大幅修改原有边缘检测逻辑,依次完成边缘断线补全、轮廓筛选、角点精定位即可输出目标坐标。
- 对Canny输出的二值边缘图做形态学闭运算,连接断续的边缘线段,避免轮廓识别时出现断裂
- 提取图像内所有闭合轮廓,按轮廓面积、多边形顶点数筛选出符合矩形板大小的4顶点闭合轮廓
- 对筛选得到的四边形轮廓做亚像素级角点校正,消除边缘检测带来的像素级误差
- 整理角点顺序,在原图上做标记验证检测效果
完整可运行脚本
import cv2 import numpy as np # 原有边缘检测逻辑(保留已编写的功能) image_original = cv2.imread('c:/python_test/camera_pics/Basler_acA640-300gm__22354308__20210211_135725420_36.tiff', cv2.IMREAD_COLOR) image_gray = cv2.cvtColor(image_original, cv2.COLOR_BGR2GRAY) # 轻微高斯模糊降低边缘检测噪声 image_gray = cv2.GaussianBlur(image_gray, (5, 5), 0) filtered_image = cv2.Canny(image_gray, threshold1=20, threshold2=200) # 新增角点检测模块 # 1. 闭运算填补边缘断线 kernel = np.ones((3, 3), np.uint8) closed_edges = cv2.morphologyEx(filtered_image, cv2.MORPH_CLOSE, kernel, iterations=2) # 2. 提取所有轮廓 contours, hierarchy = cv2.findContours(closed_edges, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # 3. 筛选目标矩形轮廓 target_contour = None max_area = 0 for cnt in contours: area = cv2.contourArea(cnt) # 过滤面积过小的噪声轮廓 if area < 1000: continue # 多边形逼近轮廓,计算近似顶点数 perimeter = cv2.arcLength(cnt, closed=True) approx = cv2.approxPolyDP(cnt, 0.02 * perimeter, closed=True) # 保留面积最大的4顶点轮廓作为目标矩形 if len(approx) == 4 and area > max_area: max_area = area target_contour = approx # 4. 亚像素角点精细化校正 if target_contour is not None: target_corners = target_contour.reshape(4, 2).astype(np.float32) # 设定亚像素校正的终止条件 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) refined_corners = cv2.cornerSubPix(image_gray, target_corners, (11, 11), (-1, -1), criteria) # 按固定顺序整理角点:左上、右上、右下、左下 rect_corners = np.zeros((4, 2), dtype=np.float32) s = refined_corners.sum(axis=1) rect_corners[0] = refined_corners[np.argmin(s)] # 左上:横纵坐标和最小 rect_corners[2] = refined_corners[np.argmax(s)] # 右下:横纵坐标和最大 diff = np.diff(refined_corners, axis=1) rect_corners[1] = refined_corners[np.argmin(diff)] # 右上:纵-横差值最小 rect_corners[3] = refined_corners[np.argmax(diff)] # 左下:纵-横差值最大 # 打印输出角点坐标 print("检测到的矩形角点坐标(按左上/右上/右下/左下顺序):") for idx, corner in enumerate(rect_corners): print(f"角点{idx+1}: (x={corner[0]:.2f}, y={corner[1]:.2f})") # 在原图上标记角点,方便目视验证 for corner in rect_corners: x, y = int(corner[0]), int(corner[1]) cv2.circle(image_original, (x, y), 5, (0, 0, 255), -1) # 保存输出文件 cv2.imwrite('c:/python_test/test.bmp', filtered_image) cv2.imwrite('c:/python_test/detect_result.jpg', image_original)
参数调整说明
- 如果需要同时检测矩形板的内框、外框角点,不需要修改轮廓检索模式的
RETR_TREE参数,该模式会遍历图像内所有层级的轮廓,可按轮廓的嵌套层级区分内框、外框轮廓后分别输出坐标 - 轮廓面积过滤阈值
1000可根据实际图像中矩形的大小调整,若误检小矩形,可适当提高该阈值 - 多边形逼近的精度系数
0.02 * perimeter可根据轮廓的圆角程度调整,若圆角较大导致顶点数识别不准,可将系数调低至0.01-0.03区间匹配实际形状 - 若边缘图存在较多细碎干扰,可适当提高闭运算的迭代次数,增强断线连接效果
内容的提问来源于stack exchange,提问作者Roy Meijer
相关产品推荐
相关产品推荐

