如何通过Kinect SDK 2在WPF中将Kinect彩色视频保存为流到硬盘

4

我们可以使用 emgucv 中的 VideoWriter 类和 WriteFrame 函数将视频保存为 avi 文件,但此函数不支持流式传输。 - AmiR Hossein
我想开发一个程序,可以将Kinect彩色数据源连续保存到硬盘文件中,而不是RAM,因为内存不足。 - AmiR Hossein
1个回答

4

对于一个项目,我必须这样做。我所做的可能不能满足您的所有要求,但可能会给您一个想法。首先,我将每个彩色帧图像保存在本地驱动器上,并进行连续命名。然后,使用ffmpeg将这些连续图像转换为视频文件,在我的情况下是mp4视频,而不是avi。

要按顺序保存彩色图像帧,您可以编写以下代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Kinect;
using System.IO;
using System.Drawing;
using System.Drawing.Imaging;

namespace Kinect_Video_Recorder
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        KinectSensor ks;
        ColorFrameReader cfr;
        byte[] colorData;
        ColorImageFormat format;
        WriteableBitmap wbmp;
        BitmapSource bmpSource;
        int imageSerial;

        public MainWindow()
        {
            InitializeComponent();
            ks = KinectSensor.GetDefault();
            ks.Open();
            var fd = ks.ColorFrameSource.CreateFrameDescription(ColorImageFormat.Bgra);
            uint frameSize = fd.BytesPerPixel * fd.LengthInPixels;
            colorData = new byte[frameSize];
            format = ColorImageFormat.Bgra;
            imageSerial = 0;

            cfr = ks.ColorFrameSource.OpenReader();
            cfr.FrameArrived += cfr_FrameArrived;
        }

        void cfr_FrameArrived(object sender, ColorFrameArrivedEventArgs e)
        {
            if (e.FrameReference == null) return;

            using (ColorFrame cf = e.FrameReference.AcquireFrame())
            {
                if(cf == null) return;
                cf.CopyConvertedFrameDataToArray( colorData, format);
                var fd = cf.FrameDescription;

                // Creating BitmapSource
                var bytesPerPixel = (PixelFormats.Bgr32.BitsPerPixel) / 8;
                var stride = bytesPerPixel * cf.FrameDescription.Width;

                bmpSource = BitmapSource.Create(fd.Width, fd.Height, 96.0, 96.0, PixelFormats.Bgr32, null, colorData, stride);

                // WritableBitmap to show on UI
                wbmp = new WriteableBitmap(bmpSource);
                kinectImage.Source = wbmp;

                // JpegBitmapEncoder to save BitmapSource to file
                // imageSerial is the serial of the sequential image
                JpegBitmapEncoder encoder = new JpegBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(bmpSource));
                using (var fs = new FileStream("./img/" + (imageSerial++) + ".jpeg", FileMode.Create, FileAccess.Write))
                {
                    encoder.Save(fs);
                }    
            }
        }
    }
}

上面的例子将图片保存为jpeg格式。如果您需要保存为png格式,请使用PngBitmapEncoder
现在我们已经将顺序图片保存到硬盘中。要将这些顺序图片转换为视频文件,您可以使用ffmpeg。您还可以使用Aforge.net。但我从未使用过它。在我的情况下,我从我的C#程序中调用了ffmpeg.exe进程,如下所示。 Process.Start("ffmpeg.exe", "-framerate 10 -i ./img/%d.jpeg -c:v libx264 -r 30 -pix_fmt yuv420p kinect_video.mp4"); 注意:
  1. 将您的构建目标设置为x64。这将增加程序的内存限制。
  2. 我已编写了一个基本的实现。如果您想查看,可以查看。

希望能有所帮助 :)


1
我使用了你的想法,亲爱的Rafaf Tahsin,但你的代码速度较慢。原因是这行代码:wbmp = new WriteableBitmap(bmpSource); 如果你删掉它,用kinectImage.Source = bmpSource;代替,就会好很多。 - AmiR Hossein
有一个大问题,那就是声音。我改变了我的问题:如何录制和保存声音和彩色视频作为流,使它们匹配在一起? - AmiR Hossein
我不知道如何从Kinect v2同步保存音频和视频。我建议您提出一个新的问题,希望有人能够帮助。谢谢。 - Rafaf Tahsin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接