opencv+directshow实现4个摄像头同步采集图像

基于网上许多人说到opencv打不开4个摄像头,事实果真如此么,记得哦:opencv是开源的,所以本作者我利用vs2013自己配置了一下opencv与directshow的开发环境,具体要怎么配置我就不详细讲了,上网搜一下就能找得到了,下面我详细讲一下如何将mfc和多线程与opencv和directshow结合实现4个摄像头同步采集图像,本作者正读大二,能力有限,有更好的方法也告诉我一下哈。


一.先在mfc上把界面先布局好如下图

打开4个摄像头


将布局好的界面稍微改一下相关的属性值

这里写图片描述


1-1将显示摄像头区域的ID分别改为:
IDC_Camera1
IDC_Camera2
IDC_Camera3
IDC_Camera3


1-2将控制摄像头开关和关闭界面的控件ID分别改为:
IDC_Capture1
IDC_Capture2
IDC_Capture3
IDC_Capture4
IDCANCEL


二.在对话框的头文件里添加4个线程句柄和打开4个摄像头和一个关闭界面的响应函数:
这里写图片描述

//创建4个线程句柄
protected:
        HANDLE h1;
        HANDLE h2;
        HANDLE h3;
        HANDLE h4;
// 创建打开摄像头和关闭界面的映射函数
public:
        afx_msg void OnBnClickedCancel();
        afx_msg void OnBnClickedCapture1();
        afx_msg void OnBnClickedCapture2();
        afx_msg void OnBnClickedCapture3();
        afx_msg void OnBnClickedCapture4();

三.在对话框的.cpp文件里的OnInitDialog()函数内初始化句柄

3.1定义一些全局变量来获取图片的句柄
这里写图片描述


//定义一些全局变量来获取图片的句柄
CRect rect1;
CRect rect2;
CRect rect3;
CRect rect4;

CDC* pDC1;
CDC* pDC2;
CDC* pDC3;
CDC* pDC4;

HDC hDC1;
HDC hDC2;
HDC hDC3;
HDC hDC4;

CWnd* pwnd1;
CWnd* pwnd2;
CWnd* pwnd3;
CWnd* pwnd4;

3.2OnInitDialog()函数内初始化句柄
这里写图片描述

//句柄的初始化
pwnd1 = GetDlgItem(IDC_Camera1);
pDC1 = pwnd1->GetDC();
hDC1 = pDC1->GetSafeHdc();
pwnd1->GetClientRect(&rect1);

pwnd2 = GetDlgItem(IDC_Camera2);
pDC2 = pwnd2->GetDC();
hDC2 = pDC2->GetSafeHdc();
pwnd2->GetClientRect(&rect2);

pwnd3 = GetDlgItem(IDC_Camera3);
pDC3 = pwnd3->GetDC();
hDC3 = pDC3->GetSafeHdc();
pwnd3->GetClientRect(&rect3);

pwnd4 = GetDlgItem(IDC_Camera4);
pDC4 = pwnd4->GetDC();
hDC4 = pDC4->GetSafeHdc();
pwnd4->GetClientRect(&rect4);

四.在对话框源文件里填加4个互斥对象并添加对应的响应函数:
这里写图片描述


    HANDLE hMutex1; //互斥对象1
    CCameraDS camera1;//摄像头1
    unsigned long _stdcall ThreadProc1(void* IpParameter){
        while (1){
            WaitForSingleObject(hMutex1, INFINITE);//等待互斥对象所以权
            if (CCameraDS::CameraCount() >= 1)
            {
                camera1.OpenCamera(0, false, 320, 240);//打开第一个摄像头
                while (1)
                {
                    IplImage *pFrame1 = camera1.QueryFrame();//获取每一帧
                    CvvImage m_CvvImage;                    
                    m_CvvImage.CopyOf(pFrame1, 1);
                    if (true)
                    {
                        m_CvvImage.DrawToHDC(hDC1, &rect1);//将获取到的图像画到控件上
                    }
                }
            }
            else
            {
                AfxMessageBox("无法打开摄像头1");
                return -1;
            }
            Sleep(100);
            ReleaseMutex(hMutex1);                          
        }
        return 0;

    }
    void CDirectshow_4CameraDlg::OnBnClickedCapture1()
    {
        CString Text;
        GetDlgItem(IDC_Capture1)->GetWindowText(Text);          //获取按键文本
        if (Text == "摄像头1")                                 //判断是否要打开摄像头
        {
            h1 = CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);//创建一个线程
            hMutex1 = CreateEvent(NULL, FALSE, TRUE, "event1");
            hMutex1 = CreateMutex(NULL, false, "hMutex1");
            GetDlgItem(IDC_Capture1)->SetWindowText("关闭摄像头1");
        }
        else        //当按键文本为"关闭摄像头1"时,执行关闭摄像头
        {
            TerminateThread(h1, 0);                         //终止线程1
            camera1.CloseCamera();                          //关闭摄像头
            GetDlgItem(IDC_Capture1)->SetWindowText("摄像头1");//修改按键文本
        }
    }
    //以下内容相同,省略注释
    //摄像头2
    HANDLE hMutex2;
    CCameraDS camera2;
    unsigned long _stdcall ThreadProc2(void* IpParameter){
        while (1){
            WaitForSingleObject(hMutex2, INFINITE);
            if (CCameraDS::CameraCount() >= 2){
                camera2.OpenCamera(1, false, 320, 240);
                while (1)
                {
                    IplImage *pFrame2 = camera2.QueryFrame();
                    CvvImage m_CvvImage2;
                    m_CvvImage2.CopyOf(pFrame2, 1);
                    if (true)
                    {
                        m_CvvImage2.DrawToHDC(hDC2, &rect2);
                    }
                }
            }
            else
            {
                AfxMessageBox("无法打开摄像头2");
                return -1;
            }
            Sleep(100);
            ReleaseMutex(hMutex2);
        }
        return 0;
    }


    void CDirectshow_4CameraDlg::OnBnClickedCapture2()
    {
        CString Text;
        GetDlgItem(IDC_Capture2)->GetWindowText(Text);
        if (Text == "摄像头2")
        {
            h2 = CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);
            hMutex2 = CreateEvent(NULL, FALSE, TRUE, "event2");
            hMutex2 = CreateMutex(NULL, false, "hMutex2");
            GetDlgItem(IDC_Capture2)->SetWindowText("关闭摄像头2");
        }
        else
        {
            TerminateThread(h2, 0);
            camera2.CloseCamera();
            GetDlgItem(IDC_Capture2)->SetWindowText("摄像头2");
        }
    }

    //摄像头3
    HANDLE hMutex3;
    CCameraDS camera3;
    unsigned long _stdcall ThreadProc3(void* IpParameter){
        while (1){
            WaitForSingleObject(hMutex3, INFINITE);
            if (CCameraDS::CameraCount() >= 3){
                camera3.OpenCamera(2, false, 320, 240);
                while (1)
                {
                    IplImage *pFrame3 = camera3.QueryFrame();
                    CvvImage m_CvvImage3;
                    m_CvvImage3.CopyOf(pFrame3, 1);
                    if (true)
                    {
                        m_CvvImage3.DrawToHDC(hDC3, &rect3);
                    }
                }
            }
            else
            {
                AfxMessageBox("无法打开摄像头3");
                return -1;
            }
            Sleep(100);
            ReleaseMutex(hMutex3);
        }
        return 0;
    }


    void CDirectshow_4CameraDlg::OnBnClickedCapture3()
    {
        CString Text;
        GetDlgItem(IDC_Capture3)->GetWindowText(Text);
        if (Text == "摄像头3")
        {
            h3 = CreateThread(NULL, 0, ThreadProc3, NULL, 0, NULL);
            hMutex3 = CreateEvent(NULL, FALSE, TRUE, "event3");
            hMutex3 = CreateMutex(NULL, false, "hMutex3");
            GetDlgItem(IDC_Capture3)->SetWindowText("关闭摄像头3");
        }
        else
        {
            TerminateThread(h3, 0);
            camera3.CloseCamera();
            GetDlgItem(IDC_Capture3)->SetWindowText("摄像头3");
        }
    }

    //摄像头4
    HANDLE hMutex4;
    CCameraDS camera4;
    unsigned long _stdcall ThreadProc4(void* IpParameter){
        while (1){
            WaitForSingleObject(hMutex4, INFINITE);
            if (CCameraDS::CameraCount() >= 4){
                CCameraDS camera4;
                camera4.OpenCamera(3, false, 320, 240);
                while (1)
                {
                    IplImage *pFrame4 = camera4.QueryFrame();
                    CvvImage m_CvvImage4;
                    m_CvvImage4.CopyOf(pFrame4, 1);
                    if (true)
                    {
                        m_CvvImage4.DrawToHDC(hDC4, &rect4);
                    }
                }
            }
            else
            {
                AfxMessageBox("无法打开摄像头4");
                return -1;
            }
            Sleep(100);
            ReleaseMutex(hMutex4);
        }
        return  h4 = CreateThread(NULL, 0, ThreadProc4, NULL, 0, NULL);
                hMutex4 = CreateEvent(NULL, FALSE, TRUE, "event4");
                hMutex4 = CreateMutex(NULL, false, "hMutex4");
                GetDlgItem(IDC_Capture4)->SetWindowText("关闭摄像头4");
            }
            else
            {
                TerminateThread(h4, 0);
                camera4.CloseCamera();
                GetDlgItem(IDC_Capture4)->SetWindowText("摄像头4");
            }
        }
        pture4)->SetWindowText("关闭摄像头4");
        }
        else
        {
            TerminateThread(h4, 0);
            camera4.CloseCamera();
            GetDlgItem(IDC_Capture4)->SetWindowText("摄像头4");
        }
    }

    void CDirectshow_4CameraDlg::OnBnClickedCancel()
    {
        switch (CCameraDS::CameraCount())   //判断需要终止多少个线程
        {
            case 1:
                    {
                        TerminateThread(h1, 0);
                        break;
                    }
            case 2:
                    {
                        TerminateThread(h1, 0);
                        TerminateThread(h2, 0);
                        break;
                    }
            case 3:
                    {
                        TerminateThread(h1, 0);
                        TerminateThread(h2, 0);
                        TerminateThread(h3, 0);
                        break;
                    }
            case 4:
                    {
                        TerminateThread(h1, 0);
                        TerminateThread(h2, 0);
                        TerminateThread(h3, 0);
                        TerminateThread(h4, 0);
                        break;
                    }
        }
        CDialogEx::OnCancel();
    }

五.验证效果
这里写图片描述

六.总结
opencv+directshow打开4个摄像头的方法除了用互斥对象实现多线程同步外还可以用事件对象实现多线程同步

转载请标明出处:http://blog.csdn.net/lwqbrell/article/details/53954795

  • 2
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: OpenCV和ZBar是两个常用的开源库,可以用于实现摄像头识别二维码的功能。 首先,OpenCV是一款用于计算机视觉的开源库,它提供了丰富的图像处理和计算机视觉算法,可以用来处理图像和视频。OpenCV支持各种程序设计语言,包括C++、Python等,因此非常方便开发者进行二维码的图像处理和识别。 而ZBar是一款专门用于二维码和条形码扫描的开源库。它提供了各种功能强大的接口,可以对摄像头捕捉到的图像进行二维码的识别。ZBar支持多种编程语言,如C、C++、Python等,因此可以与OpenCV结合使用。 要实现摄像头识别二维码的功能,可以按照以下步骤进行: 1. 首先,使用OpenCV打开摄像头,获取实时图像流。 2. 将摄像头捕捉到的图像传递给ZBar库进行二维码的识别。ZBar库提供了相关的函数和接口,可以将摄像头捕获的图像进行处理,并识别其中的二维码。 3. 当ZBar识别到二维码时,可以通过回调函数或其他方式将识别到的二维码信息传递给应用程序,可以对识别到的二维码进行相关的操作,如解析二维码内容,打开对应的链接或进行其他业务处理。 总的来说,通过将OpenCV和ZBar结合使用,我们可以实现摄像头实时识别二维码的功能。这样,我们可以利用摄像头实时获取图像流,并通过ZBar库对图像进行识别,从而实现对二维码的实时扫描和处理。 ### 回答2: OpenCV是一个开源的计算机视觉库,提供了丰富的图像处理和计算机视觉算法。而ZBar是一个开源的条码和二维码识别库,能够通过摄像头进行实时的二维码识别。 使用OpenCV和ZBar库实现摄像头识别二维码的步骤如下: 1. 首先,我们需要使用OpenCV库中的VideoCapture类来打开摄像头,并获取实时的视频帧。 2. 在每一帧中,我们将使用ZBar库提供的二维码识别功能。通过将每一帧转换为灰度图像,可以提高识别效果。 3. 在灰度图像上,我们可以使用ZBar库的Scanner类进行二维码的扫描。Scanner类可以检测到图像中的所有二维码,并返回相关信息。 4. 当扫描到二维码时,我们可以从Scanner类中获取二维码的内容。 5. 最后,我们可以使用OpenCV库提供的绘图功能,在视频帧上标记出识别到的二维码的位置和内容。 通过以上步骤,我们可以实现摄像头实时识别二维码的功能。这种方法可以应用于一些需要实时扫描二维码的场景,例如门禁系统、物流追踪等。同时,OpenCV和ZBar库的开源特性也使得开发者能够根据自己的需求进行定制和修改,提高二维码识别的准确率和效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值