[Azure] C# + Azure FaceAPI + MediaToolkit.NetCore 抓取影片(mp4) 中的 frame 進行辨識

2021-11-02

最近在處理一些騷專案,所以在看 Azure Face API ,然後我在想一件事情,就是可不可以把我多年收藏的謎片做分類

這時候就要有一個很重要的關鍵,就是我要能夠從影片檔取一個 frame 出來採樣進行辨識,所以稍微研究一下

其實不難,但是因為很多都是用不是用 .net core 寫的,所以都得 depends on  .Net Framework,雖然成功但是我還是重新測試

找了一個不用 .Net Framewrok 的,但是你還是得安裝 ffmpeg



1. 下載 ffmpeg ,網址: https://ffmpeg.org/download.html ,因為我的環境是 windows 那就下載 windows 的版本

2. 解壓縮到專案,我複製在 ASP.net core 3.1 專案下一個 ffmpeg 檔案夾下,然後記得要調成複製到 release 下。




3. 再來就是 nuget 套件,以前我記得我是使用 MediaToolkit , 網路上找到案例不少,這邊分享 .net Core 的,下載這個

https://www.nuget.org/packages/MediaToolkit.NetCore/0.2.1-preview



4. 影片選用,我是去 youtube  找一個影片來測試,謎片太過精彩不能再部落格公開,我測試影片是 

https://www.youtube.com/watch?v=K0mhNqW-mTo

然後把這影片下載成 mp,至於是用什麼方法,就自己去找一下吧,我只是測試使用。


5. 接下來就是程式碼的部分,這裡面比較重要的就是要指向到 ffmpeg 的執行目錄,其他我就寫在程式碼註解中


private void GetMP4FrameAndDetect() { //來源影片檔案 var sourceFilm = AppDomain.CurrentDomain.BaseDirectory + "sample" + System.IO.Path.DirectorySeparatorChar + "s1.mp4"; //輸出的圖片 var outputFile = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "wwwroot", "s1.jpg"); //ffmpeg 路徑 var ffmpegFilePath = AppDomain.CurrentDomain.BaseDirectory + "ffmpeg" + System.IO.Path.DirectorySeparatorChar + "bin" + System.IO.Path.DirectorySeparatorChar + "ffmpeg.exe"; var serviceProvider = new ServiceCollection() .AddMediaToolkit(ffmpegFilePath) .BuildServiceProvider(); var engine = serviceProvider.GetService<imediatoolkitservice>(); //抓取第 11 秒縮圖 var saveThumbnailTask = new MediaToolkit.Tasks.FfTaskSaveThumbnail( sourceFilm, outputFile, TimeSpan.FromSeconds(11) ); var result = engine.ExecuteAsync(saveThumbnailTask).Result; //送去 Azure Face API var faceClient = Authenticate(ENDPOINT, SUBSCRIPTION_KEY); //取圖片轉成 stream byte[] buff = System.IO.File.ReadAllBytes(outputFile); System.IO.MemoryStream ms = new System.IO.MemoryStream(buff); //送往 azure 辨識&#65292;如果 Detection01 偵測不到可以改用 Detection02 var localFaces = faceClient.Face.DetectWithStreamAsync(ms, detectionModel: DetectionModel.Detection02).Result; //紀錄一下偵測到人臉的部分 List<rectangle> rects = new List<rectangle>(); if (localFaces.Count > 0) { foreach (var face in localFaces) { var faceRect = face.FaceRectangle; Result += "FaceId:" + face.FaceId+"<br>"; rects.Add(new Rectangle(faceRect.Left, faceRect.Top, faceRect.Width, faceRect.Height)); } ms.Close(); //下面的部分就是&#65292;讀取一次圖片&#65292;將找出來的人臉畫出來&#12290; System.IO.Directory.CreateDirectory(AppDomain.CurrentDomain.BaseDirectory + "output"); var img = Image.FromFile(outputFile); img = DrawRectsToImage(img, rects.ToArray()); string pathStr = System.IO.Path.Combine(System.IO.Directory.GetCurrentDirectory(), "wwwroot", "s2.jpg"); img.Save(pathStr); } Result += "<img src="/s1.jpg" style="width:500px"><br>"; Result += "<img src="/s2.jpg" style="width:500px"><br>"; } /// <summary> /// 將抓到的臉標示上紅框 /// </summary> /// <param name="img"></param> /// <param name="rects"></param> /// <returns></returns> private Image DrawRectsToImage(Image img, System.Drawing.Rectangle[] rects) { if (img == null) { return null; } Result += "ImgW:" + img.Width + "ImgH: " + img.Height + " <br>"; if (rects != null) { Pen redPen = new Pen(Color.Red, 2); foreach (var rect in rects) { var nRect = new Rectangle(rect.Left, rect.Top, rect.Width, rect.Height); Graphics graphic = Graphics.FromImage(img); graphic.DrawRectangle(redPen, nRect); } return img; } return null; }



result:



有沒有很方便,這樣就可以把手上的謎片人臉偵測出來,之後有時間我再來分享怎麼做人物分類。



reference

https://github.com/rosenbjerg/FFMpegCore
https://ffmpeg.org/download.html

https://github.com/mtebenev/MediaToolkit.NetCore


當麻許的超技八 2014 | Donma Hsu Design.