""" 作者:太一 微信:taiyi1224 邮箱:shuobo1224@qq.com """ import math import cv2 import numpy as np class ResizeHandle: """图片缩放控制点""" def __init__(self, position): # 位置: 'tl', 'tr', 'bl', 'br' 分别代表四个顶点 self.position = position self.active = False self.x = 0 self.y = 0 self.radius = 5 # 控制点半径,从8减小到5 def hit_test(self, x, y): """检查点是否在控制范围内""" dx = x - self.x dy = y - self.y return math.sqrt(dx * dx + dy * dy) <= self.radius class TransformHelper: """图片变形辅助工具""" @staticmethod def calculate_handles(fg, canvas): """计算四个顶点的控制点位置""" handles = { 'tl': ResizeHandle('tl'), 'tr': ResizeHandle('tr'), 'bl': ResizeHandle('bl'), 'br': ResizeHandle('br') } # 转换顶点坐标到画布坐标 for i, pos in enumerate(['tl', 'tr', 'bl', 'br']): x, y = fg.vertices[i] canvas_x, canvas_y = canvas.template_to_canvas(x, y) handles[pos].x = canvas_x handles[pos].y = canvas_y return handles @staticmethod def update_vertices(fg, handle_pos, dx, dy, canvas): """根据拖动的控制点更新顶点坐标和图片尺寸""" t_dx, t_dy = canvas.canvas_to_template(dx, dy) idx_map = {'tl': 0, 'tr': 1, 'bl': 2, 'br': 3} idx = idx_map[handle_pos] # 更新对应顶点 x, y = fg.vertices[idx] new_x, new_y = x + t_dx, y + t_dy # 获取其他顶点 tl = fg.vertices[0] if idx != 0 else (new_x, new_y) tr = fg.vertices[1] if idx != 1 else (new_x, new_y) bl = fg.vertices[2] if idx != 2 else (new_x, new_y) br = fg.vertices[3] if idx != 3 else (new_x, new_y) # 计算宽度和高度 width = max(abs(tr[0] - tl[0]), abs(br[0] - bl[0])) height = max(abs(bl[1] - tl[1]), abs(br[1] - tr[1])) # 确保最小尺寸 if width < 10 or height < 10: # 如果太小,则不更新 return fg fg.vertices[idx] = (new_x, new_y) return fg @staticmethod def get_perspective_matrix(src_vertices, dst_size): """计算透视变换矩阵""" # 源坐标:图片四个角 src = np.float32([ [0, 0], [dst_size[0], 0], [0, dst_size[1]], [dst_size[0], dst_size[1]] ]) # 目标坐标:变形后的四个角 dst = np.float32(src_vertices) # 计算透视变换矩阵 return cv2.getPerspectiveTransform(src, dst) @staticmethod def update_image_size(fg, handle_pos, dx, dy, canvas): """根据拖动的控制点更新图片尺寸""" t_dx, t_dy = canvas.canvas_to_template(dx, dy) if handle_pos in ['nw', 'sw', 'w']: fg.x += t_dx fg.w -= t_dx if handle_pos in ['ne', 'se', 'e']: fg.w += t_dx if handle_pos in ['nw', 'ne', 'n']: fg.y += t_dy fg.h -= t_dy if handle_pos in ['sw', 'se', 's']: fg.h += t_dy # 确保尺寸为正值 fg.w = max(10, fg.w) fg.h = max(10, fg.h) return fg