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

  • 0
    点赞
  • 23
    收藏
  • 打赏
    打赏
  • 2
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:创作都市 设计师:CSDN官方博客 返回首页
评论 2

打赏作者

Trevor Lan

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值