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

已定义on_mouse函数仍报NameError,如何正确调用该函数?

解决cv2.setMouseCallback调用时的NameError问题

问题场景

调用cv2.setMouseCallback('img', on_mouse)时触发报错:NameError: name 'on_mouse' is not defined,相关代码及报错信息如下:

代码片段

def on_mouse(event,x,y,flags,params):
    global img,point1,point2
    img2 =img.copy()
    if event == cv2.EVENT_LBUTTONDOWN:
        point1 = (x,y)
        cv2.circle(img2,point1,10,(0,255,0),5)
        cv2.imshow('image',img2)
    elif event == cv2.EVENT_MOUSEMOVE and (flags & cv2.EVENT_FLAG_LBUTTON):
        cv2.rectangle(img2,point1,(x,y),(255,0,0),5)
        cv2.imshow('image',img2)
    elif event == cv2.EVENT_LBUTTONUP:
        point2 = (x,y)
        cv2.rectangle(img2,point1,point2,(0,0,255),5)
        cv2.imshow('image',img2)
        min_x = min(point1[0],point2[0])
        min_y = min(point1[1],point2[1])
        width = abs(point1[0]-point2[0])
        height = abs(point1[1]-point2[1])
        cut_img = img[min_y:min_y+height,min_x:min_x+width]
        cv2.imwrite('new.jpg',cut_img)

def take_image(self):
    Clock.unschedule(self.update)
    file_path = self.camera.capture(gp.GP_CAPTURE_IMAGE)
    camera_file = self.camera.file_get(file_path.folder, file_path.name, gp.GP_FILE_TYPE_NORMAL)
    ...
    cv2.imwrite(capture_path,image)
    cv2.namedWindow('img')
    cv2.setMouseCallback('img',on_mouse)
    cv2.imshow('img',image)
    cv2.waitKey(0)

报错详情

Exception in thread Thread-2:
Trackback (most recent call last):
    File"/usr/lib/python3.9/threading.py" line 954, in _bootstrap_inner self.run()
    File"/usr/lib/python3.9/threading.py" line 892, in run self._target(*self._args, **self._kwargs)
    File "/home/user002/app.py", line 220, in capture App.camera.take_image()
    File "/home/user002/cameraControll.py", line 189, in take_image cv2.setMouseCallback('img', on_mouse)
    NameError:name 'on_mouse' is not defined

解决方案

核心原因是on_mouse函数不在take_image方法的可访问作用域内,结合代码中take_image带有self参数(说明是类的成员方法),给出两种可行修复方式:

  • 方式一:将on_mouse改为类的静态方法
    把on_mouse移到类内部,用@staticmethod装饰,调用时指定类名或self来引用:

    class CameraController:
        @staticmethod
        def on_mouse(event,x,y,flags,params):
            global img,point1,point2
            img2 = img.copy()
            # 原函数逻辑保持不变...
    
        def take_image(self):
            # 原代码逻辑...
            cv2.setMouseCallback('img', CameraController.on_mouse)
            # 后续代码...
    
  • 方式二:确保on_mouse在全局作用域可访问
    如果on_mouse定义在其他模块,需要在cameraControll.py中导入该函数;如果在同一模块,确认on_mouse定义在take_image方法所在类的外部,且没有被同名局部变量覆盖。

另外,额外建议:避免使用global变量传递img,可以利用cv2.setMouseCallback的param参数传递数据,减少全局变量依赖:

def on_mouse(event,x,y,flags,params):
    img = params['img']
    point1 = params['point1']
    point2 = params['point2']
    img2 = img.copy()
    # 原函数逻辑...
    # 当需要修改point1/point2时,直接修改params内的引用

def take_image(self):
    # 原代码...
    # 准备参数字典
    callback_params = {'img': image, 'point1': None, 'point2': None}
    cv2.setMouseCallback('img', on_mouse, param=callback_params)
    # 后续代码...

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 01:05:05