C# 从视频C中提取帧#

C# 从视频C中提取帧#,c#,video,image-processing,win-universal-app,C#,Video,Image Processing,Win Universal App,我正在尝试制作一个应用程序,使用摄像头录制视频并处理视频图像。这是我想要的。首先,我的应用程序用Torch录制了一段10秒的视频。其次,我使用一种方法来播放视频,以查看我录制的内容 我被三件事困住了 如何将视频转换为单个帧(图像) 是否可以在录制视频时异步转换视频 当我将视频转换为单个帧时,我如何处理它们?它们是JPEG吗?我可以简单地将它们显示为图像吗?等等 主要代码: using System; using Windows.UI.Xaml; using Windows.UI.Xaml.Con

我正在尝试制作一个应用程序,使用摄像头录制视频并处理视频图像。这是我想要的。首先,我的应用程序用Torch录制了一段10秒的视频。其次,我使用一种方法来播放视频,以查看我录制的内容

我被三件事困住了

  • 如何将视频转换为单个帧(图像)
  • 是否可以在录制视频时异步转换视频
  • 当我将视频转换为单个帧时,我如何处理它们?它们是JPEG吗?我可以简单地将它们显示为图像吗?等等
  • 主要代码:

    using System;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Controls;
    
    using Windows.UI.Xaml.Navigation;
    
    namespace App3
    {
    
    public sealed partial class MainPage : Page
    {          
        DispatcherTimer D;
        double basetimer = 0;
        public MainPage()
        {
            this.InitializeComponent();       
            this.NavigationCacheMode = NavigationCacheMode.Required;
            D = new DispatcherTimer();      
            D.Interval = new TimeSpan(0, 0, 1);
            D.Tick += timer_Tick;
            txt.Text = basetimer.ToString();
            Play.IsEnabled = false;            
        }  
        public Library Library = new Library();
        public object PreviewImage { get; private set; }
        void timer_Tick(object sender, object e)
        {
            basetimer = basetimer - 1;
            txt.Text = basetimer.ToString();
            if (basetimer == 0)
            {
                D.Stop();               
                Preview.Source = null;
                Library.Stop();
                Record.IsEnabled = false;
                Play.IsEnabled = true;
                Clear.IsEnabled = true;
                if (Library._tc.Enabled)
                {
                    Library._tc.Enabled = false;
                }                
            }
        }
        private void Record_Click(object sender, RoutedEventArgs e)
        {            
            if (Library.Recording)
            {
                Preview.Source = null;
                Library.Stop();
                Record.Icon = new SymbolIcon(Symbol.Video);                
            }
            else
            {
                basetimer = 11;
                D.Start();
                //D.Tick += timer_Tick;
                Display.Source = null;
                Library.Record(Preview);
                Record.Icon = new SymbolIcon(Symbol.VideoChat);
                Record.IsEnabled = false;
                Play.IsEnabled = false;
            }
        }
        private async void Play_Click(object sender, RoutedEventArgs e)
        {            
            await Library.Play(Dispatcher, Display);
            //Extract_Image_From_Video(Library.buffer);            
        }
        private  void Clear_Click(object sender, RoutedEventArgs e)
        {
            Display.Source = null;            
            Record.Icon = new SymbolIcon(Symbol.Video);
            txt.Text = "0";
            basetimer=  0;
            Play.IsEnabled = false;
            Record.IsEnabled =true;
            if (Library.capture != null)
            {
                D.Stop();
                Library.Recording = false;
                Preview.Source = null;               
                Library.capture.Dispose();
                Library.capture = null;
                basetimer = 11;
            }
            }
        }
    }
    
    图书馆类别:

    using System;
    using System.Diagnostics;
    using System.Linq;
    using System.Threading.Tasks;
    using Windows.Devices.Enumeration;
    using Windows.Media.Capture;
    using Windows.Media.Devices;
    using Windows.Media.MediaProperties;
    using Windows.Storage;
    using Windows.Storage.Streams;
    using Windows.UI.Core;
    using Windows.UI.Xaml.Controls;
    using Windows.UI.Xaml.Media.Imaging;
    using Windows.Graphics.Imaging;
    using Emgu.CV.Structure;
    using Emgu.CV;
    using System.Collections.Generic;
    
    public class Library
    {
    
    private const string videoFilename = "video.mp4";
    private string filename;
    public MediaCapture capture;
    public InMemoryRandomAccessStream buffer;
    public static bool Recording;
    public TorchControl _tc;
    public int basetimer  ;   
    public async Task<bool> init()
    {
        if (buffer != null)
        {
            buffer.Dispose();
        }
        buffer = new InMemoryRandomAccessStream();
        if (capture != null)
        {
            capture.Dispose();
        }
        try
        {
    
            if (capture == null)
            {
                var allVideoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);               
                DeviceInformation cameraDevice =
                allVideoDevices.FirstOrDefault(x => x.EnclosureLocation != null &&
                x.EnclosureLocation.Panel == Windows.Devices.Enumeration.Panel.Back);
                capture = new MediaCapture();
                var mediaInitSettings = new MediaCaptureInitializationSettings { VideoDeviceId = cameraDevice.Id };
                // Initialize 
                try
                {
                    await capture.InitializeAsync(mediaInitSettings);
                    var videoDev = capture.VideoDeviceController;
                    _tc = videoDev.TorchControl;
                    Recording = false;
                    _tc.Enabled = false;                                      
                }
                catch (UnauthorizedAccessException)
                {
                    Debug.WriteLine("UnauthorizedAccessExeption>>");
                }
                catch (Exception ex)
                {
                    Debug.WriteLine("Exception when initializing MediaCapture with {0}: {1}", cameraDevice.Id, ex.ToString());
                }
            }
                capture.Failed += (MediaCapture sender, MediaCaptureFailedEventArgs errorEventArgs) =>
            {
                Recording = false;
                _tc.Enabled = false;
                throw new Exception(string.Format("Code: {0}. {1}", errorEventArgs.Code, errorEventArgs.Message));
            };
        }
        catch (Exception ex)
        {
            if (ex.InnerException != null && ex.InnerException.GetType() == typeof(UnauthorizedAccessException))
            {
                throw ex.InnerException;
            }
            throw;
        }
        return true;
    }
    public async void Record(CaptureElement preview)
    {    
        await init();
        preview.Source = capture; 
        await capture.StartPreviewAsync();
        await capture.StartRecordToStreamAsync(MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto), buffer);
        if (Recording) throw new InvalidOperationException("cannot excute two records at the same time");
        Recording = true;
        _tc.Enabled = true;
    
    }
    public async void Stop()
    {
        await capture.StopRecordAsync();
        Recording = false;
        _tc.Enabled = false;       
    }    
    
    public async Task Play(CoreDispatcher dispatcher, MediaElement playback)
    {
        IRandomAccessStream video = buffer.CloneStream();
    
        if (video == null) throw new ArgumentNullException("buffer");
        StorageFolder storageFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
        if (!string.IsNullOrEmpty(filename))
        {
            StorageFile original = await storageFolder.GetFileAsync(filename);
            await original.DeleteAsync();
        }
        await dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
        {
            StorageFile storageFile = await storageFolder.CreateFileAsync(videoFilename, CreationCollisionOption.GenerateUniqueName);
            filename = storageFile.Name;
            using (IRandomAccessStream fileStream = await storageFile.OpenAsync(FileAccessMode.ReadWrite))
            {
                await RandomAccessStream.CopyAndCloseAsync(video.GetInputStreamAt(0), fileStream.GetOutputStreamAt(0));
                await video.FlushAsync();
                video.Dispose();
            }
            IRandomAccessStream stream = await storageFile.OpenAsync(FileAccessMode.Read);
    
            playback.SetSource(stream, storageFile.FileType);
            playback.Play();
    
    
    
    
    
        });
    
    
    }   
    
    使用系统;
    使用系统诊断;
    使用System.Linq;
    使用System.Threading.Tasks;
    使用Windows.Devices.Enumeration;
    使用Windows.Media.Capture;
    使用Windows.Media.Devices;
    使用Windows.Media.MediaProperties;
    使用Windows.Storage;
    使用Windows.Storage.Streams;
    使用Windows.UI.Core;
    使用Windows.UI.Xaml.Controls;
    使用Windows.UI.Xaml.Media.Imaging;
    使用Windows.Graphics.Imaging;
    使用Emgu.CV.Structure;
    使用Emgu.CV;
    使用System.Collections.Generic;
    公共班级图书馆
    {
    私有常量字符串videoFilename=“video.mp4”;
    私有字符串文件名;
    公共媒体捕获;
    公共内存随机访问流缓冲区;
    公共静态bool记录;
    公共火炬控制中心;
    公共整数基定时器;
    公共异步任务init()
    {
    if(缓冲区!=null)
    {
    buffer.Dispose();
    }
    缓冲区=新的InMemoryRandomAccessStream();
    如果(捕获!=null)
    {
    capture.Dispose();
    }
    尝试
    {
    如果(捕获==null)
    {
    var allVideoDevices=等待设备信息.findalsync(DeviceClass.VideoCapture);
    设备信息摄像设备=
    allVideoDevices.FirstOrDefault(x=>x.EnclosureLocation!=null&&
    x、 EnclosureLocation.Panel==Windows.Devices.Enumeration.Panel.Back);
    capture=新媒体捕获();
    var medialinitsettings=new mediacaptureininitializationsettings{VideoDeviceId=cameraDevice.Id};
    //初始化
    尝试
    {
    等待捕获。初始化同步(mediaInitSettings);
    var videoDev=capture.VideoDeviceController;
    _tc=视频开发火炬控制;
    记录=假;
    _tc.Enabled=false;
    }
    捕获(未经授权的访问例外)
    {
    Debug.WriteLine(“unauthorizedAccessException>>”;
    }
    捕获(例外情况除外)
    {
    WriteLine(“使用{0}:{1}初始化MediaCapture时出现异常”,cameraDevice.Id,ex.ToString());
    }
    }
    capture.Failed+=(MediaCapture发送方、MediaCaptureFailedEventArgs errorEventArgs)=>
    {
    记录=假;
    _tc.Enabled=false;
    抛出新异常(string.Format(“代码:{0}.{1}”,errorEventArgs.Code,errorEventArgs.Message));
    };
    }
    捕获(例外情况除外)
    {
    if(ex.InnerException!=null&&ex.InnerException.GetType()==typeof(UnauthorizedAccessException))
    {
    抛出ex.InnerException;
    }
    投掷;
    }
    返回true;
    }
    公共异步无效记录(CaptureElement预览)
    {    
    等待初始化();
    preview.Source=捕获;
    等待捕获。StartPreviewSync();
    等待捕获。StartRecordToStreamAsync(MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto),缓冲区);
    如果(记录)抛出新的InvalidOperationException(“无法同时执行两条记录”);
    记录=真;
    _tc.Enabled=true;
    }
    公共异步无效停止()
    {
    等待捕获。StopRecordAsync();
    记录=假;
    _tc.Enabled=false;
    }    
    公共异步任务播放(CoreDispatcher、MediaElement播放)
    {
    irandomaccesstream video=buffer.CloneStream();
    如果(video==null)抛出新的ArgumentNullException(“缓冲区”);
    StorageFolder StorageFolder=Windows.ApplicationModel.Package.Current.InstalledLocation;
    如果(!string.IsNullOrEmpty(文件名))
    {
    StorageFile original=等待storageFolder.GetFileAsync(文件名);
    等待original.DeleteAsync();
    }
    等待dispatcher.RunAsync(CoreDispatcherPriority.Normal,async()=>
    {
    StorageFile StorageFile=Wait storageFolder.CreateFileAsync(videoFilename,CreationCollisionOption.GenerateUniqueName);
    filename=storageFile.Name;
    使用(irandomaccesstream fileStream=await-storageFile.OpenAsync(FileAccessMode.ReadWrite))
    {
    等待RandomAccessStream.CopyAndCloseAsync(video.GetInputStreamAt(0),fileStream.GetOutputStreamAt(0));
    等待video.FlushAsync();
    video.Dispose();
    }
    irandomaccesstream=wait-storageFile.OpenAsync(FileAccessMode.Read);
    playback.SetSource(stream,storageFile.FileType);
    playback.Play();
    });
    }   
    
    我昨天才想到这一点

    下面是一个完整且易于理解的示例,其中包括拾取视频文件并在视频的第1秒保存快照

    您可以选择适合您的项目的部分,并更改其中的一些部分(即从相机获取视频分辨率)

    1)和3)

    如果要提取更多帧,还可以使用
    composition.GetThumbnailsAsync

    2)当计时器滴答作响时,使用mediaCapture

    使用并安装

    使用(var vfreeader=new VideoFileReader())
    {
    vfreeader.Open(“video.mp4”);
    对于(int i=0;i
    在与Accord发生大量问题后,我最终用它解决了一个类似的问题

    我需要为视频的每一秒保存一幅图像:

    using (var engine = new Engine())
    {
        var mp4 = new MediaFile { Filename = mp4FilePath };
    
        engine.GetMetadata(mp4);
    
        var i = 0;
        while (i < mp4.Metadata.Duration.Seconds)
        {
            var options = new ConversionOptions { Seek = TimeSpan.FromSeconds(i) };
            var outputFile = new MediaFile { Filename = string.Format("{0}\\image-{1}.jpeg", outputPath, i) };
            engine.GetThumbnail(mp4, outputFile, options);
            i++;
        }
    }
    
    使用(var引擎=新的E
    
    BitmapImage bitmapImage = new BitmapImage();
    bitmapImage.SetSource(imageStream);
    
    XAMLImage.Source = bitmapImage;
    
    using (var vFReader = new VideoFileReader())
    {
        vFReader.Open("video.mp4");
        for (int i = 0; i < vFReader.FrameCount; i++)
        {
            Bitmap bmpBaseOriginal = vFReader.ReadVideoFrame();
        }
        vFReader.Close();
    }
    
    using (var engine = new Engine())
    {
        var mp4 = new MediaFile { Filename = mp4FilePath };
    
        engine.GetMetadata(mp4);
    
        var i = 0;
        while (i < mp4.Metadata.Duration.Seconds)
        {
            var options = new ConversionOptions { Seek = TimeSpan.FromSeconds(i) };
            var outputFile = new MediaFile { Filename = string.Format("{0}\\image-{1}.jpeg", outputPath, i) };
            engine.GetThumbnail(mp4, outputFile, options);
            i++;
        }
    }
    
    // _env is the injected IWebHostEnvironment
    // _tempPath is temporary file storage
    var ffmpegPath = Path.Combine(_env.ContentRootPath, "<path-to-ffmpeg.exe>");
    
    var mediaToolkitService = MediaToolkitService.CreateInstance(ffmpegPath);
    var metadataTask = new FfTaskGetMetadata(_tempFile);
    var metadata = await mediaToolkitService.ExecuteAsync(metadataTask);
    
    var i = 0;
    while (i < metadata.Metadata.Streams.First().DurationTs)
    {
        var outputFile = string.Format("{0}\\image-{1:0000}.jpeg", _imageDir, i);
        var thumbTask = new FfTaskSaveThumbnail(_tempFile, outputFile, TimeSpan.FromSeconds(i));
        _ = await mediaToolkitService.ExecuteAsync(thumbTask);
        i++;
    }