Я использую библиотеки Boost в C ++ для достижения многопоточной очереди ввода-вывода для кадров видеофайлов в OpenCV
У меня возникла проблема, потому что поток Push работает хорошо, но когда все видеокадры прочитаны, функция-потребитель, которая выдает очередь, всегда возвращает один и тот же кадр, и я не уверен, почему.
Вот класс очереди:
#include "videoqueue.h"
VideoQueue::VideoQueue()
{
std::cout << "Class initialized" << std::endl;
}
void VideoQueue::InitReader(std::string filename)
{
VideoQueue::cap = cv::VideoCapture(filename);
if(!cap.isOpened())
{
std::cout << "Error opening video file" << std::endl;
}
else
{
std::cout << "File opened: " << cap.get(cv::CAP_PROP_FRAME_COUNT) << " frames" << std::endl;
framesAcquired = 0;
framesAvailable = 0;
}
}
void VideoQueue::start()
{
while(framesAcquired < cap.get(cv::CAP_PROP_FRAME_COUNT))
{
//frame read from file
cap.read(captureFrame);
//safe push
boost::mutex::scoped_lock lock(queueMutex);
bool const was_empty = queueFrame.empty();
queueFrame.push(captureFrame);
//frames amount updated
framesAcquired++;
std::cout << "Frames acquired " << framesAcquired << std::endl;
framesAvailable = queueFrame.size();
//mutex unlock
lock.unlock();
if(was_empty)
queueCondition.notify_one();
}
}
bool VideoQueue::queueEmpty() const
{
boost::mutex::scoped_lock lock(queueMutex);
return queueFrame.empty();
}
int VideoQueue::framesQueued()
{
boost::mutex::scoped_lock lock(queueMutex);
return queueFrame.size();
}
void VideoQueue::readFrame(cv::Mat &output)
{
boost::mutex::scoped_lock lock(queueMutex);
std::cout << "mutex lettura bloccato" << std::endl;
while(queueFrame.empty())
{
std::cout << "aspetto" << std::endl;
queueCondition.wait(lock);
}
output = queueFrame.front();
queueFrame.pop();
std::cout << "front pop eseguito" << std::endl;
//framesAvailable = queueFrame.size();
framesConsumed++;
//mutex unlock
//lock.unlock();
//queueCondition.notify_one();
std::cout << "Frames consumed: " << framesConsumed << std::endl;
}
с его заголовком
#ifndef VIDEOQUEUE_H
#define VIDEOQUEUE_H
#include <opencv2/opencv.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/core/core.hpp>
#include <boost/thread.hpp>
#include <string>
#include <iostream>
#include <queue>
class VideoQueue
{
public:
VideoQueue();
void InitReader(std::string filename);
void start();
bool queueEmpty() const;
int framesQueued();
void readFrame(cv::Mat& output);
private:
//std::queue<Mat> frameQueue;
cv::VideoCapture cap;
int framesAcquired;
int framesAvailable;
int framesConsumed;
cv::Mat captureFrame;
cv::Mat outputFrame;
//concurrent queue
std::queue<cv::Mat> queueFrame;
mutable boost::mutex queueMutex;
boost::condition_variable queueCondition;
};
#endif // VIDEOQUEUE_H
и тестовая программа с инициализацией потока
#include <iostream>
#include <string>
#include <opencv2/highgui/highgui.hpp>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/chrono.hpp>
#include "videoqueue.h"
void wait(int milliseconds)
{
boost::this_thread::sleep_for(boost::chrono::milliseconds(milliseconds));
}
int main()
{
VideoQueue prova;
cv::Mat frame;
prova.InitReader("/home/exeless/DEV/C++/1_10_rest.avi");
boost::thread t(&VideoQueue::start, &prova);
wait(500);
while(prova.framesQueued()>0)
{
wait(100);
prova.readFrame(frame);
std::cout << "frames " << prova.framesQueued() << std::endl;
std::cout << "value " << cv::mean(frame) << std::endl;
imshow("output",frame);
cv::waitKey(10);
}
t.join();
return 0;
}
Я думаю, что проблема заключается в планировании потоков, но я не уверен, где. Любая помощь будет отличной.
Задача ещё не решена.
Других решений пока нет …