使用c++的opencv库实现摄像头在html中的调用

主要流程是:封装一个ocx控件,其中包含了opencv打开摄像头的函数,接着在windows下注册ocx,并用html的Object标签加载ActiveX控件
具体步骤:
一、测试摄像头调用函数
1、新建MFC ActiveX控件
2、在ctrl头文件中定义openCamera函数
3、ctrl.cpp文件中进行调度映射,使用DISP_FUNCTION函数,加载openCamera函数
4、ctrl.cpp文件中使用Cctrl::openCamera()来编写实现函数,用到VedioCapture类、Mat图像矩阵类,imshow调用默认对话框显示摄像头图像,while(1){waitKey(30)};反复执行
5、Mat转换为CImage
(1)对一些异常情况的处理:矩阵元素总个数mat.total为0,通道数不等于1或者3,这两种情况返回错误值,提示无法转换
(2)获取图像宽高,width=mat.cols height=mat.rows
(3)重建cImage,调用destroy方法和create方法,创建RGB模式图像,3通道各8位深度,一共24位(3*channels)
(4)拷贝数据,如果是单通道,创建灰度模式图像,初始化调色板,设置8位深度(256),并设置调色板数组的每个元素的RGB默认值,为cImage设置新的调色板,删除调色板临时数组
(5)设置mat行指针、cImage位的指针和cImage每行的字节数,拷贝数据,通过两个for循环,将cImage指针指向对应的mat数组元素

代码引用:https://blog.csdn.net/liangjialang/article/details/33320093

void MatToCImage(Mat& mat, CImage& cimage)
{
    if (0 == mat.total())
    {
        return;
    }


    int nChannels = mat.channels();
    if ((1 != nChannels) && (3 != nChannels))
    {
        return;
    }
    int nWidth    = mat.cols;
    int nHeight   = mat.rows;


    //重建cimage
    cimage.Destroy();
    cimage.Create(nWidth, nHeight, 8 * nChannels);


    //拷贝数据


    uchar* pucRow;                                  //指向数据区的行指针
    uchar* pucImage = (uchar*)cimage.GetBits();     //指向数据区的指针
    int nStep = cimage.GetPitch();                  //每行的字节数,返回值有正有负


    if (1 == nChannels)                             //对于单通道的图像需要初始化调色板
    {
        RGBQUAD* rgbquadColorTable;
        int nMaxColors = 256;
        rgbquadColorTable = new RGBQUAD[nMaxColors];
        cimage.GetColorTable(0, nMaxColors, rgbquadColorTable);
        for (int nColor = 0; nColor < nMaxColors; nColor++)
        {
            rgbquadColorTable[nColor].rgbBlue = (uchar)nColor;
            rgbquadColorTable[nColor].rgbGreen = (uchar)nColor;
            rgbquadColorTable[nColor].rgbRed = (uchar)nColor;
        }
        cimage.SetColorTable(0, nMaxColors, rgbquadColorTable);
        delete []rgbquadColorTable;
    }


    for (int nRow = 0; nRow < nHeight; nRow++)
    {
        pucRow = (mat.ptr<uchar>(nRow));
        for (int nCol = 0; nCol < nWidth; nCol++)
        {
            if (1 == nChannels)
            {
                *(pucImage + nRow * nStep + nCol) = pucRow[nCol];
            }
            else if (3 == nChannels)
            {
                for (int nCha = 0 ; nCha < 3; nCha++)
                {
                    *(pucImage + nRow * nStep + nCol * 3 + nCha) = pucRow[nCol * 3 + nCha];
                }           
            }
        }   
    }
}

6、F7快速生成ocx
二、使用regsvr32 …ocx命令注册ocx控件
三、html中放置按钮,并在点击事件中添加调用ocx的方法,Object中的style定义了摄像头窗口的大小,与ctrl,cpp文件中OnDraw方法相对应,Object的classid值与idl文件中ctrl的uuid相对应
四、在IE中允许ActiveX控件,并运行程序

遇到的问题:
一、引入Mat类时,要包含opencv中的higngui头文件,必须使用cv命名空间
二、引入CImage类时,必须先包含atlimage.h再包含stdafx.h
三、测试时,必须使用IE浏览器,加载ActiveX控件

扩展:CImage转换为Mat
原理同Mat转CImage
(1)初始化mat时,采用CV_8UC1和CV_8UC3两种类型
(2)不需要借助调色板,直接由图像转为矩阵

猜你喜欢

转载自blog.csdn.net/zhawenting/article/details/81333818
今日推荐