C# 捕获摄像头的每一帧图像

public void CaptureVideo()
    {
      int hr = 0;
      IBaseFilter sourceFilter = null;

      try
      {
        // Get DirectShow interfaces
        GetInterfaces();

        // Attach the filter graph to the capture graph
        hr = this.captureGraphBuilder.SetFiltergraph(this.graphBuilder);
        DsError.ThrowExceptionForHR(hr);

        // Use the system device enumerator and class enumerator to find
        // a video capture/preview device, such as a desktop USB video camera.
        sourceFilter = FindCaptureDevice();

        ISampleGrabber sampGrabber = new SampleGrabber() as ISampleGrabber;

        hr = sampGrabber.SetOneShot(false);
        hr = sampGrabber.SetBufferSamples(true);
        DsError.ThrowExceptionForHR(hr);
        ConfigureSampleGrabber(sampGrabber);
        IBaseFilter baseGrabFlt = sampGrabber as IBaseFilter;

        // Add Capture filter to our graph.
        hr = this.graphBuilder.AddFilter(sourceFilter, "Video Capture");
        DsError.ThrowExceptionForHR(hr);
        hr = this.graphBuilder.AddFilter(baseGrabFlt, "SampleGrabber");
        DsError.ThrowExceptionForHR(hr);
 
        // Render the preview pin on the video capture filter
        // Use this instead of this.graphBuilder.RenderFile
     // 在这会返回一个错误,hr的值为262782.不知道如果解决.
        hr = this.captureGraphBuilder.RenderStream(PinCategory.Preview, MediaType.Video, sourceFilter, baseGrabFlt, null);

        DsError.ThrowExceptionForHR(hr);

        // Now that the filter has been added to the graph and we have
        // rendered its stream, we can release this reference to the filter.
        Marshal.ReleaseComObject(sourceFilter);

        // Set video window style and position
        SetupVideoWindow();

        // Add our graph to the running object table, which will allow
        // the GraphEdit application to "spy" on our graph
        rot = new DsROTEntry(this.graphBuilder);

        // Start previewing video data
        hr = this.mediaControl.Run();
        DsError.ThrowExceptionForHR(hr);

        // Remember current state
        this.currentState = PlayState.Running;
      }
      catch
      {
        MessageBox.Show("An unrecoverable error has occurred.");
      }
    }


 

    ///  buffer callback, COULD BE FROM FOREIGN THREAD. 
    int ISampleGrabberCB.BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
    {
        Graphics g;
        String s;
        float sLeft;
        float sTop;
        SizeF d;

        g = Graphics.FromImage(bitmapOverlay);
        g.Clear(System.Drawing.Color.Transparent);
        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

        // Prepare to put the specified string on the image
        g.DrawRectangle(System.Drawing.Pens.Blue, 0, 0, this.Width  - 1, this.Height  - 1);
        g.DrawRectangle(System.Drawing.Pens.Blue, 1, 1, this.Width  - 3, this.Height  - 3);

        d = g.MeasureString(m_String, fontOverlay);

        sLeft = (this.Width  - d.Width) / 2;
        sTop = (this.Height  - d.Height) / 2;

        g.DrawString(m_String, fontOverlay, System.Drawing.Brushes.Red,
            sLeft, sTop, System.Drawing.StringFormat.GenericTypographic);

        // Add a frame number in the bottom right
        s = "Frame " + m_Count.ToString();
        d = g.MeasureString(s, transparentFont);
        sLeft = (this.Width  - d.Width) - 10;
        sTop = (this.Height  - d.Height) - 10;

        g.DrawString(s, transparentFont, transparentBrush, sLeft, sTop,
            System.Drawing.StringFormat.GenericTypographic);
        g.Dispose();

        // need to flip the bitmap so it's the same orientation as the
        // video buffer
        bitmapOverlay.RotateFlip(RotateFlipType.RotateNoneFlipY);

        // create and copy the video's buffer image to a bitmap
        Bitmap v;
        v = new Bitmap(this.Width , this.Height , m_stride, PixelFormat.Format32bppArgb, pBuffer);
        g = Graphics.FromImage(v);
        g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

        // draw the overlay bitmap over the video's bitmap
        g.DrawImage(bitmapOverlay, 0, 0, bitmapOverlay.Width, bitmapOverlay.Height);

        // dispose of the various objects
        g.Dispose();
        v.Dispose();

        // Increment frame number.  Done this way, frame are zero indexed.
        m_Count++;

        return 0;
    }


 

    ///  Set the options on the sample grabber 
    private void ConfigureSampleGrabber(ISampleGrabber sampGrabber)
    {
        AMMediaType media;
        int hr;

        // Set the media type to Video/RBG24
        media = new AMMediaType();
        media.majorType = MediaType.Video;
        media.subType = MediaSubType.ARGB32;
        media.formatType = FormatType.VideoInfo;

        hr = sampGrabber.SetMediaType(media);
        DsError.ThrowExceptionForHR(hr);

        DsUtils.FreeAMMediaType(media);
        media = null;

        hr = sampGrabber.SetCallback(this, 1);
        DsError.ThrowExceptionForHR(hr);
    }

 

 	void SetupBitmap()
        {
            int fSize;

            // scale the font size in some portion to the video image
            fSize = 9 * (this.Width  / 64);
            bitmapOverlay = new Bitmap(this.Width , this.Height ,
                System.Drawing.Imaging.PixelFormat.Format32bppArgb);
            fontOverlay = new Font("Times New Roman", fSize, System.Drawing.FontStyle.Bold,
                System.Drawing.GraphicsUnit.Point);

            // scale the font size in some portion to the video image
            fSize = 5 * (this.Width  / 64);
            transparentFont = new Font("Tahoma", fSize, System.Drawing.FontStyle.Bold,
                System.Drawing.GraphicsUnit.Point);
            transparentBrush = new SolidBrush(Color.FromArgb(96, 0, 0, 255));
        }


 

	下面是叠加字符的方法
	/// 
	/// buffer callback, COULD BE FROM FOREIGN THREAD.
	/// 
	/// The sample time.
	/// The p buffer.
	/// The buffer len.
	/// 
	int ISampleGrabberCB.BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
	{
		// Note that we depend on only being called once per call to Click. Otherwise
		// a second call can overwrite the previous image.
		Debug.Assert(BufferLen == Math.Abs(stride)*videoHeight, "Incorrect buffer length");

		if (imageLogo != null || stringLogo != null)
		{
			//获取帧图片。	
			Bitmap frameImage = new Bitmap(videoWidth, videoHeight, stride, PixelFormat.Format24bppRgb, pBuffer);
			Graphics g = Graphics.FromImage(frameImage);
			g.SmoothingMode = SmoothingMode.AntiAlias;

			//帧图片的坐标原点为左下角,GDI+的坐标原点为左上角,需要变换全局坐标系。
			System.Drawing.Drawing2D.Matrix matrix = new System.Drawing.Drawing2D.Matrix(1, 0, 0, -1, 0, 0);
			g.Transform = matrix;
			g.TranslateTransform(0, -videoHeight);

			//设置字符所处的位置。
			if (imageLogo != null)
			{
				g.DrawImage(imageLogo, imagePosition.X, imagePosition.Y);
			}
			if (stringLogo != null)
			{
				g.DrawImage(stringLogo, stringPosition.X, stringPosition.Y);
			}
			//释放设备管理器和帧图片的内存。
			g.Dispose();
			frameImage.Dispose();
		}
		return 0;
	}

你可能感兴趣的:(DirectShow,c#)