Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

cv2.createTrackbar pass userdata parameter into callback

I read the doc about cv2.createTrackbar. It said that

onChange – Pointer to the function to be called every time the slider changes position. This function should be prototyped as void Foo(int,void*); , where the first parameter is the trackbar position and the second parameter is the user data (see the next parameter). If the callback is the NULL pointer, no callbacks are called, but only value is updated.

But I don't know how to pass userdata into the onChange callback in Python.

I define my callback function:

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

I got the error:

callback() takes exactly 2 arguments (1 given)

Because it only passes the bar value parameter into the callback.
But I really need the cur_img for cv2.GaussianBlur function. How can I pass cur_img argument into the callback ?

like image 990
Haha TTpro Avatar asked Nov 18 '16 15:11

Haha TTpro


2 Answers

You can create a function closure using a lambda expression as the callback function. I had the same issue when wrapping up a player in a class, and wanted to use properties of my class instance. Snippet of a class method below.

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
like image 127
Graham Monkman Avatar answered Oct 10 '22 03:10

Graham Monkman


You can make a partial function using functools' partial function Python docs for partial and then the callback function will only take 1 arg. For example:

import cv2
from functools import partial

def callback(x, a, b=None, c=None):
  print(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'))

This is similar to using function closure but I feel it's simpler and neater.

like image 41
James Calo Avatar answered Oct 10 '22 03:10

James Calo