Colab中cv2.setMouseCallback()无法工作的问题求助
问题:Colab中OpenCV鼠标交互代码崩溃,无法绘制线条/多边形并获取坐标
我需要在图像上通过鼠标点击绘制线条或多边形,并获取这些图形的点坐标。本地PC运行正常的代码,在Colab中执行到cv2.setMouseCallback('image',printCoordinate)时崩溃,已替换cv2.imshow为Colab支持的cv2_imshow,求解决方法。
原代码:
import cv2 import numpy as np from google.colab.patches import cv2_imshow prevX,prevY=-1,-1 def printCoordinate(event, x, y, flags, params): global prevX,prevY if event==cv2.EVENT_LBUTTONDOWN: cv2.circle(img,(x,y),3,(255,255,255),-1) strXY='('+str(x)+','+str(y)+')' font=cv2.FONT_HERSHEY_PLAIN cv2.putText(img,strXY,(x+10,y-10),font,1,(255,255,255)) if prevX==-1 and prevY==-1: prevX,prevY=x,y else: cv2.line(img,(prevX,prevY),(x,y),(0,0,255),5) prevX,prevY=-1,-1 cv2_imshow(img) img = np.zeros((800,800,3),dtype=np.uint8) cv2.namedWindow('image', cv2.WINDOW_AUTOSIZE) cv2_imshow(img) cv2.setMouseCallback('image',printCoordinate) cv2.waitKey() cv2.destroyAllWindows()
原因分析
Colab运行在云端服务器,没有本地图形界面,OpenCV的cv2.namedWindow和cv2.setMouseCallback依赖本地窗口环境,直接调用会崩溃。cv2_imshow仅能显示静态图片,不支持交互操作。
解决方案
使用Colab支持的matplotlib和ipywidgets实现交互式绘图,这两个库支持浏览器端的交互操作。
修改后的代码
import numpy as np import cv2 import matplotlib.pyplot as plt from ipywidgets import widgets from IPython.display import display # 初始化画布和数据 img = np.zeros((800, 800, 3), dtype=np.uint8) all_points = [] current_start_point = None def handle_mouse_click(event): global current_start_point, img # 仅响应左键点击 if event.button != 1: return # 获取点击坐标(转为图像像素坐标) x, y = int(event.xdata), int(event.ydata) if x < 0 or x >= 800 or y <0 or y >=800: return # 绘制点和坐标文本 cv2.circle(img, (x, y), 3, (255, 255, 255), -1) coord_text = f'({x},{y})' cv2.putText(img, coord_text, (x+10, y-10), cv2.FONT_HERSHEY_PLAIN, 1, (255, 255, 255)) all_points.append((x, y)) # 处理线条绘制:第一次点击记起点,第二次点击画线条 if current_start_point is None: current_start_point = (x, y) else: cv2.line(img, current_start_point, (x, y), (0, 0, 255), 5) current_start_point = None # 更新画布显示 plt.clf() plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.axis('off') plt.draw() # 设置matplotlib交互式画布 plt.figure(figsize=(8, 8)) plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) plt.axis('off') # 绑定鼠标点击事件 canvas = plt.gcf().canvas canvas.mpl_connect('button_press_event', handle_mouse_click) plt.show() # 添加打印坐标的按钮 def print_all_points(b): print("所有点击的点坐标:") for idx, point in enumerate(all_points): print(f"点 {idx+1}: {point}") print_btn = widgets.Button(description="打印点坐标") print_btn.on_click(print_all_points) display(print_btn)
代码功能说明
- 左键点击画布绘制白色点,连续两次点击自动绘制红色线条
- 所有点击的点坐标都会被记录
- 点击"打印点坐标"按钮可输出所有点的坐标
- 画布尺寸保持和原代码一致的800x800像素
内容的提问来源于stack exchange,提问作者Momina
相关产品推荐
相关产品推荐

