首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

[原创]基于LabWindows/CVI的摄像头控制技术--实现屏幕截图、录像功能

[原创]基于LabWindows/CVI的摄像头控制技术--实现屏幕截图、录像功能

    我们都知道,LabWindows/CVI的强大功能实际上不只是在测控领域,在其它方面,也显示着无与伦比的优势。
    你的电脑有没有摄像头?看到别人用QQ玩视屏你会不会去想怎么实现的?
    一般来说,所有的摄像头都会包括一个AVICAP32.DLL动态链接库文件,而动态库里面必有capCreateCaptureWindow和capCreateCaptureWindowA这两个函数,我们就是利用这些函数实现图像采集的!
    这里介绍使用AVICAP32.DLL就可轻松的实现对摄像头编程,如果再加上你的网络编程水平,实现一个视屏聊天就不成什么问题了。如果电脑没有摄像头,但又想看看程序的效果,可以么?呵呵,当然可以,找个虚拟摄像头就可以搞定了,大家可以试试“SoftCam”这个软件,它是一个名副其实的软件摄像机,能模拟成为“真实的”摄像机,提醒一下各位,大家可不要用这个东东用在QQ,MSN等聊天软件上欺骗MM或GG啊。
  本例能实现图片的保存,浏览以及录像功能,在界面上都能显示出来,大家仔细瞧瞧吧!
 
  界面如下:
 
  
 
  图中的景像就是我的实验室,情况有点糟糕,哈哈,还能凑合着过!
  
 
  代码如下:
 
#include "windows.h"
#include "avicap32.h"
#include   
#include
#include "cam.h"

//设置所需要摄像头的常量
#define WM_CAP_START         WM_USER    //开始
#define WM_CAP_STOP         WM_CAP_START + 68  //停止
#define WM_CAP_DRIVER_CONNECT      WM_CAP_START + 10   //连接
#define WM_CAP_DRIVER_DISCONNECT      WM_CAP_START + 11   //断开
#define WM_CAP_SAVEDIB        WM_CAP_START + 25
#define WM_CAP_GRAB_FRAME       WM_CAP_START + 60
#define WM_CAP_SEQUENCE        WM_CAP_START + 62
#define WM_CAP_FILE_SET_CAPTURE_FILEA    WM_CAP_START + 20 //保存至文件
#define WM_CAP_SEQUENCE_NOFILE     WM_CAP_START + 63
#define WM_CAP_SET_OVERLAY      WM_CAP_START + 51
#define WM_CAP_SET_PREVIEW      WM_CAP_START + 50
#define WM_CAP_SET_CALLBACK_VIDEOSTREAM    WM_CAP_START +6
#define WM_CAP_SET_CALLBACK_ERROR     WM_CAP_START +2
#define WM_CAP_SET_CALLBACK_STATUSA    WM_CAP_START +3
#define WM_CAP_SET_CALLBACK_FRAME     WM_CAP_START +5
#define WM_CAP_SET_SCALE      WM_CAP_START+  53
#define WM_CAP_SET_PREVIEWRATE     WM_CAP_START+  52
#define WM_CAP_COPYDIB      WM_CAP_START + 30  //复制图片
//定义面板句柄
static int handle;
//定义摄像头句柄
static int result;
static int panelHandle;
int main (int argc, char *argv[])
{
 if (InitCVIRTE (0, argv, 0) == 0)
  return -1; /* out of memory */
 if ((panelHandle = LoadPanel (0, "cam.uir", PANEL)) < 0)
  return -1;
 DisplayPanel (panelHandle);
 RunUserInterface ();
 DiscardPanel (panelHandle);
 return 0;
}
//退出按钮
int CVICALLBACK QuitCallback (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 switch (event)
 {
  case EVENT_COMMIT:
   QuitUserInterface (0);
   break;
 }
 return 0;
}
//开始按钮
int CVICALLBACK startCB (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 int width;
 int height;
 int top;
 int left;
 switch (event)
 {
  case EVENT_COMMIT:
   
   //获得面板句柄
   GetPanelAttribute (panelHandle, ATTR_SYSTEM_WINDOW_HANDLE, &handle);
   
   //获得屏幕中图像要显示的位置
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_LEFT, &left);
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_TOP, &top);
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, &height);
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, &width);
   
   //打开摄像头
   result = capCreateCaptureWindowA("",WS_CHILD | WS_VISIBLE ,left,top,width,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;
}
//停止按钮
int CVICALLBACK stopCB (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 switch (event)
 {
  case EVENT_COMMIT:
   if (result != 0)
   {
    //断开连接
    SendMessage((HWND)result, WM_CAP_DRIVER_DISCONNECT, 0, 0);
   }
   break;
 }
 return 0;
}
//保存BMP按钮
int CVICALLBACK recordbmp (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
// int available;
 
 //定义BMP位图ID号
 int bitmapID;
 
 //定义文件存储路径
 char path[MAX_PATHNAME_LEN];
 //定义静态变量,设置循环次数
 static int i;
 switch (event)
 {
  case EVENT_COMMIT:
   /* 此代码为将图片存入剪切板  
   if (result != 0)
   {
    SendMessage((HWND)result, WM_CAP_GRAB_FRAME, 0, 0);
        SendMessage((HWND)result, WM_CAP_COPYDIB, 0, 0);
  
    ClipboardGetBitmap (&bitmapID, &available);
    if (available ==1)
    {
     CanvasClear (panelHandle, PANEL_CANVAS, VAL_ENTIRE_OBJECT);
     CanvasDrawBitmap (panelHandle, PANEL_CANVAS, bitmapID, VAL_ENTIRE_OBJECT, VAL_ENTIRE_OBJECT);
    }
    DiscardBitmap (bitmapID);
   }
     */
   
   //保存位图
   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;
}
//开始录像按钮
int CVICALLBACK recordstream (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 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;
}
//停止录像按钮
int CVICALLBACK stopstream (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 switch (event)
 {
  case EVENT_COMMIT:
   SendMessage((HWND)result, WM_CAP_STOP, 0, 0);
   break;
 }
 return 0;
}
//显示制式设置
int CVICALLBACK method (int panel, int control, int event,
  void *callbackData, int eventData1, int eventData2)
{
 int kind;
 int width;
 int height;
 int top;
 int left;
 switch (event)
 {
  case EVENT_COMMIT:
   
   //获得制式种类
   GetCtrlVal (panelHandle, PANEL_RING, &kind);
   switch (kind)
   {
    case 0:
     
     //160*120制式
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 160);
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 120);
     break;
    case 1:
     
     //1176*144制式
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 176);
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 144);
     break;
    case 2:
     
     //320*240制式
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 320);
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 240);
     break;
    case 3:
     
     //352*288制式
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 352);
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 288);
     break;
    case 4:
     
     //1默认制式
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 592);
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 333);
     break;
   }
   
   //获得屏幕中图像要显示的位置
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_LEFT, &left);
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_TOP, &top);
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, &height);
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, &width);
   
   //重新定位
   SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_TOP, (333-height)/2+55);
   SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_LEFT, (592-width)/2+53);
   
   //断开连接
   SendMessage((HWND)result, WM_CAP_DRIVER_DISCONNECT, 0, 0);
   
   //调用开始按钮事件
   startCB(panel, PANEL_CANVAS_TV, EVENT_COMMIT, NULL, 0, 0);
   break;
 }
 return 0;
}

挺专业的,非常想看看“庐山真面目”

能给我把做好的发过来吗?学习学习

candle-ren@sohu.com

万分感谢!

楼主太强大了,基于labwindows/cvi的USB摄像头控制系统就是我的毕业设计啊,顶。我在迷茫中看到了一点曙光,谢谢
这里介绍使用AVICAP32.DLL就可轻松的实现对摄像头编程,如果再加上你的网络编程水平,实现一个视屏聊天就不成什么问题了。如果电脑没有摄像头,但又想看看程序的效果,可以么?呵呵,当然可以,找个虚拟摄像头就可以搞定了,大家可以试试“SoftCam”这个软件,它是一个名副其实的软件摄像机,能模拟成为“真实的”摄像机,提醒一下各位,大家可不要用这个东东用在QQ,MSN等聊天软件上欺骗MM或GG啊。

     //160*120制式
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 160);
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 120);
     break    valve testing machine;
    case 1:
     
     //1176*144制式
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 176);
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 144);
     break;
    case 2:
     
     //320*240制式
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 320);
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 240);
     break;
    case 3:
     
     //352*288制式
     SetCtrlAttribute (panelHandle,Valve testing machine PANEL_CANVAS_TV, ATTR_WIDTH, 352);
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 288);
     break;
    case 4:
     
     //1默认制式
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, 592);
     SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, 333);
     break;
   }
   
   //获得屏幕中图像要显示的位置
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_LEFT, &left);
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_TOP, &top);
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_HEIGHT, &height);
   GetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_WIDTH, &width);
   
   //重新定位
   SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_TOP, (333-height)/2+55);
   SetCtrlAttribute (panelHandle, PANEL_CANVAS_TV, ATTR_LEFT, (592-width)/2+53);
哎呀呀,牛叉
如何实现在面板中实时显示两个摄像头所采集的数据
返回列表