none
请教一个关于实现后台操作摄像头拍照截图的问题。 RRS feed

  • 问题

  • 我是个学生,正在做一个摄像头动作识别系统,现在已经基本完成得差不多。
    但是现在有点遇到瓶颈了。

    简单说一下我想实现的效果,我举个简化了的例子说明一下:用户打开我写的摄像头动作识别系统,设置一下,把向下设置为虚拟的“PageDown”这个按键,然后点击“开始识别”,摄像头动作识别软件就会自动缩小到任务栏的托盘里,然后我们把焦点定在一个文档窗口时,向下挥一挥手,该文档窗口就会自动向下翻一页。

    我的摄像头识别系统的基本原理是:把摄像头获取的影像在一个容器控件里面显示出来,然后根据利用截图的功能不断截图,然后根据截下来的多帧图片判断用户的动作。
    现在遇到的问题是:目前只有显示影像的那个容器控件在屏幕上没有被完全遮掩住的时候,动作识别功能才能运行。其实归根结底就是,当那个容器控件被其他东西完全遮掩住,一点都看不见的时候,截图功能就没用了,这样导致整个动作识别都没法子正常运行。

    各位高手有没有什么方法可以实现不用把摄像头获取的影像全部像监控那样一直播放出来,也能随时按需要利用摄像头像拍照那样截图吗?或者说,有没有什么方法能使我那个程序在缩小到任务栏托盘的情况下还能正常运行?

    谢谢指教了!

    2009年8月17日 8:42

答案

  • 关于DXSnap的问题可以去http://sourceforge.net/forum/forum.php?forum_id=460697提问。
    如果你不需要支持Windows 200的话,可以用WIA接口。WIA的脚本接口任何支持COM的语言都可以调用。参考http://blogs.msdn.com/coding4fun/archive/2006/10/31/912546.aspx。
    如果你还需要支持Windows 98,建议至少升级到DirectShow 6.0。DirectShow没有脚本接口,建议像WIA那样用C++写一个脚本接口给托管程序用。

    VFW是DirectShow的前身,现在已经没有单独的讨论区讨论VFW了。如果你确实需要VFW方面的帮助,可以去microsoft.public.win32.programmer.mmedia新闻组。


    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月18日 16:34
    版主

全部回复

  • 下面我贴的这段代码是我利用来实现这个动作识别系统的基础,我上面所说的功能的基础都是这段代码里面的那个截图功能。(其实这段代码就是一个常规的摄像头软件,有开始监视和截图功能。)

            private int hHwnd;
            private const int port = 2000;

            public struct videohdr_tag
            {
                public byte[] lpData;
                public int dwBufferLength;
                public int dwBytesUsed;
                public int dwTimeCaptured;
                public int dwUser;
                public int dwFlags;
                public int[] dwReserved;
            }

            public delegate bool CallBack(int hwnd, int lParam);
            //<summary>
            //必需的设计器变量。
            //</summary>
            //private System.ComponentModel.Container components = null;
            [DllImport("avicap32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
            public static extern int capCreateCaptureWindowA([MarshalAs(UnmanagedType.VBByRefStr)]   ref   string lpszWindowName, int dwStyle, int x, int y, int nWidth, short nHeight, int hWndParent, int nID);
            [DllImport("avicap32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
            public static extern bool capGetDriverDescriptionA(short wDriver, [MarshalAs(UnmanagedType.VBByRefStr)]   ref   string lpszName, int cbName, [MarshalAs(UnmanagedType.VBByRefStr)]   ref   string lpszVer, int cbVer);
            [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
            public static extern bool DestroyWindow(int hndw);
            [DllImport("user32", EntryPoint = "SendMessageA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
            public static extern int SendMessage(int hwnd, int wMsg, int wParam, [MarshalAs(UnmanagedType.AsAny)]   object lParam);
            [DllImport("user32", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
            public static extern int SetWindowPos(int hwnd, int hWndInsertAfter, int x, int y, int cx, int cy, int wFlags);
            [DllImport("vfw32.dll")]
            public static extern string capVideoStreamCallback(int hwnd, videohdr_tag videohdr_tag);
            [DllImport("vicap32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
            public static extern bool capSetCallbackOnFrame(int hwnd, string s);

            private void OpenCapture()
            {
                int intWidth = this.panelCamera.Width;
                int intHeight = this.panelCamera.Height;
                int intDevice = 0;
                string refDevice = intDevice.ToString();
                //创建视频窗口并得到句柄
                hHwnd = FormCamera.capCreateCaptureWindowA(ref refDevice, 1342177280, 0, 0, 640, 480, this.panelCamera.Handle.ToInt32(), 0);
                if (FormCamera.SendMessage(hHwnd, 0x40a, intDevice, 0) > 0)
                {
                    FormCamera.SendMessage(this.hHwnd, 0x435, -1, 0);
                    FormCamera.SendMessage(this.hHwnd, 0x434, 0x42, 0);
                    FormCamera.SendMessage(this.hHwnd, 0x432, -1, 0);
                    FormCamera.SetWindowPos(this.hHwnd, 1, 0, 0, intWidth, intHeight, 6);
                }
                else
                {
                    FormCamera.DestroyWindow(this.hHwnd);
                }
            }

            //开始监视
            private void buttonStart_Click(object sender, EventArgs e)
            {
                this.OpenCapture();
            }

            //停止监视
            private void buttonStop_Click(object sender, EventArgs e)
            {
                //停止视频注销视频句柄
                FormCamera.SendMessage(this.hHwnd, 0x40b, 0, 0);
                FormCamera.DestroyWindow(this.hHwnd);
            }

            //截图
            private void buttonCapture_Click(object sender, EventArgs e)
            {
                try
                {
                    FormCamera.SendMessage(this.hHwnd, 0x41e, 0, 0);
                    IDataObject objImage = Clipboard.GetDataObject();
                    if (objImage.GetDataPresent(typeof(Bitmap)))
                    {
                        Image imageCapture = (Image)objImage.GetData(typeof(Bitmap));
                        SaveFileDialog saveFileDialogCapture = new SaveFileDialog();
                        saveFileDialogCapture.FileName = DateTime.Now.ToString("yyyyMMddhhmmss");
                        saveFileDialogCapture.Filter = "Image Files(*.jpg;*.jpeg)|*.jpg;*.jpeg|All files (*.*)|*.*";
                        if (saveFileDialogCapture.ShowDialog() == DialogResult.OK)
                        {
                            imageCapture.Save(saveFileDialogCapture.FileName, ImageFormat.Jpeg);
                        }
                    }
                }
                catch
                {
                }
            }

    2009年8月17日 8:42
  • 得看摄像头支持什么接口。一般摄像头支持DirectShow,支持windows 3.2和Windows 95的一般也支持VFW,支持Windows XP的一般也支持WIA。你的代码用的是VFW,现在很少人用。

    如果你用DirectShow的话,可以参考DirectShow SDK里面的amcap示例。

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月17日 13:48
    版主
  • 得看摄像头支持什么接口。一般摄像头支持DirectShow,支持windows 3.2和Windows 95的一般也支持VFW,支持Windows XP的一般也支持WIA。你的代码用的是VFW,现在很少人用。

    如果你用DirectShow的话,可以参考DirectShow SDK里面的amcap示例。

    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP

    能详细给段代码么?
    单单是一个拍照的代码块应该很短吧?
    2009年8月17日 14:38
  • http://directshownet.sourceforge.net/
    这上面的示例中的DxSnap怎么编译的时候会出错啊?
    其他的明明都没问题的.....
    我需要的就是这个啊..........
    2009年8月18日 13:16
  • 我是个学生,正在用C#做一个摄像头动作识别系统,现在已经基本完成得差不多。
    但是现在有点遇到瓶颈了。

    简单说一下我想实现的效果,我举个简化了的例子说明一下:用户打开我写的摄像头动作识别系统,设置一下,把向下设置为虚拟的“PageDown”这个按键,然后点击“开始识别”,摄像头动作识别软件就会自动缩小到任务栏的托盘里,然后我们把焦点定在一个文档窗口时,向下挥一挥手,该文档窗口就会自动向下翻一页。

    我的摄像头识别系统的基本原理是:把摄像头获取的影像在一个容器控件里面显示出来,然后根据利用截图的功能不断截图,然后根据截下来的多帧图片判断用户的动作。
    现在遇到的问题是:目前只有显示影像的那个容器控件在屏幕上没有被完全遮掩住的时候,动作识别功能才能运行。其实归根结底就是,当那个容器控件被其他东西完全遮掩住,一点都看不见的时候,截图功能就没用了,这样导致整个动作识别都没法子正常运行。

    各位高手有没有什么方法可以实现不用把摄像头获取的影像全部像监控那样一直播放出来,也能随时按需要利用摄像头像拍照那样截图吗?或者说,有没有什么方法能使我那个程序在缩小到任务栏托盘的情况下还能正常运行?

    谢谢指教了!

    注:我现在用的是VFW,因为我根本找不到DirectShow的C#版摄像头拍照程序代码来学习,所以请知道哪里有程序示例的高人也指点指点。谢谢。

    注2:http://directshownet.sourceforge.net/
    上面的DxSnap示例编译的时候会出错,其他示例明明都没问题的.....这是我找到的唯一一个示例,结果.....

    注3:其实这帖子我之前发过一次了,没注意注明是C#的,被版主转到 .NET Framework 一般性问题讨论区 了。

    2009年8月18日 13:25
  • 关于DXSnap的问题可以去http://sourceforge.net/forum/forum.php?forum_id=460697提问。
    如果你不需要支持Windows 200的话,可以用WIA接口。WIA的脚本接口任何支持COM的语言都可以调用。参考http://blogs.msdn.com/coding4fun/archive/2006/10/31/912546.aspx。
    如果你还需要支持Windows 98,建议至少升级到DirectShow 6.0。DirectShow没有脚本接口,建议像WIA那样用C++写一个脚本接口给托管程序用。

    VFW是DirectShow的前身,现在已经没有单独的讨论区讨论VFW了。如果你确实需要VFW方面的帮助,可以去microsoft.public.win32.programmer.mmedia新闻组。


    Please mark the post answered your question as the answer, and mark other helpful posts as helpful.
    Visual C++ MVP
    2009年8月18日 16:34
    版主