如何使用 OpenCV 解决图像处理相机 IO 延迟
Posted
技术标签:
【中文标题】如何使用 OpenCV 解决图像处理相机 IO 延迟【英文标题】:How to solve image processing camera IO delay with OpenCV 【发布时间】: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 帧使用队列。我提到***.com/questions/30032063/… 认为grab
应该和read
一样工作,但事实并非如此。
在我的 Ubuntu 上,第二个测试也有效。但我不确定它是否可以在没有丢帧的情况下正常工作?第二 - cv::VideoCapture 不是线程安全类。
【参考方案1】:
在使用多目标跟踪的项目中,我使用了 2 个帧缓冲区(cv::Mat frames[2])和 2 个线程:
一个线程用于捕获下一帧并检测对象。
用于跟踪检测到的对象并在帧上绘制结果的第二个线程。
我使用 index = [0,1] 进行缓冲区交换,并且该索引受互斥体保护。使用 2 个条件变量来发出关于工作结束的信号。
首先使用帧 [capture_ind] 缓冲区使用 CatureAndDetect,然后使用之前的帧 [1-capture_ind] 缓冲区进行跟踪。下一步 - 切换缓冲区:capture_ind = 1 - capture_ind。
你可以在这里做这个项目吗:Multitarget-tracker。
【讨论】:
以上是关于如何使用 OpenCV 解决图像处理相机 IO 延迟的主要内容,如果未能解决你的问题,请参考以下文章
如何使用opencv将鱼眼相机拍摄的图像转换为平面(矩形)图像?
OpenCV - 如何在 Android 中设置全屏相机视图?