原创 第4节 利用Labwindows/CVI软件对摄像头的控制

2012-4-6 16:14 6322 22 21 分类: 软件与OS 文集: Labwindows技术板块

利用Labwindows/CVI软件对摄像头的控制

一、概述
        首先,先介绍一下windows系统在驱动摄像头的时候都使用到一个链接库,传统的是avicap32.dll和avicap32.lib。这两个文件是比较通用的,而且也是比较早期的文件。现在也有比较新的链接库,例如DirectShowLib.dll。在使用这个链接库来实现视频的捕捉时,主要使用下面这个函数来打开摄像头:
int capCreateCaptureWindowA(String lpszWindowName,Long dwStyle,Long x,Long y,Long nWidth,Long nHeight,Long hwndParent,Long nID);
       返回值为打开的句柄值。    
       String lpszWindowName:视频窗口的名字
       Long dwStyle:样式
       Long x:左边距(相对于主窗口,没有边距值为0)
       Long y:上边距(相对于主窗口,没有边距值为0)
       Long nWidth:视频窗口的宽度(注:此项不会改变摄像头的分辨率,超出部分不会被刷新)
       Long nHeight:视频窗口的高度
       Long hwndParent:主窗口句柄,主要是用来显示摄像头采集到得视频。
       Long nID:标识符(一般为0)
      摄像头打开后,要对摄像头相关信息进行参数设置,比如摄像头的分辨率等。摄像头参数的设置使用到得函数是windows.h声明到的SendMessage。函数的原型为:
       LRESULT SendMessage(HWND hWnd,UNIT Msg,WPARAM wParam,LPARAM IParam);
       hWnd:其窗口程序将接收消息的窗口的句柄。如果此参数为HWND_BROADCAST,则消息将被发送到系统中所有顶层窗口,包括无效或不可见的非自身拥有的窗口,被覆盖的窗口和弹出式窗口,但消息不被发送到子窗口。
       Msg:指定被发送的消息。
       wParam:指定附加的消息指定信息。
       IParam:指定附加的消息指定信息。
      返回值:返回值指定消息处理的结果,依赖于所发送的消息。
      Msg是指定发送的消息,主要有一下这些消息指令:
   WM_CAP_START= WM_USER=1024;
  // start of unicode messages
  WM_CAP_UNICODE_START= WM_USER+100; //开始
  WM_CAP_GET_CAPSTREAMPTR= (WM_CAP_START+ 1); //获得 CAPSTR EAMPTR
  WM_CAP_SET_CALLBACK_ERROR= (WM_CAP_START+ 2); //设置回调错误
  WM_CAP_SET_CALLBACK_STATUS= (WM_CAP_START+ 3); //设置回调状态
  WM_CAP_SET_CALLBACK_YIELD= (WM_CAP_START+ 4); //设置回调出产
  WM_CAP_SET_CALLBACK_FRAME= (WM_CAP_START+ 5); //设置回调结构
  WM_CAP_SET_CALLBACK_VIDEOSTREAM= (WM_CAP_START+ 6); //设置回调视频流
  WM_CAP_SET_CALLBACK_WAVESTREAM= (WM_CAP_START+ 7); //设置回调视频波流
  WM_CAP_GET_USER_DATA =(WM_CAP_START+ 8); //获得使用者数据
  WM_CAP_SET_USER_DATA =(WM_CAP_START+ 9) ; //设置使用者数据
  WM_CAP_DRIVER_CONNECT =(WM_CAP_START+ 10); //驱动程序连接
  WM_CAP_DRIVER_DISCONNECT =(WM_CAP_START+ 11); //断开启动程序连接
  WM_CAP_DRIVER_GET_NAME =(WM_CAP_START+ 12); //获得驱动程序名字
  WM_CAP_DRIVER_GET_VERSION =(WM_CAP_START+ 13); //获得驱动程序版本
  WM_CAP_DRIVER_GET_CAPS =(WM_CAP_START+ 14); //获得驱动程序性能
  WM_CAP_FILE_SET_CAPTURE_FILE =(WM_CAP_START+ 20); //设置捕获文件的文件名
  WM_CAP_FILE_GET_CAPTURE_FILE =(WM_CAP_START+ 21); //获得捕获文件的文件名
  WM_CAP_FILE_SAVEAS =(WM_CAP_START+ 23); //另存文件为
  WM_CAP_FILE_SAVEDIB =(WM_CAP_START+ 25); //保存文件
  // out of order to save on ifdefs
  WM_CAP_FILE_ALLOCATE =(WM_CAP_START+ 22); //分派文件, 为捕获文件建一个指定大小的文件
  WM_CAP_FILE_SET_INFOCHUNK =(WM_CAP_START+ 24); //设置开始文件
  WM_CAP_EDIT_COPY =(WM_CAP_START+ 30); //编辑复制,把图象考入剪贴板
  WM_CAP_SET_AUDIOFORMAT =(WM_CAP_START+ 35); //设置音频格式
  WM_CAP_GET_AUDIOFORMAT =(WM_CAP_START+ 36); //捕获音频格式
  WM_CAP_DLG_VIDEOFORMAT =(WM_CAP_START+ 41); //1065 打开视频格式设置对话框, 选择数字视频的框架大小和视频图像的色深,以及捕获视频图像的压缩格式。
  WM_CAP_DLG_VIDEOSOURCE =(WM_CAP_START+ 42); //1066 打开属性设置对话框,设置对比度、亮度等。(视频源对话框) 选择视频输入通道和视频图像的动态参数。
  WM_CAP_DLG_VIDEODISPLAY =(WM_CAP_START+ 43); //1067 打开视频显示对话框
  WM_CAP_GET_VIDEOFORMAT =(WM_CAP_START+ 44); //1068 获得视频格式
  WM_CAP_SET_VIDEOFORMAT =(WM_CAP_START+ 45); //1069 设置视频格式
  WM_CAP_DLG_VIDEOCOMPRESSION =(WM_CAP_START+ 46); //1070 打开压缩设置对话框
  WM_CAP_SET_PREVIEW =(WM_CAP_START+ 50); //设置预览模式
  WM_CAP_SET_OVERLAY =(WM_CAP_START+ 51); //设置覆盖
  WM_CAP_SET_PREVIEWRATE =(WM_CAP_START+ 52); //设置预览模式下图像的帧速度
  WM_CAP_SET_SCALE =(WM_CAP_START+ 53); //设置预览视频的缩放比例
  WM_CAP_GET_STATUS =(WM_CAP_START+ 54); //获得状态
  WM_CAP_SET_SCROLL =(WM_CAP_START+ 55); //设置卷
  WM_CAP_GRAB_FRame =(WM_CAP_START+ 60); //逮捕结构
  WM_CAP_GRAB_FRame_NOSTOP =(WM_CAP_START+ 61); //停止逮捕结构,截取当前图象
  WM_CAP_SEQUENCE =(WM_CAP_START+ 62); //次序,捕捉到文件
  WM_CAP_SEQUENCE_NOFILE =(WM_CAP_START+ 63); //没有文件
  WM_CAP_SET_SEQUENCE_SETUP =(WM_CAP_START+ 64); //设置当前捕获的帧频率
  WM_CAP_GET_SEQUENCE_SETUP =(WM_CAP_START+ 65); //获得当前捕获的帧频率
  WM_CAP_SET_MCI_DEVICE =(WM_CAP_START+ 66); //设置媒体控制接口
  WM_CAP_GET_MCI_DEVICE =(WM_CAP_START+ 67); //获得媒体控制接口
  WM_CAP_STOP =(WM_CAP_START+ 68); //停止捕捉
  WM_CAP_ABORT =(WM_CAP_START+ 69); //异常中断
  WM_CAP_SINGLE_FRame_OPEN =(WM_CAP_START+ 70); //打开单一的结构
  WM_CAP_SINGLE_FRame_CLOSE =(WM_CAP_START+ 71); //关闭单一的结构
  WM_CAP_SINGLE_FRame =(WM_CAP_START+ 72); //单一的结构
  WM_CAP_PAL_OPEN =(WM_CAP_START+ 80); //打开视频
  WM_CAP_PAL_SAVE =(WM_CAP_START+ 81); //保存视频
  WM_CAP_PAL_PASTE =(WM_CAP_START+ 82); //粘贴视频
  WM_CAP_PAL_AUTOCREATE =(WM_CAP_START+ 83); //自动创造
  WM_CAP_PAL_MANUALCREATE =(WM_CAP_START+ 84); //手动创造
  // Following added post VFW 1.1
  WM_CAP_SET_CALLBACK_CAPCONTROL =(WM_CAP_START+ 85); // 设置收回的错误
  WM_CAP_END =WM_CAP_SET_CALLBACK_CAPCONTROL;
二、编程实例
        说明:此实例采用的是labwindows/CVI8.5虚拟软件实现的摄像头采集图像程序。
打开labwindows/CVI8.5软件,点击“File->New->Project”新建一个工程文件camera.prj,然后添加一个*.uir面板,命名为camera.uir,并添加到工程文件中。然后对camera.uir面板进行编辑。如图:

         接着,为这面板上的控件进行编辑。显示面板采用的是CANVAS控件,定义变量命为:CANVAS_DISPLAY,用于后面显示时调用,“开始视频”控件定义函数名:StartCB,“退出视频”控件函数名:stopCB,“保存图像”控件函数名:recordbmp,“录像”控件函数名:recordstream,“停止录像”控件函数名:stopstream,显示模式控件采用的Ring控件,定义函数名:method。最后退出面板控件定义函数QuitCallback。在面板的最左边空白处,添加了三个canvas控件,用于在保存图像时,对新保存的三个图像进行显示。
然后为工程新建一个c源文件或通过自动方式来生成一个c源文件。一般使用自动方式,即在uir文件处,通过“Code->Generate->All code”为此面板自动生成c文件代码。保存c源文件为camera.c。接着为这些函数添加代码:
  (1)为“开始视频”控件函数startCB添加代码如下:
        int Display_width;
        int Display_height;
        int Display_top;
        int Display_left;
        switch (event)
         {
          case EVENT_COMMIT:
          //获得面板句柄,用于在调用摄像头函数时,需要使用的句柄handle
         GetPanelAttribute (panelHandle, ATTR_SYSTEM_WINDOW_HANDLE, &handle);
         //获得屏幕中图像要显示的位置
         GetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_LEFT, &Display_left);
         GetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_TOP, &Display_top);
         GetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_HEIGHT, &Display_height);
         GetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_WIDTH, &Display_width);
        //打开摄像头
        result = capCreateCaptureWindowA("",WS_CHILD | WS_VISIBLE ,Display_left,Display_top,Display_width,Display_height,handle,0);
        //设置摄像头函数
       SendMessage((HWND)result, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0);
       SendMessage((HWND)result, WM_CAP_SET_CALLBACK_ERROR, 0, 0);
       SendMessage((HWND)result, WM_CAP_SET_CALLBACK_STATUSA, 0, 0);
       SendMessage((HWND)result, WM_CAP_DRIVER_CONNECT, 0, 0);
       SendMessage((HWND)result, WM_CAP_SET_SCALE, 1, 0);
      SendMessage((HWND)result, WM_CAP_SET_PREVIEWRATE, 66, 0);
      SendMessage((HWND)result, WM_CAP_SET_OVERLAY, 1, 0);
      SendMessage((HWND)result, WM_CAP_SET_PREVIEW, 1, 0);
      break;
    }
   return 0;

  (2)为“停止视频”控件函数stopCB添加源代码如下:
     if (result != 0)  //如果有摄像头开启
       {
         //发送一个断开连接命令
         SendMessage((HWND)result, WM_CAP_DRIVER_DISCONNECT, 0, 0);
        }
(3)为“保存图像”控件函数recordbmp添加源代码如下:
    //定义BMP位图ID号
     int bitmapID;
     //定义文件存储路径
     char path[MAX_PATHNAME_LEN];
     //定义静态变量,设置循环次数
     static int i;
     i = 0;
     switch (event)
      {
        case EVENT_COMMIT:
        //保存位图
        if (FileSelectPopup ("", "*.bmp", "*.bmp", "保存", VAL_SAVE_BUTTON, 0, 0, 1, 1, path) > 0)
        {
           SendMessage((HWND)result,WM_CAP_SAVEDIB,0,(LPARAM)path);
           //获得BMP位图ID
           GetBitmapFromFile (path, &bitmapID);
           switch (i)
           {
                //设置三个位图浏览器
                case 0:
                    CanvasDrawBitmap (panelHandle, PANEL_CANVAS_SNAP0, bitmapID, VAL_ENTIRE_OBJECT, VAL_ENTIRE_OBJECT);
                    break;
                  case 1:
                    CanvasDrawBitmap (panelHandle, PANEL_CANVAS_SNAP1, bitmapID, VAL_ENTIRE_OBJECT, VAL_ENTIRE_OBJECT);
                    break;
                  case 2:
                    CanvasDrawBitmap (panelHandle, PANEL_CANVAS_SNAP2, bitmapID, VAL_ENTIRE_OBJECT, VAL_ENTIRE_OBJECT);
                    break;
           }
             //删除BMP位图ID
           DiscardBitmap (bitmapID);
          //循环累加,共三次,三次之后回零
          i++;
          if (i == 3)
             {
               i = 0;
              }
          }
            break;
    }
    return 0;
(4)为“开始录像”控件函数recordstream添加源代码如下:
char path[MAX_PATHNAME_LEN];  
    switch (event)
    {
        case EVENT_COMMIT:
            //保存录像
             if (FileSelectPopup ("", "*.avi", "*.avi", "保存", VAL_SAVE_BUTTON, 0, 0, 1, 1, path) > 0)
                {
    SendMessage((HWND)result,WM_CAP_FILE_SET_CAPTURE_FILEA,0,(LPARAM)path);
                  SendMessage((HWND)result, WM_CAP_SEQUENCE, 0, 0);
                }
            break;
    }
    return 0;
(5)为“停止录像”控件函数stopstream添加源代码如下:
    switch (event)
    {
        case EVENT_COMMIT:
//发送WM_CAP_STOP停止命令
            SendMessage((HWND)result, WM_CAP_STOP, 0, 0);        
           break;
    }
    return 0;
}
(6)为“显示模式”控件添加函数method代码如下:
//获得制式种类
GetCtrlVal (panelHandle, PANEL_RING, &kind);
switch (kind)
   {
     case 0:
        //160*120制式
        SetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_WIDTH, 160);
        SetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_HEIGHT, 120);
     break;
     case 1:
        //1176*144制式
        SetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_WIDTH, 176);
        SetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_HEIGHT, 144);
     break;
     case 2:
        //320*240制式
        SetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_WIDTH, 320);
        SetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_HEIGHT, 240);
     break;
     case 3:
        //352*288制式
        SetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_WIDTH, 352);
        SetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_HEIGHT, 288);
     break;
     case 4:
        //1默认制式
        SetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_WIDTH, 592);
        SetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_HEIGHT, 333);
     break;
    }
//获得屏幕中图像要显示的位置
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_LEFT, &left);
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_TOP, &top);
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_HEIGHT, &height);
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_WIDTH, &width);
   //重新定位
   SetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_TOP, (333-height)/2+55);
   SetCtrlAttribute (panelHandle, PANEL_CANVAS_DISPLAY, ATTR_LEFT, (592-width)/2+53);
   //断开连接
   SendMessage((HWND)result, WM_CAP_DRIVER_DISCONNECT, 0, 0);
   //调用开始按钮事件
   startCB(panel, PANEL_CANVAS_DISPLAY, EVENT_COMMIT, NULL, 0, 0);
三、总结
        采用Labwindows/CVI软件实现了摄像头的视频和录像功能,而且可以选择不同的显示分辨率,设计面板较为简单且美观,控件使用方面快捷!主要使用到得函数来自于动态链接库avicap32.dll中的摄像头开启函数capCreateCaptureWindowA,然后通过windows.h声明的SendMessage函数来发送摄像头的显示相关的命令来设置摄像头。
 

作者: sharcky, 来源:面包板社区

链接: https://mbb.eet-china.com/blog/uid-me-221763.html

版权声明:本文为博主原创,未经本人允许,禁止转载!

文章评论8条评论)

登录后参与讨论

甜橙鸭 2022-12-11 14:33

只对你微笑: 你好,这个问题你现在会了吗
我也不会  呜呜呜

只对你微笑 2022-8-28 10:38

mutian704_504247768: 我借鉴了你的这个作品,可是我在程序中有个报错“avicap32.h”cannot find ,我的windows中有avicap32.dll,还报错,我不知道问题出在哪里,想向你请教。如果你 ...
你好,这个问题你现在会了吗

用户377235 2016-1-27 17:00

博主您好,读了您的文章非常受益,可否将程序源代码发我一份?非常感谢。 我的邮箱:wangzi10060@163.com

sharcky 2015-2-7 16:59

你好!有可能是系统吧这个丢了,我再添加一下,如果不行,你留个邮箱我可以发给你!

sharcky 2015-2-7 16:58

差不多,简单的做了修改,然后加了一些说明,希望大家能更快的学习。

用户1825108 2015-1-7 15:50

下载不了!

用户377235 2012-11-3 12:55

好东东,好像与《LabWindows/CVI虚拟仪器测试技术及工程应用》中的例子差不多,借鉴过来的吧?

用户426357 2012-8-19 18:01

我借鉴了你的这个作品,可是我在程序中有个报错“avicap32.h”cannot find ,我的windows中有avicap32.dll,还报错,我不知道问题出在哪里,想向你请教。如果你不介意的话,你能不能用屏幕录制软件,重新完成一次这个作品发给我。(重点是界面和工程中avicap32.dll,avicap32.lib添加进工程。QQ:704232694,也可以QQ指点一下我。感激
相关推荐阅读
sharcky 2020-06-07 21:37
技术书籍分享
最近将自己一直积累收藏的一些电子书籍拿出来给大家分享一下,希望对大家有帮助!电子电路相关书籍: (1)有源滤波器的设计手册.pdf 下载地址:http://www.yimuhe.com/file...
sharcky 2020-06-07 20:57
第9节 CVI添加日历控件及操作
1、如何添加日历控件 (1)在需要添加日历控件的界面,点击鼠标右键,选择“ActiveX…”,如图3-1所示。然后进入选择外部插件的界面,如图3-2所示。 图3-1 添加外部控件 图3-...
sharcky 2020-06-07 20:52
第8节 鼠标右键实现菜单功能
(1)在主界面下,新建一个界面,菜单Create中,选择Panel..,直接就生成一个新的面板,双击新建的面板,修改参数。 图2-1 右键菜单面板参数设置界面 如图2-1所示,设置界面的名称代...
sharcky 2020-06-07 18:14
第1节 CVI实现无标题栏界面如何实现界面的移动
(1)首先需要在主界面添加一个函数,如图1所示,在Callback function 中加入主界面回调函数,命名为mainTableFunction,点击“ok”按钮确定设置。 图1 程序的主界...
sharcky 2013-03-03 13:37
放大电路的级间耦合及多级放大电路
   电子设备中所用的放大电路常将微弱的信号放大,使之成为能带动负载的有用信号。这就要求放大电路有很高的放大倍数,并能输出一定的功率。单级放大器通常是无法胜任的。通常将若干个单...
sharcky 2013-03-03 13:31
交流信号幅度的微小变化的检测,遇到问题...
1、引言:分子力学研究一个或多个分子的非键合原子的相互作用,它能够决定某种结构的空间构型或邻近分子导致的构型转变,概括地说,分子力学是分子结构、相互作用及其变化的模型,以及根据物理和物理化学第一定...
我要评论
8
22
关闭 站长推荐上一条 /2 下一条