Tkinter+OpenCV标注ROI时矩形不实时显示、points列表无法重置问题
问题修复方案
1. 矩形选框无法实时显示的问题
原因
- 仅在鼠标左键抬起时绘制最终矩形,未处理拖拽过程中的实时绘制逻辑
- 绘制矩形后未立即刷新窗口,后续弹出的tkinter对话框直接阻塞了渲染流程
修复方式
新增鼠标移动事件的处理逻辑,拖拽过程中基于原图副本实时重绘临时选框,每次绘制完成后立即刷新窗口。
2. 按r清空后仍保留历史ROI数据的问题
原因
- 条件判断误用位运算符
&,应使用逻辑运算符and,导致判断逻辑失效 - 未做类型匹配:
key是waitKey返回的整数,和字符串'r'比较永远返回True,判断条件完全不生效 - 完成单个ROI标注后未重置
rect列表,只要rect长度保持为4,每次while循环都会重复追加相同的ROI数据到points。你清空points后下一次循环会立刻把未重置的rect数据重新加回去,导致清空无效
修复方式
- 替换位运算符为逻辑运算符,修正按键比较的类型匹配
- 每次把ROI数据加入
points后立即重置rect为空列表,避免重复追加
修复后完整代码
import cv2 import numpy as np import tkinter import tkinter.simpledialog # 提前初始化tkinter实例,避免每次弹框都新建 root = tkinter.Tk() root.withdraw() rect = [] cropping = False def click_crop(event,x,y,flag,params): global rect,cropping, image, clone # 左键按下开始选框 if event==cv2.EVENT_LBUTTONDOWN: rect = [(x,y)] cropping = True # 拖拽时实时绘制选框 elif event == cv2.EVENT_MOUSEMOVE: if cropping: # 每次都基于原图副本绘制,避免拖影 temp_img = clone.copy() cv2.rectangle(temp_img, rect[0], (x,y), (255,0,0), 2) cv2.imshow('Image', temp_img) # 左键抬起完成选框 elif event == cv2.EVENT_LBUTTONUP: rect.append((x,y)) cropping = False # 绘制最终选框到原图上 cv2.rectangle(image,rect[0],rect[1],(255,0,0),2) cv2.imshow('Image', image) # 弹框输入标签 dtype = tkinter.simpledialog.askstring("Data Type","Text/Box..") info_type = tkinter.simpledialog.askstring("Info Type","Name/Country/Email/Phone..") rect.append(dtype) rect.append(info_type) image = cv2.imread("path_to_image") # 替换为你的图片路径 clone = image.copy() cv2.namedWindow('Image') cv2.setMouseCallback('Image',click_crop) points = [] while True: cv2.imshow('Image',image) key = cv2.waitKey(1) & 0xFF if key==ord('c'): break # 修正判断逻辑:运算符用and,按键比较用ord('r') elif len(rect)==4 and key!=ord('r'): points.append([(rect[0][0],rect[0][1],rect[1][0],rect[1][1]),rect[2],rect[3]]) # 加入后重置rect,避免重复追加 rect = [] elif key==ord('r'): # 重置所有状态 image = clone.copy() points.clear() rect = [] cropping = False print(points) print(points) new_points = [] for coords in points: if coords not in new_points: new_points.append(coords) print(new_points) cv2.destroyAllWindows() root.destroy() # 销毁tkinter实例
内容的提问来源于stack exchange,提问作者trunksabhi -
相关产品推荐
相关产品推荐

