import cv2 import numpy as np # 全局变量 points = [] # 存储选择的四个点 img = None # 存储原始图像 img_copy = None # 用于绘制的图像副本 def mouse_callback(event, x, y, flags, param): """鼠标回调函数,用于选择四个点""" global img_copy, points if event == cv2.EVENT_LBUTTONDOWN: if len(points) < 4: points.append((x, y)) print(f"已选择点 {len(points)}: ({x}, {y})") # 在图像上绘制点 cv2.circle(img_copy, (x, y), 5, (0, 255, 0), -1) # 如果已经选择了4个点,绘制连线 if len(points) == 4: # 按照上、右、下、左的顺序连接点 for i in range(4): cv2.line(img_copy, points[i], points[(i + 1) % 4], (0, 255, 0), 2) # 标记每个点的位置 cv2.putText(img_copy, "Top", points[0], cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) cv2.putText(img_copy, "Right", points[1], cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) cv2.putText(img_copy, "Bottom", points[2], cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) cv2.putText(img_copy, "Left", points[3], cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 0, 255), 2) cv2.imshow("Select Points", img_copy) def perspective_transform(image, src_points): """执行透视变换""" # 将点排序为上、右、下、左 top, right, bottom, left = src_points # 计算新图像的宽度(取左右边的最大值) width_a = np.linalg.norm(np.array(right) - np.array(left)) width_b = np.linalg.norm(np.array(top) - np.array(bottom)) max_width = max(int(width_a), int(width_b)) # 计算新图像的高度(取上下边的最大值) height_a = np.linalg.norm(np.array(bottom) - np.array(top)) height_b = np.linalg.norm(np.array(right) - np.array(left)) max_height = max(int(height_a), int(height_b)) # 定义目标点 dst = np.array([ [0, 0], # 左上角 [max_width - 1, 0], # 右上角 [max_width - 1, max_height - 1], # 右下角 [0, max_height - 1] # 左下角 ], dtype="float32") # 转换源点数组为numpy数组 src = np.array([top, right, bottom, left], dtype="float32") # 计算透视变换矩阵 M = cv2.getPerspectiveTransform(src, dst) # 执行透视变换 warped = cv2.warpPerspective(image, M, (max_width, max_height)) return warped def k_perspective_transform(image, src_points): """执行透视变换""" # 将点排序为上、右、下、左 top, right, bottom, left = src_points # 计算新图像的宽度(取左右边的最大值) sub_zy = np.array(right) - np.array(left) sub_sx = np.array(top) - np.array(bottom) sub_x=sub_sx[0]/2 print("x差值",sub_sx[0]) sub_y = sub_zy[1] / 2 print("y差值", sub_sx[0]) # 定义目标点 dst = np.array([ [top[0]-sub_x, top[1]], # 左上角 [right[0], right[1]- sub_y], # 左上角 [bottom[0]+sub_x, bottom[1]], # 左上角 [left[0] , left[1]+ sub_y], # 左上角 ], dtype="float32") # 转换源点数组为numpy数组 src = np.array([top, right, bottom, left], dtype="float32") # 计算透视变换矩阵 M = cv2.getPerspectiveTransform(src, dst) print(f"矩阵M={M}") # 执行透视变换 warped = cv2.warpPerspective(image, M, (1050, 900)) return warped def main(): global img, img_copy, points # 读取图像 img = cv2.imread("images/trans/subRawImg.jpg") if img is None: print("无法加载图像,请检查路径是否正确") return img_copy = img.copy() # 创建窗口并设置鼠标回调 cv2.namedWindow("Select Points") cv2.setMouseCallback("Select Points", mouse_callback) print("请按顺序点击选择四个点:上、右、下、左") print("选择完成后按任意键继续...") while True: cv2.imshow("Select Points", img_copy) key = cv2.waitKey(1) & 0xFF # 如果已经选择了4个点,按任意键继续 if len(points) == 4: break # 执行透视变换 warped = k_perspective_transform(img, points) # 显示结果 cv2.imshow("Original Image", img) cv2.imshow("Transformed", warped) output_path="images/trans/_4point.jpg" cv2.imwrite(output_path, warped) print(f"图像已保存到 {output_path}") cv2.waitKey(0) cv2.destroyAllWindows() if __name__ == "__main__": main()