当前位置:编程学习 > C#/ASP.NET >>

directshow 如何在录像同时抓图

directshow录像和抓图,单独进行都可以,不知道如何在图像同时抓图,望指点。
下面是部分代码


    bool SetupGraph()
    {
        int hr;
        IFileSinkFilter sink;
        IBaseFilter mux;
        try
        {
            hr = capGraph.SetFiltergraph(graphBuilder);
            if (hr < 0)
                Marshal.ThrowExceptionForHR(hr);

            hr = graphBuilder.AddFilter(capFilter, "Ds.NET Video Capture Device");
            if (hr < 0)
                Marshal.ThrowExceptionForHR(hr);

            DsUtils.ShowCapPinDialog(capGraph, capFilter, this.Handle);

            AMMediaType media = new AMMediaType();
            media.majorType = MediaType.Video;
            media.subType = MediaSubType.RGB24;
            media.formatType = FormatType.VideoInfo;
            hr = sampGrabber.SetMediaType(media);
            if (hr < 0)
                Marshal.ThrowExceptionForHR(hr);

            hr = graphBuilder.AddFilter(baseGrabFlt, "Ds.NET Grabber");
            if (hr < 0)
                Marshal.ThrowExceptionForHR(hr);
            Guid cat;
            Guid med;

            cat = PinCategory.Preview;
            med = MediaType.Video;
            hr = capGraph.RenderStream(ref cat, ref med, capFilter, null, null);  
            if (hr < 0)
                Marshal.ThrowExceptionForHR(hr);

            cat = MediaSubType.Avi;

            // hr = capGraph.SetOutputFileName(ref cat, "c:\\323.avi", out baseGrabFlt, out sink);   //当这句运行的话,后面后有异常,看红色字体
            if (hr < 0)
                Marshal.ThrowExceptionForHR(hr);

            cat = PinCategory.Capture;
            med = MediaType.Video;
            hr = capGraph.RenderStream(ref cat, ref med, capFilter, null, baseGrabFlt); 
            if (hr < 0)
                Marshal.ThrowExceptionForHR(hr);

            media = new AMMediaType();
            hr = sampGrabber.GetConnectedMediaType(media);   //当捕获视频录像时,此处会有异常

            if (hr < 0)
                Marshal.ThrowExceptionForHR(hr);
            if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero))
                throw new NotSupportedException("Unknown Grabber Media Format");

            videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader));
            Marshal.FreeCoTaskMem(media.formatPtr); media.formatPtr = IntPtr.Zero;

            hr = sampGrabber.SetBufferSamples(false);
            if (hr == 0)
                hr = sampGrabber.SetOneShot(false);
            if (hr == 0)
                hr = sampGrabber.SetCallback(null, 0);
            if (hr < 0)
                Marshal.ThrowExceptionForHR(hr);

            return true;
        }
        catch (Exception ee)
        {
            MessageBox.Show(this, "Could not setup graph\r\n" + ee.Message, "test", MessageBoxButtons.OK, MessageBoxIcon.Stop);
            return false;
        }
    } directshow 如何在录像同时抓图 directshow  录像同时抓图 --------------------编程问答-------------------- 顶起来,请大神们帮帮忙 --------------------编程问答-------------------- 还没有解决,再顶 --------------------编程问答-------------------- 你这个是事先设置好视频录像文件或者抓图文件的。


如果是触发式的,你这个办法就不行了。
在 sampGrabber.SetCallback里设置一个回调函数,
当从摄像头读取数据的时候,会触发这个事件,这个事件里就有你要的图像数据,把它保存了就可以实现抓图的功能了。

如果是触发式录像和抓图,都可以在这个回调函数里做。 --------------------编程问答-------------------- 可不可以在录像的时候就直接调用抓图方法呢 --------------------编程问答--------------------
引用 3 楼 mjp1234airen4385 的回复:
你这个是事先设置好视频录像文件或者抓图文件的。


如果是触发式的,你这个办法就不行了。
在 sampGrabber.SetCallback里设置一个回调函数,
当从摄像头读取数据的时候,会触发这个事件,这个事件里就有你要的图像数据,把它保存了就可以实现抓图的功能了。

如果是触发式录像和抓图,都可以在这个回调函数里做。


抓图是在回调函数里面做的,

/// <summary> buffer callback, COULD BE FROM FOREIGN THREAD. </summary>
int ISampleGrabberCB.BufferCB( double SampleTime, IntPtr pBuffer, int BufferLen )
{
if( captured || (savedArray == null) )
{
Trace.WriteLine( "!!CB: ISampleGrabberCB.BufferCB" );
return 0;
}

captured = true;
bufferedSize = BufferLen;
Trace.WriteLine( "!!CB: ISampleGrabberCB.BufferCB  !GRAB! size = " + BufferLen.ToString() );
if( (pBuffer != IntPtr.Zero) && (BufferLen > 1000) && (BufferLen <= savedArray.Length) )
Marshal.Copy( pBuffer, savedArray, 0, BufferLen );
else
Trace.WriteLine( "    !!!GRAB! failed " );
this.BeginInvoke( new CaptureDone( this.OnCaptureDone ) );
return 0;
}


void OnCaptureDone()
{
Trace.WriteLine( "!!DLG: OnCaptureDone" );
try {
toolBarBtnGrab.Enabled = true;
int hr;
if( sampGrabber == null )
return;
hr = sampGrabber.SetCallback( null, 0 );

int w = videoInfoHeader.BmiHeader.Width;
int h = videoInfoHeader.BmiHeader.Height;
if( ((w & 0x03) != 0) || (w < 32) || (w > 4096) || (h < 32) || (h > 4096) )
return;
int stride = w * 3;

GCHandle handle = GCHandle.Alloc( savedArray, GCHandleType.Pinned );
int scan0 = (int) handle.AddrOfPinnedObject();
scan0 += (h - 1) * stride;
Bitmap b = new Bitmap( w, h, -stride, PixelFormat.Format24bppRgb, (IntPtr) scan0 );
handle.Free();
savedArray = null;
Image old = pictureBox.Image;
pictureBox.Image = b;
if( old != null )
old.Dispose();
toolBarBtnSave.Enabled = true;
}
catch( Exception ee )
{
MessageBox.Show( this, "Could not grab picture\r\n" + ee.Message, "DirectShow.NET", MessageBoxButtons.OK, MessageBoxIcon.Stop );
}
}

回调函数中如何录像?请指点 --------------------编程问答-------------------- Bitmap b = new Bitmap( w, h, -stride, PixelFormat.Format24bppRgb, (IntPtr) scan0 );


这个就是你已经找到的图片,如果把这个图片每一的张都写入一个avi文件里,就是你的录像了。
C#把图片生成avi的代码,你在网上找找,有现成。
以前把C#写avi的代码改成了一个delphi写avi的代码,反而找不到C#的代码了,不然就直接给你发了。

利用网上那个代码写成的avi文件很大,需要在写入的时候自己做压缩编码。
以前使用的是微软的mp4压缩格式免费的编码器,效果不错。
下面的资源,你看看
http://download.csdn.net/detail/mjp1234airen4385/3607954
补充:.NET技术 ,  C#
CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,