【发布时间】:2019-03-21 04:14:05
【问题描述】:
我有一个这样工作的 OpenCV 程序:
VideoCapture cap(0);
Mat frame;
while(true) {
cap >> frame;
myprocess(frame);
}
问题是如果myprocess的时间长于相机的IO时间间隔,那么抓拍的帧就会延迟,无法得到与实时同步的帧。
所以,我认为要解决这个问题,应该让相机流和myprocess 并行运行。一个线程做 IO 操作,另一个做 CPU 计算。当相机完成捕获后,发送到工作线程进行处理。
这个想法对吗?有什么更好的策略来解决这个问题?
演示:
int main(int argc, char *argv[])
{
cv::Mat buffer;
cv::VideoCapture cap;
std::mutex mutex;
cap.open(0);
std::thread product([](cv::Mat& buffer, cv::VideoCapture cap, std::mutex& mutex){
while (true) { // keep product the new image
cv::Mat tmp;
cap >> tmp;
mutex.lock();
buffer = tmp.clone(); // copy the value
mutex.unlock();
}
}, std::ref(buffer), cap, std::ref(mutex));
product.detach();
while (cv::waitKey(20)) { // process in the main thread
mutex.lock();
cv::Mat tmp = buffer.clone(); // copy the value
mutex.unlock();
if(!tmp.data)
std::cout<<"null"<<std::endl;
else {
std::cout<<"not null"<<std::endl;
cv::imshow("test", tmp);
}
}
return 0;
}
或者使用线程不断清除缓冲区。
int main(int argc, char *argv[])
{
cv::Mat buffer;
cv::VideoCapture cap;
std::mutex mutex;
cap.open(0);
std::thread product([](cv::Mat& buffer, cv::VideoCapture cap, std::mutex& mutex){
while (true) { // keep product the new image
cap.grab();
}
}, std::ref(buffer), cap, std::ref(mutex));
product.detach();
int i;
while (true) { // process in the main thread
cv::Mat tmp;
cap.retrieve(tmp);
if(!tmp.data)
std::cout<<"null"<<i++<<std::endl;
else {
cv::imshow("test", tmp);
}
if(cv::waitKey(30) >= 0) break;
}
return 0;
}
我认为第二个演示应该是基于https://docs.opencv.org/3.0-beta/modules/videoio/doc/reading_and_writing_video.html#videocapture-grab,但它不是......
【问题讨论】:
-
是的,想法是对的。
-
@Nuzhny 我添加了两个演示代码,请你看看哪个是正确的。
-
我不确定这种方法是否可行。它需要为N帧设置捕获顺序并处理N-1帧。
-
@Nuzhny 我测试了两者,第一个工作,但第二个没有。我只需要最新的,所以没有为 N 帧使用队列。我提到stackoverflow.com/questions/30032063/… 认为
grab应该和read一样工作,但事实并非如此。 -
在我的 Ubuntu 上,第二个测试也有效。但我不确定它是否可以在没有丢帧的情况下正常工作?第二 - cv::VideoCapture 不是线程安全类。
标签: c++ opencv parallel-processing camera