【发布时间】:2020-03-06 17:18:59
【问题描述】:
我这里有一个代码,它从在单独的线程中运行视频捕获操作的摄像机捕获视频流。代码可以编译,但是当我尝试运行它时,我收到以下错误。
我做了一些研究,发现这个问题与th.join(); 的缺失有关,但是当用户通过按下q 键中断进程时,我已经这样做了。在那之前,代码应该继续在创建的线程中运行。所以这告诉我应该在其他地方加入线程。
如果我通过用VideoCaptureAsync::update(); 替换thread th(&VideoCaptureAsync::update, this); 并删除th.join(); 来删除线程,错误就会消失,但这显然违背了这段代码的目的。
输出
内部启动函数
(进程:10748):GStreamer-CRITICAL **:gst_element_get_state: 断言“GST_IS_ELEMENT(元素)”失败
内部启动函数
内部更新函数
在没有活动异常的情况下终止调用
内部读取函数
中止(核心转储)
代码
/*
* Asynchronous_video_capture.cpp
*
* Copyright (C) 2019 C. S. G.
*
* MIT License
*/
#include <iostream> // for standard I/O
#include <string> // for strings
#include <opencv2/highgui.hpp>
#include <opencv2/core.hpp> // Basic OpenCV structures (cv::Mat)
#include <opencv2/videoio.hpp> // Video write
#include <opencv2/opencv.hpp>
#include <opencv2/core/utility.hpp>
#include <thread>
#include <tuple>
using namespace cv;
using namespace std;
void foo(bool &keep_run){
cout << "Inside the thread: Interrupt flag = " << keep_run << endl;
if (std::cin.get() == 'q') {
keep_run = false;
cout << "User Interrupted the process. Interrupt flag = " << keep_run << endl;
}
}
class VideoCaptureAsync
{
private:
VideoCapture cam;
thread th;
bool read_lock;
Mat frame;
Mat grabbed;
bool isStarted;
public:
void initiate(unsigned int camId, unsigned int width, unsigned int height, double fps);
void start(); // a start function to create and start the thread
void update(); // an update function that will be called asynchronously
tuple<Mat, Mat> read(); // a read function that we will call from our code to retrieve a new frame.
void stop(); // a stop function to stop (join) the thread
void exit(); // an __exit__ function to clean up some resources.
};
void VideoCaptureAsync::initiate(unsigned int camId, unsigned int width, unsigned int height, double fps){
cout << "Inside initiate function" << endl;
cam.open(camId);
if (!cam.isOpened())
{
cerr << "Could not open the VideoCapture camera: " << camId << endl;
}
cam.set(CV_CAP_PROP_FRAME_WIDTH, width);
cam.set(CV_CAP_PROP_FRAME_HEIGHT, height);
cam.set(CAP_PROP_FPS, fps);
isStarted = false;
read_lock = false;
VideoCaptureAsync::start();
}
void VideoCaptureAsync::start(){
cout << "Inside start function" << endl;
if (isStarted) {
cout << "Asynchroneous video capturing has already been started" << endl;
}
isStarted = true;
thread th(&VideoCaptureAsync::update, this);
//VideoCaptureAsync::update();
}
void VideoCaptureAsync::update(){
cout << "Inside update function" << endl;
while(isStarted){
Mat frame_update;
Mat grabbed_update;
tie(frame_update, grabbed_update) = VideoCaptureAsync::read();
if(!read_lock){
frame_update.copyTo(frame);
grabbed_update.copyTo(grabbed);
}
}
}
tuple<Mat, Mat> VideoCaptureAsync::read(){
cout << "Inside read function" << endl;
if (!read_lock){
read_lock = true;
Mat frame_read;
cam.read(frame_read);
Mat grabbed_read;
read_lock = false;
return make_tuple(frame_read, grabbed_read);
}
}
void VideoCaptureAsync::stop(){
cout << "Inside stop function" << endl;
th.join();
isStarted = false;
read_lock = true;
}
void VideoCaptureAsync::exit(){
cout << "Finished writing ..." << endl;
cam.release();
}
int main(int argc, char *argv[]){
const unsigned int camId = 1;
const bool enableOutput = true;
const unsigned int w = 1280;
const unsigned int h = 720;
double fps = 30.0;
VideoCaptureAsync obj;
obj.initiate(camId,w,h,fps);
bool keep_running = true;
thread th1(foo, std::ref(keep_running));
Mat original_frame;
while (keep_running) {
std::tie(std::ignore, original_frame) = obj.read();
if (enableOutput) {
imshow("Retrieved Image", original_frame);
waitKey(1000/fps);
}
}
obj.stop();
obj.exit();
}
【问题讨论】:
-
"没有 th.join(); 但是当用户按 q 键中断进程时我已经这样做了。" -- 如您所说,上述与
q键处理相关的代码的哪一部分在正在运行的线程上执行join()?显示的代码没有这样的事情。 -
@SamVarshavchik 确实如此。按 q 退出 main() 内的 while 循环,然后执行 VideoCaptureAsync::stop() ,其中包含 th.join() 。
-
该类的
th成员与实际执行线程main()中的th1对象有什么关系?th.join()对th1对象完全没有任何作用,这是您真正需要停止的对象。似乎没有任何由th启动的执行线程,因此调用它的join()看起来并没有加入任何东西。 -
@SamVarshavchik 好的,我在
obj.stop()之前也停止了th1,但这并没有解决问题。我确定问题出在th,而不是th1。
标签: c++ multithreading opencv oop c++17