C# 如何使用SharpDX从网络摄像头捕获帧

C# 如何使用SharpDX从网络摄像头捕获帧,c#,webcam,sharpdx,C#,Webcam,Sharpdx,我正在尝试实现一个网络摄像头捕获应用程序,它应该拍摄静止帧,在屏幕上显示它们并保存到磁盘 由于我已经在使用SharpDX来捕获屏幕,所以我认为使用该库会很好。我不确定SharpDX是否具有任何视频捕获功能,因此我开始搜索并找到了它看起来像网络摄像头捕获原型的部分内容: var attributes = new MediaAttributes(1); attributes.Set<Guid>(CaptureDeviceAttributeKeys.SourceType, CaptureD

我正在尝试实现一个网络摄像头捕获应用程序,它应该拍摄静止帧,在屏幕上显示它们并保存到磁盘

由于我已经在使用SharpDX来捕获屏幕,所以我认为使用该库会很好。我不确定SharpDX是否具有任何视频捕获功能,因此我开始搜索并找到了它看起来像网络摄像头捕获原型的部分内容:

var attributes = new MediaAttributes(1);
attributes.Set<Guid>(CaptureDeviceAttributeKeys.SourceType, CaptureDeviceAttributeKeys.SourceTypeVideoCapture.Guid);
var activates = MediaFactory.EnumDeviceSources(attributes);

var dic = new Dictionary<string, Activate>();
foreach (var activate in activates)
{
    var uid = activate.Get(CaptureDeviceAttributeKeys.SourceTypeVidcapSymbolicLink);
    dic.Add(uid, activate);
}

var camera = dic.First().Value;
输出图像如下所示:

图像重复4次,每个部分都有一个灰度图像和一个高度为一半的彩色版本。
图像的三分之二是透明的。

您的输出是NV12,下面是一些将NV12转换为rgb的示例代码

    unsafe private static void TransformImage_NV12(IntPtr pDest, int lDestStride, IntPtr pSrc, int lSrcStride, int dwWidthInPixels, int dwHeightInPixels)
    {
        uint imageWidth = (uint)dwWidthInPixels;
        uint widthHalf = imageWidth / 2;
        uint imageHeight = (uint)dwHeightInPixels;

        byte* nv12Data = (byte*)pSrc;
        byte* rgbData = (byte*)pDest;

        uint dataSize = imageWidth * imageHeight * 3;

        for (uint y = 0; y < imageHeight; y++)
        {
            for (uint x = 0; x < imageWidth; x++)
            {
                uint xEven = x & 0xFFFFFFFE;
                uint yEven = y & 0xFFFFFFFE;
                uint yIndex = y * imageWidth + x;
                uint cIndex = imageWidth * imageHeight + yEven * widthHalf + xEven;

                byte yy = nv12Data[yIndex];
                byte cr = nv12Data[cIndex + 0];
                byte cb = nv12Data[cIndex + 1];

                uint outputIndex = (dataSize - (y * imageWidth + x) * 3) - 3;

                rgbData[outputIndex + 0] = (byte)Math.Min(Math.Max((yy + 1.402 * (cr - 128)), 0), 255);
                rgbData[outputIndex + 1] = (byte)Math.Min(Math.Max((yy - 0.344 * (cb - 128) - 0.714 * (cr - 128)), 0), 255);
                rgbData[outputIndex + 2] = (byte)Math.Min(Math.Max((yy + 1.772 * (cb - 128)), 0), 255);
            }
        }
    }

请参阅SDK中提到的MFCaptureTFile示例项目。也许这会有帮助。看起来您使用的是BGRA,但显示的内容看起来确实是不同的颜色格式。很抱歉延迟回复您。我得到一个垂直翻转的图像。顺便说一句,这是BGR,不是RGB,但我还是想和BGR合作。媒体类型是MJPEG。如果我通过选择流中的其他格式切换到NV12,我在示例中只得到几个字节。
    unsafe private static void TransformImage_NV12(IntPtr pDest, int lDestStride, IntPtr pSrc, int lSrcStride, int dwWidthInPixels, int dwHeightInPixels)
    {
        uint imageWidth = (uint)dwWidthInPixels;
        uint widthHalf = imageWidth / 2;
        uint imageHeight = (uint)dwHeightInPixels;

        byte* nv12Data = (byte*)pSrc;
        byte* rgbData = (byte*)pDest;

        uint dataSize = imageWidth * imageHeight * 3;

        for (uint y = 0; y < imageHeight; y++)
        {
            for (uint x = 0; x < imageWidth; x++)
            {
                uint xEven = x & 0xFFFFFFFE;
                uint yEven = y & 0xFFFFFFFE;
                uint yIndex = y * imageWidth + x;
                uint cIndex = imageWidth * imageHeight + yEven * widthHalf + xEven;

                byte yy = nv12Data[yIndex];
                byte cr = nv12Data[cIndex + 0];
                byte cb = nv12Data[cIndex + 1];

                uint outputIndex = (dataSize - (y * imageWidth + x) * 3) - 3;

                rgbData[outputIndex + 0] = (byte)Math.Min(Math.Max((yy + 1.402 * (cr - 128)), 0), 255);
                rgbData[outputIndex + 1] = (byte)Math.Min(Math.Max((yy - 0.344 * (cb - 128) - 0.714 * (cr - 128)), 0), 255);
                rgbData[outputIndex + 2] = (byte)Math.Min(Math.Max((yy + 1.772 * (cb - 128)), 0), 255);
            }
        }
    }