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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 12:51:17