4

I have recently started working on OpenCV using c++. I am having a problem with the following code.

#include "cv.h"
#include "highgui.h"
int g_slider_position = 0;
CvCapture* g_capture = NULL;

void onTrackbarSlide(int pos) {
  cvSetCaptureProperty(
    g_capture,
    CV_CAP_PROP_POS_FRAMES,
    pos
  );
}

int main( int argc, char** argv ) {
  cvNamedWindow( "Example3", CV_WINDOW_AUTOSIZE );
  g_capture = cvCreateFileCapture( "Aawaarapan.avi" );
  int frames = (int) cvGetCaptureProperty(
    g_capture,
    CV_CAP_PROP_FRAME_COUNT
  );
  if( frames!= 0 ) {
    cvCreateTrackbar(
      "Position",
      "Example3",
      &g_slider_position,
      frames,
      onTrackbarSlide //need to be call as onTrackbarSlide(g_slider_position) but gives error:invalid use of void expression 
    );
  }

  IplImage* frame;
  while(1) {
    frame = cvQueryFrame( g_capture );
    if( !frame ) break;

    cvShowImage( "Example3", frame );
    cvCreateTrackbar(
      "Position",
      "Example3",
      &g_slider_position,
      frames,
      onTrackbarSlide
    );

    char c = cvWaitKey(33);
    if( c == 27 ) break;

    ++g_slider_position;
  }

  cvReleaseCapture( &g_capture );
  cvDestroyWindow( "Example3" );
  return(0);
}

here the call to the function cvCreateTrackbar takes as argument, the function

void onTrackbarSlide(int pos)

but when I call the function like this cvCreateTrackbar( "Position", "Example3", &g_slider_position, frames, onTrackbarSlide(g_slider_position) );`

it is reporting an error error: invalid use of void expression

Actually i need to pass the g_slider_position to the function so that the slider's position is known.

A friend of mine told me to call the function as

cvCreateTrackbar(
  "Position",
  "Example3",
  &g_slider_position,
  frames,
  onTrackbarSlide
);

this doesn't report any error but it doesn't do what it is supposed to.the slider's position is necessary.

So, my question is how do I call the cvCreateTracker with argument onTrackerSlide(with its integer argument). I hope I was not confusing.

Thank you!

Jav_Rock
  • 22,059
  • 20
  • 123
  • 164
Ashish Yadav
  • 1,667
  • 6
  • 20
  • 26
  • 1
    Please tell me that you don't format all your code like that! I hope that it was just a copy-paste error. – Mark Byers Oct 12 '10 at 18:29
  • Definitely confusing. If you're trying to pass g_slider_position, what are you doing with onTrackbarSlide()? – Jay Oct 12 '10 at 18:30
  • @Mark: Reindented (pfiuu) @CadetNumber1: you should make an effort when posting, unreadable questions are unlikely to get answers... – Matthieu M. Oct 12 '10 at 18:31
  • @jay G_slider_position is supposed to be passed to onTrackbarSlide which in turn is suppoesed to be passed to cvTrackbar – Ashish Yadav Oct 12 '10 at 18:38
  • @CadetNumber1: you should brush up on pointers to functions and callbacks in C... – Eugen Constantin Dinca Oct 12 '10 at 18:42
  • @eugen please provide any good link for the same... – Ashish Yadav Oct 12 '10 at 18:45
  • @CadetNumber1: "doesn't do what it is supposed to do" is the same as "doesn't work". That doesn't say anything. It doesn't say what behavior you're expecting, or what it does that it shouldn't do, or what it doesn't do that it should. In some cases one see some obvious error in the code. In this case, one would need to be a telepath to deduce what the "doesn't work" means. – Cheers and hth. - Alf Oct 12 '10 at 18:49
  • @alf actually that piece of code is supposed to modify the global variable g_slider_position. – Ashish Yadav Oct 12 '10 at 18:53
  • You could have a look here: http://www.aishack.in/2010/02/highgui-creating-interfaces/ – Utkarsh Sinha Oct 13 '10 at 03:36

2 Answers2

3

g_slider_position is accessible to your function -- you can't pass it. You should use the code you have (from your friend), but the int passed is the id of the trackbar.

Should be this:

void onTrackbarSlide(int id) {
  cvSetCaptureProperty(
    g_capture,
    CV_CAP_PROP_POS_FRAMES,
    g_slider_position
  );
}
Lou Franco
  • 87,846
  • 14
  • 132
  • 192
  • how could that be? In the code you show, it's declared right above the function. If you moved it to another cpp, then you need to extern declare it with `extern int g_slider_position;` – Lou Franco Oct 12 '10 at 19:57
  • id is the id of the slider -- this is so you can share the same callback in multiple sliders. – Lou Franco Oct 12 '10 at 19:58
1

This is an issue of C function pointer usage, which I'm assuming you've never used.

At the point of creating the trackbar, you should indeed use:

cvCreateTrackbar(
  "Position",
  "Example3",
  &g_slider_position,
  frames,
  onTrackbarSlide
);

When you make that call, you are telling OpenCV two pieces of information:

  1. the address of g_slider_position
  2. the address of onTrackbarSlide

Now, when that trackbar is moved, OpenCV will:

  1. modify g_slider_position directly (so you don't actually even need to receive it as a function parameter, but anyway)
  2. call onTrackbarSlide(g_slider_position), which it can do because it knows both pieces of information

If you write the code the way you were trying to:

cvCreateTrackbar(
  "Position",
  "Example3",
  &g_slider_position,
  frames,
  onTrackbarSlide(g_slider_position)
);

Where you wrote onTrackbarSlide(g_slider_position), that turned into a function invocation of onTrackbarSlide. In other words, while trying to figure out what values you wanted to pass to cvCreateTrackbar, it called onTrackbarSlide and passed it the current value of g_slider_position, and hoped that onTrackbarSlide would return a function pointer, because that's what it needed. OK, it never got that far, because it could tell at compile time that onTrackbarSlide returned void, and that void was not void(*aCallbackFunction)(int) (which is how you specify the type "a function that takes an int and returns nothing"), but I'm using narrative style...

As for the id vs position argument, I can't speak from experience. The docs I just read from willowgarage state that your callback receives the position, not the id, which means you have no way to use a single callback to differentiate between sliders. I personally wouldn't want to do that anyway, 'coz it means I'd have one function with a switch instead of multiple functions. Multiple functions will be (microscopically) more efficient, and definitely more readable.

On the other hand, cvCreateTrackbar does return an int, which might be the id of that trackbar. Not sure what you're supposed to do with it, though. The actual meaning of the return value was not defined on the doc page I just read. Given that this is a C API and lacks a bool type, that int might just be a true/false return...