摄像头视频采集----基于AviCap

2 篇文章 0 订阅
1 篇文章 0 订阅

         相对DirectShow,AviCap算是视频采集框架里面的老前辈了,虽然已经有点力不从心,但对一些要求不高的场合还是很实用的,网上一番搜索之后(借鉴了很多现成的轮子),实现了一个基于AviCap的摄像头采集程序(C sharp实现):


先实现一个CapVideo的类,主要是引入avicap提供的接口,结构体及一些方法的定义

其中主要用到了Avicap32.dll中提供的以下三个函数:

capCreateCaptureWindowA:创建一个视频显示窗口

capGetDriverDescriptionA:获取视频设备描述符

capGetVideoFormat:获取视频格式

   public class CapVideo
    {
        #region DLL Import Method
        [DllImport("avicap32.dll")]
        public static extern IntPtr capCreateCaptureWindowA(byte[] lpszWindowName, int dwStyle, int x, int y, int nWidth, int nHeight, IntPtr hWndParent, int nID);
        [DllImport("avicap32.dll")]
        public static extern bool capGetDriverDescriptionA(short wDriver, byte[] lpszName, int cbName, byte[] lpszVer, int cbVer);
        [DllImport("avicap32.dll")]
        public static extern int capGetVideoFormat(IntPtr hWnd, IntPtr psVideoFormat, int wSize);
        [DllImport("User32.dll")]
        public static extern bool SendMessage(IntPtr hWnd, int wMsg, bool wParam, int lParam);
        [DllImport("User32.dll")]
        public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, int lParam);
        [DllImport("User32.dll")]
        public static extern bool SendMessage(IntPtr hWnd, int wMsg, short wParam, FrameEventHandler lParam);
        [DllImport("User32.dll")]
        public static extern bool SendMessage(IntPtr hWnd, int wMsg, int wParam, ref BITMAPINFO lParam);
        [DllImport("User32.dll")]
        public static extern int SetWindowPos(IntPtr hWnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);
        #endregion 

        #region public const Fields
        public const int WM_USER = 0x400;
        public const int WS_CHILD = 0x40000000;
        public const int WS_VISIBLE = 0x10000000;
        public const int SWP_NOMOVE = 0x2;
        public const int SWP_NOZORDER = 0x4;
        public const int WM_CAP_DRIVER_CONNECT = WM_USER + 10;
        public const int WM_CAP_DRIVER_DISCONNECT = WM_USER + 11;
        public const int WM_CAP_SET_CALLBACK_FRAME = WM_USER + 5;
        public const int WM_CAP_SET_PREVIEW = WM_USER + 50;
        public const int WM_CAP_SET_PREVIEWRATE = WM_USER + 52;
        public const int WM_CAP_SET_VIDEOFORMAT = WM_USER + 45;
        public const int WM_CAP_GRAB_FRAME_NOSTOP = WM_USER + 61;
        public const int WM_CAP_GRAB_FRAME = WM_USER + 60;
        public const int WM_CAP_FILE_SAVEDIBA = WM_USER + 25;
        #endregion

        #region Structures
        [StructLayout(LayoutKind.Sequential)]
        public struct VIDEOHDR
        {
            [MarshalAs(UnmanagedType.I4)]
            public int lpData;
            [MarshalAs(UnmanagedType.I4)]
            public int dwBufferLength;
            [MarshalAs(UnmanagedType.I4)]
            public int dwBytesUsed;
            [MarshalAs(UnmanagedType.I4)]
            public int dwTimeCaptured;
            [MarshalAs(UnmanagedType.I4)]
            public int dwUser;
            [MarshalAs(UnmanagedType.I4)]
            public int dwFlags;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            public int[] dwReserved;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct BITMAPINFOHEADER
        {
            [MarshalAs(UnmanagedType.I4)]
            public Int32 biSize;
            [MarshalAs(UnmanagedType.I4)]
            public Int32 biWidth;
            [MarshalAs(UnmanagedType.I4)]
            public Int32 biHeight;
            [MarshalAs(UnmanagedType.I2)]
            public short biPlanes;
            [MarshalAs(UnmanagedType.I2)]
            public short biBitCount;
            [MarshalAs(UnmanagedType.I4)]
            public Int32 biCompression;
            [MarshalAs(UnmanagedType.I4)]
            public Int32 biSizeImage;
            [MarshalAs(UnmanagedType.I4)]
            public Int32 biXPelsPerMeter;
            [MarshalAs(UnmanagedType.I4)]
            public Int32 biYPelsPerMeter;
            [MarshalAs(UnmanagedType.I4)]
            public Int32 biClrUsed;
            [MarshalAs(UnmanagedType.I4)]
            public Int32 biClrImportant;
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct BITMAPINFO
        {
            [MarshalAs(UnmanagedType.Struct, SizeConst = 40)]
            public BITMAPINFOHEADER bmiHeader;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 1024)]
            public Int32[] bmiColors;
        }
        #endregion

        #region Public Method
        public delegate void FrameEventHandler(IntPtr lwnd, IntPtr lpVHdr);

        public static object GetStructure(IntPtr ptr, ValueType structure)
        {
            return Marshal.PtrToStructure(ptr, structure.GetType());
        }

        public static object GetStructure(int ptr, ValueType structure)
        {
            return GetStructure(new IntPtr(ptr), structure);
        }

        public static void Copy(IntPtr ptr, byte[] data)
        {
            Marshal.Copy(ptr, data, 0, data.Length);
        }

        public static void Copy(int ptr, byte[] data)
        {
            Copy(new IntPtr(ptr), data);
        }

        public static int SizeOf(object structure)
        {
            return Marshal.SizeOf(structure);
        }
        #endregion
    }


接着实现一个Camera类,主要实现摄像头采集开始,停止,截图等功能。

    public class Camera
    {
        
        public Camera(IntPtr handle, int width, int height)
        {
            mControlPtr = handle;
            mWidth = width;
            mHeight = height;
        }

        //定义委托
        public delegate void RecievedFrameEventHandler(byte[] data);
        public event RecievedFrameEventHandler RecievedFrame;

        private IntPtr lwndC; 
        private IntPtr mControlPtr; 
        private int mWidth;
        private int mHeight;

        private CapVideo.FrameEventHandler mFrameEventHandler;

        #region Camera Operation

        //开始采集
        public bool StartCamera()
        {
            byte[] lpszName = new byte[100];
            byte[] lpszVer = new byte[100];
            
            //获取设备信息
            CapVideo.capGetDriverDescriptionA(0, lpszName, 100, lpszVer, 100);
            //创建捕获窗口
            this.lwndC = CapVideo.capCreateCaptureWindowA(lpszName, CapVideo.WS_VISIBLE + CapVideo.WS_CHILD, 0, 0, mWidth, mHeight, mControlPtr, 0);

            //连接设备
            if (this.capDriverConnect(this.lwndC, 0))
            {
                //设置为预览模式,初始帧率为60
                this.capPreview(this.lwndC, true);
                this.capPreviewRate(this.lwndC, 60);
              
                //BitMap及其头信息
                CapVideo.BITMAPINFO bitmapinfo = new CapVideo.BITMAPINFO();
                bitmapinfo.bmiHeader.biSize = CapVideo.SizeOf(bitmapinfo.bmiHeader);
                bitmapinfo.bmiHeader.biWidth = 400;
                bitmapinfo.bmiHeader.biHeight = 200;
                bitmapinfo.bmiHeader.biPlanes = 1;
                bitmapinfo.bmiHeader.biBitCount = 24;

                //设置视频参数
                this.capSetVideoFormat(this.lwndC, ref bitmapinfo, CapVideo.SizeOf(bitmapinfo));

                //注册回调
                this.mFrameEventHandler = new CapVideo.FrameEventHandler(FrameCallBack);
                this.capSetCallbackOnFrame(this.lwndC, this.mFrameEventHandler);

                //设置窗口
                CapVideo.SetWindowPos(this.lwndC, 0, 0, 0, mWidth, mHeight, 6);
                return true;
            }
            else
            {
                return false;
            }
        }
       

        //停止采集
        public void CloseCamera()
        {
            this.capDriverDisconnect(this.lwndC);
        }

        //快照
        public bool SnapShot(string str)
        {
            bool blRes = CapVideo.SendMessage(this.lwndC, CapVideo.WM_CAP_GRAB_FRAME_NOSTOP, 0, 0);
            if ( !blRes )
            {
                return blRes;
            }
            IntPtr ptr = Marshal.StringToHGlobalAnsi(str);
            return CapVideo.SendMessage(this.lwndC,CapVideo.WM_CAP_FILE_SAVEDIBA,0,ptr.ToInt32());
            Marshal.FreeHGlobal(ptr);

        }

        //收到帧数据时会执行此回调函数
        private void FrameCallBack(IntPtr lwnd, IntPtr lpVHdr)
        {
            CapVideo.VIDEOHDR videoHeader = new CapVideo.VIDEOHDR();
            byte[] VideoData;
            //获取帧头信息图像数据地址
            videoHeader = (CapVideo.VIDEOHDR)CapVideo.GetStructure(lpVHdr, videoHeader);
            VideoData = new byte[videoHeader.dwBytesUsed];
            //复制图像数据
            CapVideo.Copy(videoHeader.lpData, VideoData);
            if (this.RecievedFrame != null)
                this.RecievedFrame(VideoData);
        }

        //连接设备
        private bool capDriverConnect(IntPtr lwnd, short i)
        {
            return CapVideo.SendMessage(lwnd, CapVideo.WM_CAP_DRIVER_CONNECT, i, 0);
        }

        //断开连接
        private bool capDriverDisconnect(IntPtr lwnd)
        {
            return CapVideo.SendMessage(lwnd, CapVideo.WM_CAP_DRIVER_DISCONNECT, 0, 0);
        }

        //设置为预览模式
        private bool capPreview(IntPtr lwnd, bool f)
        {
            return CapVideo.SendMessage(lwnd, CapVideo.WM_CAP_SET_PREVIEW, f, 0);
        }

        //设置预览帧率
        private bool capPreviewRate(IntPtr lwnd, short wMS)
        {
            return CapVideo.SendMessage(lwnd, CapVideo.WM_CAP_SET_PREVIEWRATE, wMS, 0);
        }

        //设置回调函数
        private bool capSetCallbackOnFrame(IntPtr lwnd, CapVideo.FrameEventHandler lpProc)
        {
            return CapVideo.SendMessage(lwnd, CapVideo.WM_CAP_SET_CALLBACK_FRAME, 0, lpProc);
        }

        //设置视频格式
        private bool capSetVideoFormat(IntPtr hCapWnd, ref CapVideo.BITMAPINFO BmpFormat, int CapFormatSize)
        {
            return CapVideo.SendMessage(hCapWnd, CapVideo.WM_CAP_SET_VIDEOFORMAT, CapFormatSize, ref BmpFormat);
        }
        #endregion

    }


接下来就是演示例子,编写一个简单的WPF程序,利用以上代码实现摄像头采集,运行结果如下,画质不是很清楚,比起摄像头自带的软件,完全下降了两个档次,具体原因有待调查,不过利用AviCap来实现还是很节省资源的,采集时看了下CPU使用率,不超过5%。整个工程已上传至我的资源里,需要参考的朋友可以点击这里下载,另外后续想将摄像头分辨率调节的功能添加进去。





vfp9.0调用API制作照相软件实例 PUBLIC WM_CAP_DRIVER_DISCONNECT PUBLIC hwndc,WM_CAP_SAVEDIB,WM_CAP_FILE_SET_CAPTURE_FILEA,WM_CAP_SEQUENCE,WM_CAP_STOP DECLARE INTEGER capCreateCaptureWindowA IN "AVICAP32.DLL" STRING lpszWindowName ,INTEGER dwStyle , INTEGER x, INTEGER Y, INTEGER nWidth ,INTEGER nHeight,INTEGER ParentWin,INTEGER nId DECLARE INTEGER SendMessage IN "user32" INTEGER HWND, INTEGER wmsg,INTEGER wpar1, INTEGER wpar2 DECLARE INTEGER SendMessage IN "user32" AS SendMessageA INTEGER HWND, INTEGER wmsg,INTEGER wpar1, STRING wpar2 *!* 显示: WM_USER = 1024 WM_CAP_START = WM_USER WM_CAP_STOP = WM_CAP_START + 68 WM_CAP_DRIVER_CONNECT = WM_CAP_START + 10 WM_CAP_DRIVER_DISCONNECT = WM_CAP_START + 11 WM_CAP_SAVEDIB = WM_CAP_START + 25 WM_CAP_GRAB_FRAME = WM_CAP_START + 60 WM_CAP_SEQUENCE = WM_CAP_START + 62 WM_CAP_FILE_SET_CAPTURE_FILEA = WM_CAP_START + 20 WM_CAP_SEQUENCE_NOFILE =WM_CAP_START+ 63 WM_CAP_SET_OVERLAY =WM_CAP_START+ 51 WM_CAP_SET_PREVIEW =WM_CAP_START+ 50 WM_CAP_SET_CALLBACK_VIDEOSTREAM = WM_CAP_START +6 WM_CAP_SET_CALLBACK_ERROR=WM_CAP_START +2 WM_CAP_SET_CALLBACK_STATUSA= WM_CAP_START +3 WM_CAP_SET_CALLBACK_FRAME= WM_CAP_START +5 WM_CAP_SET_SCALE=WM_CAP_START+ 53 WM_CAP_SET_PREVIEWRATE=WM_CAP_START+ 52 hWndC = capCreateCaptureWindowA('My Own Capture Window',1342177280,0,0,200,150,THISFORM.HWND ,0) &&显示大小 IF hWndC 0 SendMessage(hWndC, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, 0) SendMessage(hWndC, WM_CAP_SET_CALLBACK_ERROR, 0, 0) SendMessage(hWndC, WM_CAP_SET_CALLBACK_STATUSA, 0, 0) SendMessage(hWndC, WM_CAP_DRIVER_CONNECT, 0, 0) SendMessage(hWndC, WM_CAP_SET_SCALE, 1, 0) SendMessage(hWndC, WM_CAP_SET_PREVIEWRATE, 66, 0) SendMessage(hWndC, WM_CAP_SET_OVERLAY, 1, 0) SendMessage(hWndC, WM_CAP_SET_PREVIEW, 1, 0) * THISFORM.ACTIVATE ENDIF
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值