提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
项目中有需要用到在图片上面绘制旋转矩形框,用于得到框选区域。一般的矩形框是不带旋转角度。目前没有找到比较好用的旋转矩形框,这个是博主结合自身需求,通过鼠标控制,在图片上绘制出来矩形框,可以和鼠标进行交互。下面是示例图片,这个是一个简单demo,后续你可以根据得到框,把对应数据取出来,也可以把图片扣出来,根据角度,做一个仿射变换得到矫正后的正的矩形。
示例gif图片,这个是最后代码运行出来效果。可以旋转,移动,缩放。

在计算机视觉领域,旋转矩形的标注与编辑是一个常见需求,无论是目标检测中的边界框标注,还是图像测量中的区域划定,都离不开直观易用的旋转矩形交互工具。本文将基于 OpenCV 和 NumPy 实现一个功能完整的可交互旋转矩形编辑工具,支持矩形的移动、旋转和多方式缩放操作,并详细解析其核心技术原理。
一.工具核心功能概述
本工具实现了一个可视化的旋转矩形编辑界面,主要功能包括:
-
实时显示旋转矩形及各类控制点(中心、旋转手柄、边中点、角落点)
-
鼠标交互操作:
-
拖动中心控制点移动矩形
-
拖动旋转手柄(蓝色)旋转矩形
-
拖动边中点(紫色)沿垂直边方向缩放
-
拖动角落点(青色)同时调整矩形宽高
-
-
自动处理坐标转换与旋转逻辑,确保交互自然流畅
二.完整代码示例
下面是完整代码示例,直接复制粘贴可以运行
import cv2
import numpy as np
# 全局变量
rects = [] # 存储所有矩形,每个矩形包含center, size, angle
selected_rect_idx = None # 当前选中的矩形索引
drawing = False # 是否正在拖动
current_mode = None # 'move', 'rotate', 'resize'
selected_handle = None # 选中的手柄类型
initial_mouse_pos = None # 初始鼠标位置
initial_rect_params = None # 初始矩形参数
initial_mouse_local = None # 初始鼠标局部坐标
def compute_handles(center, size, angle):
"""计算矩形的控制点坐标"""
w, h = size[0] / 2, size[1] / 2
# 计算旋转手柄的距离为矩形对角线长度的一半
handle_distance = np.sqrt(w**2 + h**2) * 0.5
return {
'center': (int(center[0]), int(center[1])),
'rotate_handle': (
int(local_to_global(handle_distance, 0, center, angle)[0]),
int(local_to_global(handle_distance, 0, center, angle)[1])
),
'left': (
int(local_to_global(-w, 0, center, angle)[0]),
int(local_to_global(-w, 0, center, angle)[1])
),
'right': (
int(local_to_global(w, 0, center, angle)[0]),
int(local_to_global(w, 0, center, angle)[1])
),
'top': (
int(local_to_global(0, h, center, angle)[0]),
int(local_to_global(0, h, center, angle)[1])
),
'bottom': (
int(local_to_global(0, -h, center, angle)[0]),
int(local_to_global(0, -h, center, angle)[1])
),
'corner': (
int(local_to_global(w, h, center, angle)[0]),
int(local_to_global(w, h, center, angle)[1])
)
}
def draw_rotated_rect(img, rect, is_selected=False):
"""绘制旋转矩形及控制点"""
center = rect['center']
size = rect['size']
angle = rect['angle']
# 绘制旋转矩形
rect_obj = ((center[0], center[1]), (size[0], size[1]), angle)
box = cv2.boxPoints(rect_obj)
box = np.intp(box)
color =


735

被折叠的 条评论
为什么被折叠?



