我有一个像这样的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,但不是...
答案 0 :(得分:0)
通过线程进行IO操作来提高性能,而另一个线程进行CPU计算的想法是一种经典策略。除了SystemErr R java.net.SocketException: Connection reset
SystemErr R at java.net.SocketInputStream.read(SocketInputStream.java:220)
SystemErr R at java.net.SocketInputStream.read(SocketInputStream.java:152)
SystemErr R at com.ibm.jsse2.a.a(a.java:79)
SystemErr R at com.ibm.jsse2.a.a(a.java:182)
SystemErr R at com.ibm.jsse2.as.a(as.java:883)
SystemErr R at com.ibm.jsse2.as.i(as.java:969)
SystemErr R at com.ibm.jsse2.as.a(as.java:680)
SystemErr R at com.ibm.jsse2.as.startHandshake(as.java:859)
SystemErr R at com.ibm.ws.ssl.config.WSSocket.startHandshake(WSSocket.java:414)
SystemErr R at com.ibm.net.ssl.www2.protocol.https.c.afterConnect(c.java:16)
SystemErr R at com.ibm.net.ssl.www2.protocol.https.d.connect(d.java:44)
SystemErr R at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1561)
SystemErr R at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1489)
SystemErr R at com.ibm.net.ssl.www2.protocol.https.b.getInputStream(b.java:93)
SystemErr R at java.net.URL.openStream(URL.java:1057)
是CPU处理延迟之外,cv2.VideoCapture().read()
是一种阻塞操作,因此您的主程序可能会遇到I / O延迟,并且在等待新帧时必须停止任何处理。通过使用单独的专用线程,您的程序可以在 parallel 中运行,而不是依靠单个线程以顺序顺序抓取帧和处理帧。
您可以将IO线程中的所有帧存储到队列中,而处理线程只需读取并处理队列中的最新帧,而不会出现任何延迟问题。
答案 1 :(得分:0)
在具有多目标跟踪的项目中,我为帧(cv :: Mat帧[2])使用了2个缓冲区和2个线程:
一个用于捕获下一帧并检测对象的线程。
第二个线程,用于跟踪检测到的对象并在框架上绘制结果。
我使用index = [0,1]进行缓冲区交换,并且此索引受互斥锁保护。为了通知工作结束,使用了两个条件变量。
CatureAndDetect首先使用frame [capture_ind]缓冲区,而Tracking使用先前的frame [1-capture_ind]缓冲区。下一步-切换缓冲区:capture_ind = 1-capture_ind。
您可以在这里进行这个项目吗:Multitarget-tracker。