python - 如何使用回调函数避免全局变量
问题描述
我想将label_image()
代码放入一个用图像初始化的函数中,即label_image(image)
. 现在,如果我不将图像声明为全局变量,它不会正确更新,因为回调函数具有image
全局label_image(image)
而不是image
. 此外,尽管在click()
内部初始化了回调函数,但除非全局声明,否则它label_image()
无法看到变量。image
我想我的问题会很容易解决,如果我可以传递image
给click()
which 然后将能够更新label_image(image)
收到的相同副本。到目前为止,我还没有找到这样做,因为回调函数需要 5 个参数event, x, y, flags, param
......
def click(event, x, y, flags, param):
global click_pts, image_storage, image
if event == cv2.EVENT_LBUTTONDOWN:
click_pts.append((x, y, 1))
cv2.circle(image, (x, y), 5, (255, 0, 0), -1)
image_storage = lshift(image_storage, image)
cv2.imshow("image", image_storage[-1])
print('added %(n)s, size %(s)s, type %(t)s' % {'n': (x, y), 's': len(click_pts), 't': 1})
elif event == cv2.EVENT_RBUTTONDOWN:
click_pts.append((x, y, 2))
cv2.circle(image, (x, y), 5, (0, 255, 255), -1)
image_storage = lshift(image_storage, image)
cv2.imshow("image", image_storage[-1])
print('added %(n)s, size %(s)s, type %(t)s' % {'n': (x, y), 's': len(click_pts), 't': 2})
def label_image() -> list:
global click_pts, image_storage, image
click_pts = []
image_storage = np.zeros((10,) + image.shape, np.uint8)
image_storage[:] = np.ndarray.copy(image)
cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.resizeWindow('image', 1400, 1400)
cv2.setMouseCallback("image", click)
# Loop until 'q' is pressed
while True:
cv2.imshow("image", image_storage[-1])
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
elif key == ord('b'):
try:
print('removed: %(n)s, size %(s)s' % {'n': click_pts[-1], 's': len(click_pts)})
click_pts.pop()
except IndexError:
print('the array is empty')
image_storage = rshift(image_storage)
image = np.ndarray.copy(image_storage[-1])
cv2.imshow("image", image_storage[-1])
cv2.destroyAllWindows()
return click_pts
image = cv2.imread('someimage.png')
label_image()
解决方案
鉴于你想最终调用这个:
def click(image, event, x, y, flags, param):
因此我们image
作为第一个参数传入,我们可以创建一个前面已经partial
有参数的函数,让回调代码像往常一样应用普通参数。image
event, x, y, flags, param
这意味着partial
为回调做一个:
def label_image():
# all the usual stuff elided ...
partial_click = partial(click, image) # here image is applied first
cv2.setMouseCallback("image", partial_click)
推荐阅读
- python - 那么不能使用 weasyprint 怎么办呢?
- node.js - 想在 $match 函数中使用 $lookup 数据
- node.js - 如何在共享主机上启动 Laravel 应用程序(Bluehost)
- android - 将视频下载到内部存储
- c# - 嵌套子 REST 控制器,ASP.NET .net5
- swift - 如何切换 int 变量的值
- ms-word - PhpWord:加载模板并保存为 Word Doc 删除表格/单元格边框
- regex - 语言参数的 Nginx URL 重写
- c# - 使用 C# 在日期范围 MongoDB 之间过滤数据
- html - 努力理解 css 格式