在boost::线程中安全地更新cv::capturevideo帧

updating cv::capturevideo frame in a boost::thread safely

本文关键字:更新 cv capturevideo 安全 boost 线程      更新时间:2023-10-16

我想通过opengl2camera同时渲染。我想尽快刷新每一帧。为了更新这些帧,我在无限循环中使用了一个线程。

我的实际问题是,我的程序崩溃,如果我把那些相机的分辨率高。用160:120就没有问题了。但是如果我设置了最大分辨率(1920:1080),那么在崩溃之前只需要更新5或6次图像。注意:在崩溃前更新的次数并不总是相同的

我认为,如果分辨率足够低,frame_L和frame_R被改变得足够快,主循环和线程之间不会发生冲突。

所以我认为我的互斥没有做它应该做的。我该怎么办?

(我不是线程和变量安全方面的专家)

我代码:

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

boost::mutex m; //for an other thread
boost::mutex n;
cv::VideoCapture capture_L(0);
cv::VideoCapture capture_R(1);
cv::Mat frame_L;
cv::Mat frame_R;
void MyThreadFunction()
{
    while (1)
    {
        {
          boost::mutex::scoped_lock lk(n);
          if (capture_L.grab()){
             capture_L.retrieve(frame_L);
             cv::transpose(frame_L, frame_L);
          }
          if (capture_R.grab()){
            capture_R.retrieve(frame_R);
            cv::transpose(frame_R, frame_R);
          }
        }
    }
}
int main()
{
  capture_L.set(CV_CAP_PROP_FRAME_WIDTH, 160);
  capture_L.set(CV_CAP_PROP_FRAME_HEIGHT, 120);
  capture_R.set(CV_CAP_PROP_FRAME_WIDTH, 160);
  capture_R.set(CV_CAP_PROP_FRAME_HEIGHT, 120);
  boost::thread thrd(&MyThreadFunction);
  while(1)
  {
       [  use  frame_L and frame_R  ]  
  }  
}

这是我用于线程相机抓取的代码。它是相机对象的一部分(例如;每个相机都有自己的对象和自己的捕捉线程。

void Camera::setCapture(cv::VideoCapture cap)
{
    pthread_mutex_lock(&latestFrameMutex);
    videoCapture = cap;
    videoCapture.read(latestFrame);
    pthread_mutex_unlock(&latestFrameMutex);
    int iret = pthread_create(&cameraGrabThread,NULL,&Camera::exec,this);
}
void *Camera::exec(void* thr)
{
   reinterpret_cast<Camera *> (thr)->grabFrame();
}

这确保在为该相机设置捕获时启动一个新线程。下面的代码由线程的exec部分运行,以实际获取帧。

void *Camera::grabFrame()
{
    while(videoCapture.isOpened())
    {
        pthread_mutex_lock(&latestFrameMutex);
        if(!videoCapture.read(latestFrame))
            std::cout << "Unable to read frame" << std::endl;
        pthread_mutex_unlock(&latestFrameMutex);
        usleep(8000); // Sleep 8ms
    }
}

最后,相机需要能够返回最新的帧;

cv::Mat Camera::getLatestFrame()
{
    while (getMilisecSinceLastCapture() < 35) //Enforce min time of 35 ms between frame requests.
    {
        usleep(5000);
    }
    pthread_mutex_lock(&latestFrameMutex);
    cv::Mat result = latestFrame.clone();
    pthread_mutex_unlock(&latestFrameMutex);
    return result.clone();
}

可以使用

来改变大小
void Camera::setImageSize(const cv::Size& size)
{    
    pthread_mutex_lock(&latestFrameMutex);
    videoCapture.set(CV_CAP_PROP_FRAME_HEIGHT, size.height);
    videoCapture.set(CV_CAP_PROP_FRAME_WIDTH, size.width);
    pthread_mutex_unlock(&latestFrameMutex);
}