【问题标题】:cv2.createTrackbar pass userdata parameter into callbackcv2.createTrackbar 将 userdata 参数传递给回调
【发布时间】:2016-11-18 15:31:53
【问题描述】:

我阅读了有关cv2.createTrackbar 的文档。它说

onChange – 指向每次滑动时调用的函数的指针 改变位置。这个函数的原型应该是 void Foo(int,void*); ,其中第一个参数是轨迹栏位置 第二个参数是用户数据(见下一个参数)。如果 回调是 NULL 指针,没有回调被调用,但只有 值已更新。

但我不知道如何将用户数据传递给 Python 中的 onChange 回调。

我定义了我的回调函数:

def callback(value,cur_img):
    cv2.GaussianBlur(cur_img, (5, 5), value)

我得到了错误:

callback() takes exactly 2 arguments (1 given)

因为它只将 bar 值参数传递给回调。
但我真的需要 cur_img 用于 cv2.GaussianBlur 函数。如何将 cur_img 参数传递给回调?

【问题讨论】:

  • 你不能在输入上声明 cur_img(在调用回调之前)并将其作为全局变量在回调中获取吗?
  • 似乎在Python中我们不能使用C++可用的参数userdata,链接页面中提供的Python语法实际上并没有提及。

标签: python python-2.7 opencv callback


【解决方案1】:

您可以使用 functools 的部分函数Python docs for partial 创建一个部分函数,​​然后回调函数只需要 1 个参数。例如:

导入简历2 从 functools 导入部分 def 回调(x,a,b=None,c=None): 打印(x,a,b,c) def addTracks(window_name): cv2.createTrackbar(bar1_name, window_name, 0, 255, partial(callback, a='R', b='G', c='B')) cv2.createTrackbar(bar2_name, window_name, 0, 255, partial(callback, a='R'))

这类似于使用函数闭包,但我觉得它更简单整洁。

【讨论】:

  • 像我这种心不在焉的人,部分调用和函数定义中的参数名一定要一致。
【解决方案2】:

您可以使用 lambda 表达式作为回调函数来创建函数闭包。在将玩家包装在一个类中时,我遇到了同样的问题,并且想使用我的类实例的属性。下面是一个类方法的片段。

def play(self):
     ... other code...
     cv2.namedWindow('main', cv2.WINDOW_NORMAL)
     cv2.createTrackbar('trackbar', 'main', 0,
         100,
         lambda x: self.callback(x, self)
         )
     ... other code...

def callback(tb_pos, self):
    #tb_pos receives the trackbar position value
    #self receives my class instance, but could be
    #whatever you want

【讨论】:

  • 绝妙的解决方案!请注意,只有 lambda 函数可以工作。它不能被实例方法替换,因为实例方法需要一个'self'参数。它也不能是类外的静态函数,因为您还需要“自我”类范围。因此 lambda 函数使用第一个 self 保留实例范围,同时使用第二个 self 将实例作为变量柯里化。
猜你喜欢
  • 2016-12-09
  • 2018-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多