已定义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
相关产品推荐
相关产品推荐

