C++ 使用OpenCV、Boost线程和多摄像头
我正在尝试编写一个程序,能够在两个不同的线程中从两个不同的相机捕获图像。我想这样做是因为当我在同一个线程中执行此操作时,我必须持续等待cvQueryFrame两倍的时间,因此我无法以30 fps的速度抓取图像(我从每个摄像头获得15 fps) 我已经看了这篇文章,但这只适用于一台相机 我当前的程序会给出不同的结果,有时会导致内存泄漏,通常我看不到任何事情发生,有时会运行几秒钟,但图像会再次冻结。奇怪的是,早些时候,当我没有调用cvShowImage,但让我的imageProcessing函数做了一些有用的事情时,我可以看到我从两个摄像头获得了实时结果。我想这意味着这是可能的,但我在某处犯了一个愚蠢的错误。我的操作系统是LINUX,我使用的是OpenCV 2.4 我的代码:C++ 使用OpenCV、Boost线程和多摄像头,c++,linux,boost,opencv,C++,Linux,Boost,Opencv,我正在尝试编写一个程序,能够在两个不同的线程中从两个不同的相机捕获图像。我想这样做是因为当我在同一个线程中执行此操作时,我必须持续等待cvQueryFrame两倍的时间,因此我无法以30 fps的速度抓取图像(我从每个摄像头获得15 fps) 我已经看了这篇文章,但这只适用于一台相机 我当前的程序会给出不同的结果,有时会导致内存泄漏,通常我看不到任何事情发生,有时会运行几秒钟,但图像会再次冻结。奇怪的是,早些时候,当我没有调用cvShowImage,但让我的imageProcessing函数做了
#include <iostream>
#include <cstdio>
#include <cv.h>
#include <ml.h>
#include <cvaux.h>
#include <highgui.h>
#include <vector>
#include <stdio.h>
#include "producer_consumer_queue.hpp"
//Camera settings
int cameraWidth = 1280;
int cameraHeight = 720;
int waitKeyValue = 5;
bool threads_should_exit = false;
CvCapture * capture;
CvCapture * capture2;
using namespace std;
using namespace cv;
void grabFrame(concurrent_queue<IplImage* > * frame_queue, int camNumber) {
try {
//Load first frames
cout << "grabFrame: " << camNumber << " init with " << cameraWidth << " x " << cameraHeight << endl;
IplImage* frame;
if (camNumber == 0)frame = cvQueryFrame(capture);
if (camNumber == 1)frame = cvQueryFrame(capture2);
while (frame && !threads_should_exit) {
if (camNumber == 0)frame = cvQueryFrame(capture);
if (camNumber == 1)frame = cvQueryFrame(capture2);
IplImage* frame_copy = NULL;
frame_copy = cvCloneImage(frame);
if (camNumber == 0)cvShowImage("NE", frame);
cout << "grabFrame: " << camNumber << " pushing back to queue" << endl;
frame_queue->push(frame_copy);
int k = cvWaitKey(waitKeyValue);
if (k == 1048603 || k == 27 || k == '\r') {
cout << "grabFrame: Process killed" << endl;
//release memory
threads_should_exit = true;
}
}
} catch (const concurrent_queue<IplImage* >::Canceled & e) {
cout << "grabFrame: Show thread is canceled" << endl;
return;
}
}
void processFrames(concurrent_queue<IplImage* > * frame_queue0, concurrent_queue<IplImage* > * frame_queue1) {
try {
do {
cout << "processFrames: Processing two frames" << endl;
IplImage* frm = NULL;
frame_queue0->wait_and_pop(frm);
IplImage * frm2 = NULL;
frame_queue1->wait_and_pop(frm2);
cvReleaseImage(&frm);
cvReleaseImage(&frm2);
} while (!threads_should_exit);
} catch (const concurrent_queue<IplImage* >::Canceled & e) {
cout << "processFrames: Processing thread is canceled" << endl;
return;
}
}
int main() {
capture = cvCreateCameraCapture(0);
capture2 = cvCreateCameraCapture(1);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, cameraWidth);
cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, cameraHeight);
cvSetCaptureProperty(capture2, CV_CAP_PROP_FRAME_WIDTH, cameraWidth);
cvSetCaptureProperty(capture2, CV_CAP_PROP_FRAME_HEIGHT, cameraHeight);
boost::thread_group frame_workers;
boost::thread_group frame_workers2;
concurrent_queue<IplImage* > frame_queue(&frame_workers);
concurrent_queue<IplImage* > frame_queue2(&frame_workers2);
boost::thread * query_thread = new boost::thread(processFrames, &frame_queue, &frame_queue2);
boost::thread * cam0_thread = new boost::thread(grabFrame, &frame_queue, 0);
usleep(10000);
boost::thread * cam1_thread = new boost::thread(grabFrame, &frame_queue2, 1);
frame_workers.add_thread(query_thread);
frame_workers.add_thread(cam0_thread);
frame_workers2.add_thread(query_thread);
frame_workers2.add_thread(cam1_thread);
while (true) {
if (threads_should_exit) {
cout << "Main: threads should be killed" << endl;
while (!frame_queue.empty()) {
usleep(10000);
}
frame_workers.remove_thread(query_thread);
frame_workers2.remove_thread(query_thread);
frame_workers.remove_thread(cam0_thread);
frame_workers2.remove_thread(cam1_thread);
frame_workers.join_all();
break;
}
usleep(10000);
}
return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括“生产者\消费者\队列.hpp”
//摄像机设置
int cameraWidth=1280;
int cameraHeight=720;
int waitKeyValue=5;
bool线程应该退出=false;
捕获*捕获;
CvCapture*capture2;
使用名称空间std;
使用名称空间cv;
void grabFrame(并发队列*帧队列,整数){
试一试{
//加载第一帧
cout应该只有一个线程操作GUI(对于任何GUI框架都是如此)。您应该组织代码,以便只从主“GUI线程”调用cvShowImage
在query\u线程中执行的工作似乎可以在主线程中轻松完成。我按照您的建议调整了代码,并将整个query\u线程移动到主线程,但这会导致完全相同的行为。如果我不调用cvShowImage,该程序工作正常。我做了,但我还需要移动cvWaitKey()到主线程,并将我的帧抓取速度限制为30 FPS。感谢您的帮助!