【问题标题】:Cannot write to OpenCV frame captured by a different thread无法写入由不同线程捕获的 OpenCV 帧
【发布时间】:2022-01-09 00:57:35
【问题描述】:

通过使用以下代码,我可以成功地从单独的线程捕获帧并将其返回给 main()。但现在我无法写入 frame/cv::Mat(main() 中的轮廓)进行显示。如果我不为网络摄像头使用单独的线程,那么我可以成功写入 frame/cv::Mat。我做错了什么?

VideoCapture cap(0);    
class Camera 
{
    public:
        Camera(void);
        ~Camera(void);
        Mat captureVideo(void);
        
    private:
        Mat frame;
        double dWidth;
        double dHeight;
        double fps;
            
};
Camera::Camera(void) {
    int isrunning = 0;
    usleep(10);
    if (!cap.open(2))
    {
        cout << "Cannot open the video camera.\n" << endl;
    }
    else 
    {
        isrunning = 1;
    }
    if(isrunning == 0) {
        this->~Camera();
    }  

    cap >> frame;        
}
Camera::~Camera(void)  {
    cap.release();  
}
Mat Camera::captureVideo(void) {
    cap >> frame;           
    return frame;
}

Camera cam1;
const int frameBuffer = 20; // Frame buffer
std::vector<cv::Mat> frameStack;    
int stopSig = 0; // Global stop signal...

void grabFrame(void) {
    Mat frame;
    
    ::frameStack.clear();

    while(!::stopSig) {
        frame = ::cam1.captureVideo();
        
        // 1. Remove one frame from the back, if the stack has more then 2 frames...
        if(::frameStack.size() > 2) {       //If the framestack has more then 2 frames...
            ::frameStack.pop_back();
        } 

        // 2. Add a frame at the front of the stack if the stack is not full...
        if (::frameStack.size() < ::frameBuffer) { 
            ::frameStack.push_back(frame);  // Put new frame on stack on the computer's RAM...
        } else {
            ::frameStack.clear();
        }
        
    }
    return;
}

int main(int argc, char* argv[])
{
    Mat fr, outImg;                 // Captured single frames...
    Mat contour;                // Video stream showin countours of objects...

    ::frameStack.clear();
    thread t1(grabFrame);

    cv::namedWindow("MyWindow", 1);
    
    while(1) {
        if(::frameStack.size() >= 2)  {
            contour = ::frameStack.back();

            circle(contour, Point(150,150),50, Scalar(0,255,255),cv::FILLED, 8);// PROBLEM -> NO EFFECT
            putText(contour, "some text", Point(100,100), FONT_HERSHEY_DUPLEX, 1, Scalar(0,143,143), 2);// PROBLEM -> NO EFFECT

            imshow("Contour Video", contour);
        }
        
        if (waitKey(1) == 27) 
        {
            ::stopSig = 1;      // Signal to threads to end their run...
            frameStack.clear();
            break; 
        }
    }
    t1.join();

    return 0;
}

【问题讨论】:

    标签: c++ opencv


    【解决方案1】:

    在您的示例中,您在两个线程之间共享stopSigframeStackframeBuffer 变量。

    当您在线程之间使用共享内存时,您必须正确同步对该共享内存的访问。需要同步的原因之一是防止两个线程同时修改一个变量。另一个原因是可见性 - 一个线程对变量的写入可以缓存在 CPU 缓存中,而在另一个 CPU 内核上运行的线程不会看到变量的变化。

    也许在线程之间同步内存访问的最简单方法是使用std::mutex。我不会在这里发布整个代码,但是您可以在线阅读 C++ 中的互斥锁,例如,here

    【讨论】:

      猜你喜欢
      • 2021-03-30
      • 1970-01-01
      • 1970-01-01
      • 2011-06-29
      • 1970-01-01
      • 1970-01-01
      • 2016-06-27
      • 1970-01-01
      • 2018-01-04
      相关资源
      最近更新 更多