opencv多线程调用摄像头预览拍照

最近需要做一个通过摄像头拍照的小程序,正好也来学习一下OpenCV。
因为拍照需要预览,程序肯定是多线程的(不然会卡死)。

先用单线程测试,打开摄像头、预览、拍照代码都很简单,没什么问题。然后把代码变成多线程,就开始各种R6010错误。

在网上到处找资料,看到有不少人说,要用CoInitialize、CoInitializeEx可以解决。开开心心的测试了一下,结果发现根本没用。也许在旧版本能行吧(我用的OPENCV3.0版本)

继续找,最后得到的结果居然是VideoCapture、namedWindow、imshow、waitKey这些个函数都只能在MainThread中使用,WorkerThread都不能使用。

实现无法理解那些OpenCV的大牛们是怎样活下来的(估计是有别的高深的方法,我不知道吧。)

最后还是要靠自己来,最终摸索出来的代码如下,简单测试了一下,能够工作了,留存一下(说不定哪天还能用上)。

使用环境是VS2012, opencv3.0版
完整示例代码如下:

#include 
#include 
#include 

using namespace cv;
using namespace std;

Mat frame;
string photoFileName = "photo1.jpg";
VideoCapture cap;

//打开摄像头
void showVideo()
{

    //打开第一个摄像头
    cap.open(0);

    //打开视频文件
    //cap.open("ad.avi");

    //检查是否成功打开
    if(!cap.isOpened())
    {
        cerr << "Can not open a camera or file." << endl;
        return;
    }

    //创建窗口
    namedWindow("edges");

    for(;;)
    {
        //从 cap 中读一帧,存到 frame
        cap >> frame;
        //如果未读到图像
        if(frame.empty())
            break;
        
        imshow("edges", frame);
        //等待 30ms,如果按键则推出循环
        waitKey(30);
    }

    //退出时会自动释放 cap 中占用资源
}

void takePhoto(string fileName)
{
    if(!frame.empty())
    {
        imwrite(fileName, frame);
    }
    else 
    {
        cout << "frame is empty" << endl;
    }
}

void showImage(string fileName)
{
    // 读入一张图片,图片来源OpenCV的数据 ...opencv\sources\samples\data\目录下  
    //Mat img = imread("lena.jpg");

    Mat img = imread(fileName);
    if (img.empty())
    {
        cout << "打开图像失败!" << endl;
        return;
    }

    // 创建一个名为 "Demo"窗口  
    namedWindow("Demo");

    // 在窗口中显示图片  
    imshow("Demo", img);

    //等待3000 ms后窗口自动关闭  
    waitKey(3000);

    //需要主动释放窗体,否则第二次窗口可能显示不出来
    cv::destroyWindow("Demo");
}

void closeVideo()
{
    if ( cap.isOpened() )
    {
        cap.release();
        //需要主动释放窗体,否则第二次窗口可能显示不出来
        cv::destroyAllWindows();
        return;
    }
}

int main(int argc, char **argv)
{
    bool bRun = true;
    while(bRun)
    {
        cout << "1:打开摄像头" << endl;
        cout << "2:拍照" << endl;
        cout << "3:显示图片" << endl;
        cout << "4:关闭摄像头" << endl;
        cout << "9:退出程序" << endl;
        cout << "请选择" << endl;
        int i = 0;
        cin >> i;
        switch (i)
        {
        case 1:  //showvideo
            {
                std::thread t1(showVideo);
                //如果不使用detach,会报R6010错误
                t1.detach();
            }
            break;
        case 2: //takePhoto
            {
                std::thread t1(takePhoto, photoFileName);
                t1.detach();
            }
            break;
        case 3: //showImage
            {
                std::thread t2(showImage, photoFileName);
                t2.detach();
            }
            break;
        case 4: //closeVideo
            {
                closeVideo();
            }
            break;
        case 9:
            bRun = false;
            break;
        default:
            cout << "请重新输入" << endl;
            break;
        }
    }
    return 0;
}

转载于:https://www.cnblogs.com/peerhuo/p/5826075.html

你可能感兴趣的:(人工智能,c/c++)