You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CustomTkinter+cv2实现图像矩形标注 修复仅绘制线条问题

问题根因

当前代码实现的是自由手绘逻辑,根本没写矩形框选的对应逻辑,具体问题点:

  • 画布层:鼠标拖动事件<B1-Motion>里持续调用create_line逐段拼接鼠标移动路径,最终呈现的就是手绘线条,没有任何矩形绘制逻辑。
  • OpenCV图像层:拖动过程中反复以上一次鼠标瞬时位置、当前鼠标瞬时位置为对角点绘制极小的矩形,没有做预览刷新,所有小矩形沿鼠标路径堆叠后视觉上和线条一致,不是从按下起点到当前位置的完整选框。
  • 事件缺失:没有绑定鼠标左键释放事件,无法确定矩形选框的终点,也没有临时预览图形的清除逻辑,拖动时会产生大量拖影残留。
修复方案

把绘制逻辑改成标准矩形框选流程:鼠标按下记录起点、拖动时实时刷新矩形预览、鼠标释放时确定最终选框并同步绘制到OpenCV图像用于后续保存,核心修改代码如下:

  1. 替换原有的事件绑定逻辑,补充鼠标释放事件绑定
def draw_action(self):
    self.color_code = ((255, 0, 0), '#ff0000')
    self.refresh_side_frame()
    # 绑定矩形绘制对应事件
    self.canvas.bind('<ButtonPress-1>', self.start_draw)
    self.canvas.bind('<B1-Motion>', self.draw_preview)
    self.canvas.bind('<ButtonRelease-1>', self.finish_draw)
    self.draw_color_button = ttk.Button(self.side_frame,
            text='Pick A Color', command=self.choose_color)
    self.draw_color_button.grid(row=0, column=2, padx=5, pady=5,
                                sticky='sw')
  1. 重写鼠标按下回调,记录矩形起点
def start_draw(self, event):
    # 记录选框起点坐标
    self.rect_start_x = event.x
    self.rect_start_y = event.y
    self.temp_rect_id = None  # 存储临时预览矩形的画布ID,用于拖动时刷新
  1. 替换原有的逐段画线逻辑,实现拖动时的矩形实时预览
def draw_preview(self, event):
    # 先删除上一帧的临时预览,避免拖影
    if self.temp_rect_id is not None:
        self.canvas.delete(self.temp_rect_id)
    # 以起点和当前鼠标位置为对角点,绘制新的临时预览矩形
    self.temp_rect_id = self.canvas.create_rectangle(
        self.rect_start_x,
        self.rect_start_y,
        event.x,
        event.y,
        width=2,
        outline=self.color_code[-1],
        dash=(4, 2)  # 虚线显示预览状态,和最终确定的选框做区分
    )
  1. 新增鼠标释放回调,确定最终选框并同步到OpenCV图像
def finish_draw(self, event):
    # 清除最后一帧临时预览
    if self.temp_rect_id is not None:
        self.canvas.delete(self.temp_rect_id)
    rect_end_x, rect_end_y = event.x, event.y
    # 在画布上绘制最终确定的标注矩形
    self.canvas.create_rectangle(
        self.rect_start_x,
        self.rect_start_y,
        rect_end_x,
        rect_end_y,
        width=2,
        outline=self.color_code[-1]
    )
    # 坐标换算后将矩形同步绘制到OpenCV格式的源图,用于后续保存
    cv2.rectangle(
        self.filtered_image,
        (int(self.rect_start_x * self.ratio), int(self.rect_start_y * self.ratio)),
        (int(rect_end_x * self.ratio), int(rect_end_y * self.ratio)),
        self.color_code[0],  # 用用户选择的颜色,替换原代码写死的绿色
        thickness=int(self.ratio * 2),
        lineType=8
    )
补充说明
  • 原代码中prev_action、next_action方法内错误调用了颜色选择器,记得替换为上一张/下一张图片的切换逻辑,否则切换图片时会异常弹出取色窗口。
  • 如果需要实现撤销功能,可将每次绘制的矩形画布ID、对应坐标存入列表,撤销时删除画布对应元素,同时将self.filtered_image恢复到绘制前的状态即可。
  • 标注完成后直接调用cv2.imwrite(保存路径, self.filtered_image)即可导出带矩形标注的图像文件。

内容的提问来源于stack exchange,提问作者Suraj Kumar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 12:21:18