У меня есть код, который захватывает видеопоток с камеры, выполняющей операцию захвата видео, в отдельном потоке. Код компилируется, но когда я пытаюсь его запустить, я получаю следующую ошибку:
Я провел некоторое исследование и обнаружил, что эта проблема связана с отсутствием th.join();
, но я уже делаю это, когда пользовательпрерывает процесс нажатием клавиши q
. До тех пор код должен продолжать работать в созданном потоке. Так что это говорит мне о том, что я должен присоединиться к потоку где-то еще.
Если я удалю поток, заменив thread th(&VideoCaptureAsync::update, this);
на VideoCaptureAsync::update();
и удалив th.join();
, ошибка исчезнет, но это, очевидно, отрицательно скажется на целиэтот код.
Выход
Внутри функции инициализации
(процесс: 10748): GStreamer-CRITICAL **: gst_element_get_state: assertion 'GST_IS_ELEMENT (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();
}