加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 使用OpenCV,Boost线程和多个摄像头

发布时间:2020-12-16 07:00:41 所属栏目:百科 来源:网络整理
导读:我正在尝试编写一个能够从两个不同线程中的两个不同摄像头捕获图像的程序.我想这样做是因为当我在同一个线程中执行此操作时,我必须继续等待cvQueryFrame两倍的时间,因此我无法以30 fps的速度抓取图像(我从每个摄像头获得15 FPS). 我看过这篇SO帖子,但这只适
我正在尝试编写一个能够从两个不同线程中的两个不同摄像头捕获图像的程序.我想这样做是因为当我在同一个线程中执行此操作时,我必须继续等待cvQueryFrame两倍的时间,因此我无法以30 fps的速度抓取图像(我从每个摄像头获得15 FPS).

我看过这篇SO帖子,但这只适用于一台摄像机. Using cvQueryFrame and boost::thread together

我当前的程序给出了不同的结果,有时它会给内存泄漏,通常我只是看不到任何事情发生,有时候它会花费几秒钟,但图像会再次冻结.奇怪的是,早些时候我没有调用cvShowImage,但是让我的imageProcessing函数做了一些有用的东西我可以看到我从两个摄像头得到实时结果.我认为这意味着可以使这项工作成功,但我在某处犯了一个愚蠢的错误.我的操作系统是LINUX,我使用的是OpenCV 2.4

我的代码:

#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,cameraWidth);
    cvSetCaptureProperty(capture2,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,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;

}

编辑:

我添加了一个简单的函数来检测一张纸,看看当我不调用cvShowImage()时一切正常.如果我不调用cvShowImage(),我的程序可以检测到一张纸.如果我这样做该程序再次有奇怪的行为并冻结等.

解决方法

应该只有一个线程来操纵GUI(对于任何GUI框架都是如此).您应该组织代码,以便仅从主“GUI线程”调用cvShowImage.

似乎在query_thread中完成的工作可以在主线程内轻松完成.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读