Ask Your Question
-1

Capture problem in thread

asked 2017-01-09 11:23:25 -0600

Harber gravatar image

updated 2017-01-09 11:49:17 -0600

Hi.

I'm try to capture a frame from webcam with parallel work in another thread.

When I capture a frame without another thread, capture function works at 50~60fps.

But, work with another thread even just while loop, capture function work at 20~30fps.

Below is a code.


using namespace std;    
using namespace cv;    

int k = 0;

IplImage* image = 0;    
CvCapture* capture = cvCaptureFromCAM(0);

int Thrr()    
{           
    while (!k)    
    {
        ;    
    }    
}


int main(int argc, char** argv)    
{

    cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, 1280);
    cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, 720);

    thread th1(Thrr);

    while (1)
    {

        for (int i = 0; i < 300; i++)
        {
            clock_t aaa = clock();
            cvGrabFrame(capture);
            clock_t ss = clock();
            image = cvRetrieveFrame(capture);
            printf("%d ", i);
            printf("a12 frame : %f\n", double(CLOCKS_PER_SEC) / double(clock() - aaa));

        }
        k = 1;
    }


    return 0;

}

image description

Like above image you can see, when it capture a frame with another thread in first for loop, it works at 25fps.

But after first for loop, Thrr() thread end(k = 1, it means Thrr() while(!k) loop end), capture function works at 55fps.

Didn't any of you know why it is and how can I do for this problem.

Thanks.

edit retag flag offensive close merge delete

Comments

1

please avoid using opencv's deprecated, no more maintained c-api.

berak gravatar imageberak ( 2017-01-09 11:31:54 -0600 )edit

Thanks for reply. But it is same problem even if I use a VideoCapture class. Do you know why is it?

Harber gravatar imageHarber ( 2017-01-09 11:56:28 -0600 )edit

please also note, that opencv is not threadsafe by design.

do you have more than one core ? if not, you're just "stealing" cpu-ticks from the main thread this way. (which would pretty much explain, what you're seeing)

berak gravatar imageberak ( 2017-01-09 11:58:57 -0600 )edit

again, sorry for the downvote, but your code is a bad example, and might mislead other noobs seing this.

berak gravatar imageberak ( 2017-01-09 12:02:20 -0600 )edit

Yeah. My system has Octa-core(exynos 5422 / octa-core) cpu. So I can't understand this problem. Also I got it understand your mind. never mind. Thanks.

Harber gravatar imageHarber ( 2017-01-09 12:05:13 -0600 )edit

also, clock() measures CPU ticks, while retrieving frames from an usb webcam is mostly an IO problem (apart from the decoding)

berak gravatar imageberak ( 2017-01-09 12:14:44 -0600 )edit

1 avoid using opencv's deprecated IplImage and CvCapture

2 are you sure your webcam works 1280x720@60fps ?

3 You have to measure Grab and Retrieve

pklab gravatar imagepklab ( 2017-01-12 13:20:11 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
2

answered 2017-01-09 18:00:41 -0600

Eduardo gravatar image

updated 2017-01-09 18:16:46 -0600

Assuming a simple parallel scheme as in your question, in my opinion you should not observe such a framerate drop on a modern CPU.

I see multiple flaws in your code:

  • usage of deprecated C API as pointed by berak
  • a mutex is missing even if in this simple code it should not matter
  • you should not time the grabbing but rather the whole acquisition as the camera acquisition should be done in background and each new frame should be stored in a buffer (if I am not wrong)

With the following code, I observe the same framerate with or whitout a parallel thread launched:

#include <iostream>
#include <thread>
#include <mutex>
#include <opencv2/opencv.hpp>

using namespace std;
using namespace cv;

mutex quit_mutex;
bool quit = false;

void thread_callback() {
  while (true) {
    lock_guard<mutex> lock(quit_mutex);
    if (quit)
      break;
  }
}


int main(int argc, char *argv[]) {
  VideoCapture capture(0);
  capture.set(CAP_PROP_FRAME_WIDTH, 1280);
  capture.set(CAP_PROP_FRAME_HEIGHT, 720);

  if (!capture.isOpened()) {
    cerr << "Cannot open camera!" << endl;
    return 0;
  }

  thread th;
  bool launch_thread = argc > 1 && atoi(argv[1]);
  if (launch_thread) {
    th = thread(thread_callback);
  }

  Mat frame;
  double t = (double) getTickCount();
  int iterations = 0;
  while (true) {
    capture >> frame;
    imshow("Camera", frame);

    int c = waitKey(30) & 0xFF; // & 0xFF should be useless with OpenCV >= 3.2
    iterations++;
    if (c == 27)
      break;
  }
  t = ((double) getTickCount() - t) / getTickFrequency();
  cout << "Mean capture time: " << iterations / t << " FPS on " << iterations << " iterations" << endl;

  if (launch_thread) {
    //Set quit to true
    unique_lock<mutex> lock(quit_mutex);
    quit = true;
    lock.unlock();
    th.join();
  }

  return 0;
}

To enable the thread launching, you have to pass as argument 1 to the executable.

Some additional links related to the subject:

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2017-01-09 11:23:25 -0600

Seen: 453 times

Last updated: Jan 09 '17