Note
ãã®ããŒãžã«ã¢ã¯ã»ã¹ããã«ã¯ãæ¿èªãå¿ èŠã§ãã ãµã€ã³ã€ã³ãŸãã¯ãã£ã¬ã¯ããªã®å€æŽã詊ãããšãã§ããŸãã
ãã®ããŒãžã«ã¢ã¯ã»ã¹ããã«ã¯ãæ¿èªãå¿ èŠã§ãã ãã£ã¬ã¯ããªã®å€æŽã詊ãããšãã§ããŸãã
ML.NET ã§äºåãã¬ãŒãã³ã°æžã¿ã® ONNX ã¢ãã«ã䜿çšããŠãç»åå ã®ãªããžã§ã¯ããæ€åºããæ¹æ³ã«ã€ããŠèª¬æããŸãã
ç©äœæ€åºã¢ãã«ããŒããããã¬ãŒãã³ã°ããã«ã¯ãäœçŸäžãã®ãã©ã¡ãŒã¿ãŒã倧éã®ã©ãã«ä»ãããããã¬ãŒãã³ã° ããŒã¿ãèšå€§ãªéã®ã³ã³ãã¥ãŒãã£ã³ã° ãªãœãŒã¹ (æ°çŸ GPU æé) ãèšå®ããå¿ èŠããããŸãã äºåãã¬ãŒãã³ã°æžã¿ã¢ãã«ã䜿çšãããšããã¬ãŒãã³ã° ããã»ã¹ãã·ã§ãŒãã«ããã§ããŸãã
ãã®ãã¥ãŒããªã¢ã«ã§ã¯ã以äžã®å 容ãåŠç¿ããŸãã
- åé¡ãçè§£ãã
- ONNX ãšã¯äœããML.NET ã§ã®åäœã«ã€ããŠèª¬æããŸã
- ã¢ãã«ãçè§£ãã
- äºåãã¬ãŒãã³ã°æžã¿ã¢ãã«ãåå©çšãã
- èªã¿èŸŒãŸããã¢ãã«ã䜿çšããŠãªããžã§ã¯ããæ€åºãã
[åææ¡ä»¶]
- Visual Studio 2022 以éã
- Microsoft.ML ã® NuGet ããã±ãŒãž
- Microsoft.ML.ImageAnalytics NuGet ããã±ãŒãž
- Microsoft.ML.OnnxTransformer NuGet ããã±ãŒãž
- Tiny YOLOv2 äºåãã¬ãŒãã³ã°æžã¿ã¢ãã«
- Netron (çç¥å¯èœ)
ONNX ãªããžã§ã¯ãæ€åºãµã³ãã«ã®æŠèŠ
ãã®ãµã³ãã«ã§ã¯ãäºåãã¬ãŒãã³ã°æžã¿ã®ãã£ãŒã ã©ãŒãã³ã° ONNX ã¢ãã«ã䜿çšããŠãã€ã¡ãŒãžå ã®ãªããžã§ã¯ããæ€åºãã .NET Core ã³ã³ãœãŒã« ã¢ããªã±ãŒã·ã§ã³ãäœæããŸãã ãã®ãµã³ãã«ã®ã³ãŒãã¯ãGitHub ã® dotnet/machinelearning-samples ãªããžã㪠ã«ãããŸãã
ç©äœæ€åºãšã¯
ç©äœæ€åºã¯ãã³ã³ãã¥ãŒã¿ãŒ ããžã§ã³ã®åé¡ã§ãã ç©äœæ€åºã¯ç»ååé¡ãšå¯æ¥ã«é¢é£ããŠããŸããããã詳现ãªã¹ã±ãŒã«ã§ç»ååé¡ãå®è¡ããŸãã ãªããžã§ã¯ã æ€åºã§ã¯ã ç»åå ã®ãšã³ãã£ãã£ãèŠã€ããŠåé¡ããŸãã ç©äœæ€åºã¢ãã«ã¯ãäžè¬çã«ãã£ãŒã ã©ãŒãã³ã°ãšãã¥ãŒã©ã« ãããã¯ãŒã¯ã䜿çšããŠãã¬ãŒãã³ã°ãããŸãã 詳现ã«ã€ããŠã¯ã ãã£ãŒã ã©ãŒãã³ã°ã𿩿¢°åŠç¿ ãåç §ããŠãã ããã
ç»åã«ç°ãªãçš®é¡ã®è€æ°ã®ãªããžã§ã¯ããå«ãŸããŠããå Žåã¯ããªããžã§ã¯ãæ€åºã䜿çšããŸãã
ãªããžã§ã¯ãæ€åºã®ãŠãŒã¹ ã±ãŒã¹ã«ã¯ã次ã®ãããªãã®ããããŸãã
- èªåé転è»
- ãããã£ãã¯ã¹
- 顿€åº
- è·å Žã®å®å š
- ãªããžã§ã¯ãã®ã«ãŠã³ã
- ã¢ã¯ãã£ããã£ã®èªè
ãã£ãŒã ã©ãŒãã³ã° ã¢ãã«ãéžæãã
ãã£ãŒã ã©ãŒãã³ã°ã¯æ©æ¢°åŠç¿ã®ãµãã»ããã§ãã ãã£ãŒã ã©ãŒãã³ã° ã¢ãã«ããã¬ãŒãã³ã°ããã«ã¯ã倧éã®ããŒã¿ãå¿ èŠã§ãã ããŒã¿å ã®ãã¿ãŒã³ã¯ãäžé£ã®ã¬ã€ã€ãŒã«ãã£ãŠè¡šãããŸãã ããŒã¿å ã®ãªã¬ãŒã·ã§ã³ã·ããã¯ãéã¿ãå«ãã¬ã€ã€ãŒéã®æ¥ç¶ãšããŠãšã³ã³ãŒããããŸãã éã¿ã倧ããã»ã©ããªã¬ãŒã·ã§ã³ã·ããã¯åŒ·ããªããŸãã ç·ç§°ããŠããã®äžé£ã®å±€ãšæ¥ç¶ã¯äººå·¥ãã¥ãŒã©ã« ãããã¯ãŒã¯ãšåŒã°ããŸãã ãããã¯ãŒã¯å ã®å±€ãå€ãã»ã©"æ·±ã"ããããã£ãŒã ãã¥ãŒã©ã« ãããã¯ãŒã¯ã«ãªããŸãã
ãã¥ãŒã©ã« ãããã¯ãŒã¯ã«ã¯ããŸããŸãªçš®é¡ããããæãäžè¬çãªãã®ã¯å€å±€ããŒã»ãããã³ (MLP)ãç³ã¿èŸŒã¿ãã¥ãŒã©ã« ãããã¯ãŒã¯ (CNN)ãããã³ãªã«ã¬ã³ã ãã¥ãŒã©ã« ãããã¯ãŒã¯ (RNN) ã§ãã æãåºæ¬ç㪠MLP ã¯ãäžé£ã®å ¥åãåºåã®ã»ããã«ãããããŸãã ãã®ãã¥ãŒã©ã« ãããã¯ãŒã¯ã¯ãããŒã¿ã«ç©ºéãŸãã¯æéã®ã³ã³ããŒãã³ãããªãå Žåã«é©ããŠããŸãã CNN ã§ã¯ãç³ã¿èŸŒã¿ã¬ã€ã€ãŒã䜿çšããŠãããŒã¿ã«å«ãŸããç©ºéæ å ±ãåŠçããŸãã CNN ã®é©åãªãŠãŒã¹ ã±ãŒã¹ã¯ãç»åã®é åã«ç¹åŸŽã®ååšãæ€åºããç»ååŠçã§ã (ç»åã®äžå€®ã«éŒ»ãããããªã©)ã æåŸã«ãRNN ã䜿çšãããšãç¶æ ãŸãã¯ã¡ã¢ãªã®æ°žç¶åãå ¥åãšããŠäœ¿çšã§ããŸãã RNN ã¯ãã€ãã³ãã®é çªãšã³ã³ããã¹ããéèŠãªæç³»ååæã«äœ¿çšãããŸãã
ã¢ãã«ãçè§£ãã
ç©äœæ€åºã¯ç»ååŠçã¿ã¹ã¯ã§ãã ãã®ããããã®åé¡ã解決ããããã«ãã¬ãŒãã³ã°ãããã»ãšãã©ã®ãã£ãŒã ã©ãŒãã³ã° ã¢ãã«ã¯ CNN ã§ãã ãã®ãã¥ãŒããªã¢ã«ã§äœ¿çšãããã¢ãã«ã¯ Tiny YOLOv2 ã¢ãã«ã§ãããã®ã¢ãã«ã¯ããã¯ã€ã ããŒããŒã§èª¬æãããŠãã YOLOv2 ã¢ãã«ã®ããã³ã³ãã¯ããªããŒãžã§ã³ã§ãã Redmon ãš Farhadi ã«ãã"YOLO9000: Better, Faster, Stronger" ã§ãã Tiny YOLOv2 ã¯ãPascal VOC ããŒã¿ã»ããã§ãã¬ãŒãã³ã°ããã20 åã®ç°ãªãã¯ã©ã¹ã®ãªããžã§ã¯ããäºæž¬ã§ãã 15 åã®ã¬ã€ã€ãŒã§æ§æãããŠããŸãã Tiny YOLOv2 ã¯å
ã® YOLOv2 ã¢ãã«ã®åçž®ããŒãžã§ã³ã§ãããããé床ãšç²ŸåºŠã®éã§ãã¬ãŒããªããè¡ãããŸãã ã¢ãã«ãæ§æããããŸããŸãªã¬ã€ã€ãŒã¯ãNetron ãªã©ã®ããŒã«ã䜿çšããŠèŠèŠåã§ããŸãã ã¢ãã«ãæ€æ»ãããšããã¥ãŒã©ã« ãããã¯ãŒã¯ãæ§æãããã¹ãŠã®ã¬ã€ã€ãŒéã®æ¥ç¶ã®ãããã³ã°ãçæãããŸããåã¬ã€ã€ãŒã«ã¯ãåã¬ã€ã€ãŒã®ååãšãããããã®å
¥å/åºåã®ãã£ã¡ã³ã·ã§ã³ãå«ãŸããŸãã ã¢ãã«ã®å
¥åãšåºåãèšè¿°ããããã«äœ¿çšãããããŒã¿æ§é ã¯ãã³ãœã«ãšåŒã°ããŸãã ãã³ãœã«ã¯ãN 次å
ã«ããŒã¿ãæ ŒçŽããã³ã³ãããŒãšèããããšãã§ããŸãã Tiny YOLOv2 ã®å Žåãå
¥åã¬ã€ã€ãŒã®åå㯠image ããã 3 x 416 x 416次å
ã®ãã³ãœã«ãå¿
èŠã§ãã åºåã¬ã€ã€ãŒã®ååã grid ããããã£ã¡ã³ã·ã§ã³ 125 x 13 x 13ã®åºåãã³ãœã«ãçæãããŸãã
YOLO ã¢ãã«ã¯ç»å 3(RGB) x 416px x 416pxãåãåããŸãã ã¢ãã«ã¯ãã®å
¥åãåãåããç°ãªãã¬ã€ã€ãŒãééããŠåºåãçæããŸãã åºåã«ãããå
¥åã€ã¡ãŒãžã 13 x 13 ã°ãªããã«åå²ãããã°ãªããå
ã®åã»ã«ã 125 å€ã§æ§æãããŸãã
ONNX ã¢ãã«ãšã¯
Open Neural Network Exchange (ONNX) ã¯ãAI ã¢ãã«ã®ãªãŒãã³ ãœãŒã¹åœ¢åŒã§ãã ONNX ã§ã¯ããã¬ãŒã ã¯ãŒã¯éã®çžäºéçšæ§ããµããŒããããŠããŸãã ã€ãŸããPyTorch ãªã©ã®å€ãã®äžè¬çãªæ©æ¢°åŠç¿ãã¬ãŒã ã¯ãŒã¯ã® 1 ã€ã§ã¢ãã«ããã¬ãŒãã³ã°ããããã ONNX 圢åŒã«å€æããML.NET ã®ãããªå¥ã®ãã¬ãŒã ã¯ãŒã¯ã§ ONNX ã¢ãã«ã䜿çšã§ããŸãã 詳现ã«ã€ããŠã¯ã ONNX ã® Web ãµã€ããåç §ããŠãã ããã
äºåãã¬ãŒãã³ã°æžã¿ã® Tiny YOLOv2 ã¢ãã«ã¯ãONNX 圢åŒã§æ ŒçŽãããŸããããã¯ãã¬ã€ã€ãŒã®ã·ãªã¢ã«åããã衚çŸãšããããã®ã¬ã€ã€ãŒã®åŠç¿ããããã¿ãŒã³ã§ãã ML.NET ã§ã¯ã ImageAnalytics ããã±ãŒãžãš OnnxTransformer NuGet ããã±ãŒãžãšã®çžäºéçšæ§ã ONNX ãšå®çŸãããŸãã
ImageAnalytics ããã±ãŒãžã«ã¯ãç»åãååŸããäºæž¬ãã€ãã©ã€ã³ãŸãã¯ãã¬ãŒãã³ã° ãã€ãã©ã€ã³ãžã®å
¥åãšããŠäœ¿çšã§ããæ°å€ã«ãšã³ã³ãŒãããäžé£ã®å€æãå«ãŸããŠããŸãã
OnnxTransformer ããã±ãŒãžã§ã¯ãONNX ã©ã³ã¿ã€ã ãå©çšã㊠ONNX ã¢ãã«ãèªã¿èŸŒã¿ãããã䜿çšããŠæäŸãããå
¥åã«åºã¥ããŠäºæž¬ãè¡ããŸãã
.NET ã³ã³ãœãŒã« ãããžã§ã¯ããèšå®ãã
ONNX ãšã¯äœããTiny YOLOv2 ã®ããã¿ãäžè¬çã«çè§£ããããã¢ããªã±ãŒã·ã§ã³ããã«ãããŸãã
ã³ã³ãœãŒã« ã¢ããªã±ãŒã·ã§ã³ã®äœæ
"ObjectDetection" ãšããååã® C# ã³ã³ãœãŒã« ã¢ããªã±ãŒã·ã§ã³ ãäœæããŸãã [ 次㞠] ãã¿ã³ãã¯ãªãã¯ããŸãã
䜿çšãããã¬ãŒã ã¯ãŒã¯ãšã㊠.NET 8 ãéžæããŸãã [äœæ] ãã¿ã³ãã¯ãªãã¯ããŸãã
Microsoft.ML NuGet ããã±ãŒãžãã€ã³ã¹ããŒã«ããŸãã
泚
ãã®ãµã³ãã«ã§ã¯ãç¹ã«æèšãããŠããªãéããèšèŒãããŠããææ°ã®å®å®ããŒãžã§ã³ã® NuGet ããã±ãŒãžã䜿çšããŸãã
- ãœãªã¥ãŒã·ã§ã³ ãšã¯ã¹ãããŒã©ãŒã§ããããžã§ã¯ããå³ã¯ãªãã¯ãã[ NuGet ããã±ãŒãžã®ç®¡ç] ãéžæããŸãã
- ããã±ãŒãž ãœãŒã¹ãšã㊠[nuget.org] ãéžæãã[åç §] ã¿ããéžæãã Microsoft.ML ãæ€çŽ¢ããŸãã
- [ã€ã³ã¹ããŒã«] ãã¿ã³ãéžæããŸãã
- [倿Žã®ãã¬ãã¥ãŒ] ãã€ã¢ãã°ã§ [OK] ãã¿ã³ãéžæãã衚瀺ãããŠããããã±ãŒãžã®ã©ã€ã»ã³ã¹æ¡é ã«åæããå Žåã¯ã[ã©ã€ã»ã³ã¹ã®åæ] ãã€ã¢ãã°ã§ [åæãã] ãã¿ã³ãéžæããŸãã
- Microsoft.Windows.CompatibilityãMicrosoft.ML.ImageAnalyticsãMicrosoft.ML.OnnxTransformerãMicrosoft.ML.OnnxRuntime ã«ã€ããŠããããã®æé ãç¹°ãè¿ããŸãã
ããŒã¿ãšäºåãã¬ãŒãã³ã°æžã¿ã¢ãã«ãæºåãã
ãããžã§ã¯ãè³ç£ãã£ã¬ã¯ããªã® zip ãã¡ã€ã«ãããŠã³ããŒãããè§£åããŸãã
assetsãã£ã¬ã¯ããªã ObjectDetection ãããžã§ã¯ã ãã£ã¬ã¯ããªã«ã³ããŒããŸãã ãã®ãã£ã¬ã¯ããªãšãã®ãµããã£ã¬ã¯ããªã«ã¯ããã®ãã¥ãŒããªã¢ã«ã«å¿ èŠãªã€ã¡ãŒãž ãã¡ã€ã« (æ¬¡ã®æé ã§ããŠã³ããŒãããŠè¿œå ãã Tiny YOLOv2 ã¢ãã«ãé€ã) ãå«ãŸããŠããŸããONNX Model Zoo ãã Tiny YOLOv2 ã¢ãã«ãããŠã³ããŒãããŸãã
model.onnxãã¡ã€ã«ã ObjectDetection ãããžã§ã¯ãassets\Modelãã£ã¬ã¯ããªã«ã³ããŒããååãTinyYolo2_model.onnxã«å€æŽããŸãã ãã®ãã£ã¬ã¯ããªã«ã¯ããã®ãã¥ãŒããªã¢ã«ã«å¿ èŠãªã¢ãã«ãå«ãŸããŠããŸãããœãªã¥ãŒã·ã§ã³ ãšã¯ã¹ãããŒã©ãŒã§ãè³ç£ãã£ã¬ã¯ããªãšãµããã£ã¬ã¯ããªå ã®åãã¡ã€ã«ãå³ã¯ãªãã¯ãã[ ããããã£] ãéžæããŸãã [ 詳现èšå®] ã§ã[ åºåãã£ã¬ã¯ããªã«ã³ã㌠] ã®å€ã [æ°ããå Žåã¯ã³ããŒ] ã«å€æŽããŸãã
ã¯ã©ã¹ã®äœæãšãã¹ã®å®çŸ©
Program.cs ãã¡ã€ã«ãéããæ¬¡ã®è¿œå ã®using ãã£ã¬ã¯ãã£ãããã¡ã€ã«ã®å
é ã«è¿œå ããŸãã
using System.Drawing;
using System.Drawing.Drawing2D;
using ObjectDetection.YoloParser;
using ObjectDetection.DataStructures;
using ObjectDetection;
using Microsoft.ML;
次ã«ãããŸããŸãªè³ç£ã®ãã¹ãå®çŸ©ããŸãã
ãŸãã
GetAbsolutePathäžéšã« ã¡ãœãããäœæããŸããstring GetAbsolutePath(string relativePath) { FileInfo _dataRoot = new FileInfo(typeof(Program).Assembly.Location); string assemblyFolderPath = _dataRoot.Directory.FullName; string fullPath = Path.Combine(assemblyFolderPath, relativePath); return fullPath; }次ã«ã
usingãã£ã¬ã¯ãã£ãã®äžã«ãè³ç£ã®å Žæãæ ŒçŽãããã£ãŒã«ããäœæããŸããvar assetsRelativePath = @"../../../assets"; string assetsPath = GetAbsolutePath(assetsRelativePath); var modelFilePath = Path.Combine(assetsPath, "Model", "TinyYolo2_model.onnx"); var imagesFolder = Path.Combine(assetsPath, "images"); var outputFolder = Path.Combine(assetsPath, "images", "output");
å ¥åããŒã¿ãšäºæž¬ã¯ã©ã¹ãæ ŒçŽããæ°ãããã£ã¬ã¯ããªããããžã§ã¯ãã«è¿œå ããŸãã
ãœãªã¥ãŒã·ã§ã³ ãšã¯ã¹ãããŒã©ãŒã§ããããžã§ã¯ããå³ã¯ãªãã¯ãã[远å >æ°ãããã©ã«ããŒ] ãéžæããŸãã ãœãªã¥ãŒã·ã§ã³ ãšã¯ã¹ãããŒã©ãŒã«æ°ãããã©ã«ããŒã衚瀺ããããã"DataStructures" ãšããååãä»ããŸãã
æ°ããäœæãã DataStructures ãã£ã¬ã¯ããªã«å ¥åããŒã¿ ã¯ã©ã¹ãäœæããŸãã
ãœãªã¥ãŒã·ã§ã³ ãšã¯ã¹ãããŒã©ãŒã§DataStructures ãã£ã¬ã¯ããªãå³ã¯ãªãã¯ãã>ãéžæããŸãã
[ æ°ããé ç®ã®è¿œå ] ãã€ã¢ãã° ããã¯ã¹ã§ã[ ã¯ã©ã¹ ] ãéžæãã[ åå ] ãã£ãŒã«ãã ImageNetData.csã«å€æŽããŸãã ãã®åŸã [远å ] ãéžæããŸãã
ImageNetData.cs ãã¡ã€ã«ãã³ãŒã ãšãã£ã¿ãŒã§éããŸãã æ¬¡ã®
usingãã£ã¬ã¯ãã£ãã ImageNetData.csã®å é ã«è¿œå ããŸããusing System.Collections.Generic; using System.IO; using System.Linq; using Microsoft.ML.Data;æ¢åã®ã¯ã©ã¹å®çŸ©ãåé€ãã
ImageNetDataã¯ã©ã¹ã®æ¬¡ã®ã³ãŒãã ImageNetData.cs ãã¡ã€ã«ã«è¿œå ããŸããpublic class ImageNetData { [LoadColumn(0)] public string ImagePath; [LoadColumn(1)] public string Label; public static IEnumerable<ImageNetData> ReadFromFile(string imageFolder) { return Directory .GetFiles(imageFolder) .Where(filePath => Path.GetExtension(filePath) != ".md") .Select(filePath => new ImageNetData { ImagePath = filePath, Label = Path.GetFileName(filePath) }); } }ImageNetDataã¯å ¥åã€ã¡ãŒãž ããŒã¿ ã¯ã©ã¹ã§ãããæ¬¡ã® String ãã£ãŒã«ãããããŸãã-
ImagePathã«ã¯ãã€ã¡ãŒãžãæ ŒçŽããããã¹ãå«ãŸããŠããŸãã -
Labelã«ã¯ããã¡ã€ã«ã®ååãå«ãŸããŠããŸãã
ããã«ã
ImageNetDataã«ã¯ãæå®ãããReadFromFileãã¹ã«æ ŒçŽãããŠããè€æ°ã®ã€ã¡ãŒãž ãã¡ã€ã«ãèªã¿èŸŒã¿ãimageFolderãªããžã§ã¯ãã®ã³ã¬ã¯ã·ã§ã³ãšããŠè¿ãã¡ãœããImageNetDataãå«ãŸããŠããŸãã-
DataStructures ãã£ã¬ã¯ããªã«äºæž¬ã¯ã©ã¹ãäœæããŸãã
ãœãªã¥ãŒã·ã§ã³ ãšã¯ã¹ãããŒã©ãŒã§DataStructures ãã£ã¬ã¯ããªãå³ã¯ãªãã¯ãã>ãéžæããŸãã
[ æ°ããé ç®ã®è¿œå ] ãã€ã¢ãã° ããã¯ã¹ã§ã[ ã¯ã©ã¹ ] ãéžæãã[ åå ] ãã£ãŒã«ãã ImageNetPrediction.csã«å€æŽããŸãã ãã®åŸã [远å ] ãéžæããŸãã
ImageNetPrediction.cs ãã¡ã€ã«ãã³ãŒã ãšãã£ã¿ãŒã§éããŸãã æ¬¡ã®
usingãã£ã¬ã¯ãã£ãã ImageNetPrediction.csã®å é ã«è¿œå ããŸããusing Microsoft.ML.Data;æ¢åã®ã¯ã©ã¹å®çŸ©ãåé€ãã
ImageNetPredictionã¯ã©ã¹ã®æ¬¡ã®ã³ãŒãã ImageNetPrediction.cs ãã¡ã€ã«ã«è¿œå ããŸããpublic class ImageNetPrediction { [ColumnName("grid")] public float[] PredictedLabels; }ImageNetPredictionã¯äºæž¬ããŒã¿ ã¯ã©ã¹ã§ãããæ¬¡ã®float[]ãã£ãŒã«ãããããŸãã-
PredictedLabelsã«ã¯ãç»åã§æ€åºãããåå¢çããã¯ã¹ã®å¯žæ³ããªããžã§ã¯ãæ§ã¹ã³ã¢ãããã³ã¯ã©ã¹ç¢ºçãå«ãŸããŸãã
-
倿°ã®åæå
MLContext ã¯ã©ã¹ã¯ããã¹ãŠã® ML.NET æäœã®éå§ç¹ã§ãããmlContextãåæåãããšãã¢ãã«äœæã¯ãŒã¯ãã㌠ãªããžã§ã¯ãéã§å
±æã§ããæ°ãã ML.NET ç°å¢ãäœæãããŸãã æŠå¿µçã«ã¯ãEntity Framework ã® DBContext ã«äŒŒãŠããŸãã
mlContext ãã£ãŒã«ãã®äžã«æ¬¡ã®è¡ã远å ããŠãMLContextã®æ°ããã€ã³ã¹ã¿ã³ã¹ã§outputFolder倿°ãåæåããŸãã
MLContext mlContext = new MLContext();
ã¢ãã«åºåãåŸåŠçããããã®ããŒãµãŒãäœæãã
ã¢ãã«ã¯ãç»åã 13 x 13 ã°ãªããã«ã»ã°ã¡ã³ãåããåã°ãªãã ã»ã«ã 32px x 32pxã åã°ãªãã ã»ã«ã«ã¯ãæå€§5ã€ã®ãªããžã§ã¯ãå¢çããã¯ã¹ãå«ãŸããŠããŸãã å¢çããã¯ã¹ã«ã¯ 25 åã®èŠçŽ ãå
å«ãããŠããŸãã
-
xé¢é£ä»ããããŠããã°ãªãã ã»ã«ãåºæºãšããå¢çããã¯ã¹ã®äžå¿ã® x äœçœ®ã -
yé¢é£ä»ããããŠããã°ãªãã ã»ã«ãåºæºãšããå¢çããã¯ã¹ã®äžå¿ã® y äœçœ®ã -
wå¢çããã¯ã¹ã®å¹ ã -
hå¢çããã¯ã¹ã®é«ãã -
oãªããžã§ã¯ããå¢çããã¯ã¹å ã«ååšããä¿¡é ŒåºŠå€ (ãªããžã§ã¯ããã¹ ã¹ã³ã¢ãšãåŒã°ããŸã)ã -
p1-p20ã¢ãã«ã«ãã£ãŠäºæž¬ããã 20 åã®åã¯ã©ã¹ã®ã¯ã©ã¹ç¢ºçã
åèšã§ã5 ã€ã®å¢çããã¯ã¹ãããããèšè¿°ãã 25 åã®èŠçŽ ããåã°ãªãã ã»ã«ã«å«ãŸãã 125 åã®èŠçŽ ãæ§æããŸãã
äºåãã¬ãŒãã³ã°æžã¿ã® ONNX ã¢ãã«ã«ãã£ãŠçæãããåºåã¯ã次å
ã21125ãã³ãœã«ã®èŠçŽ ã衚ããé·ã125 x 13 x 13ã® float é
åã§ãã ã¢ãã«ã«ãã£ãŠçæãããäºæž¬ããã³ãœã«ã«å€æããã«ã¯ãããã€ãã®åŸåŠçäœæ¥ãå¿
èŠã§ãã ãããè¡ãã«ã¯ãåºåã®è§£æã«åœ¹ç«ã€ã¯ã©ã¹ã®ã»ãããäœæããŸãã
æ°ãããã£ã¬ã¯ããªããããžã§ã¯ãã«è¿œå ããŠãããŒãµãŒ ã¯ã©ã¹ã®ã»ãããæŽçããŸãã
- ãœãªã¥ãŒã·ã§ã³ ãšã¯ã¹ãããŒã©ãŒã§ããããžã§ã¯ããå³ã¯ãªãã¯ãã[远å >æ°ãããã©ã«ããŒ] ãéžæããŸãã ãœãªã¥ãŒã·ã§ã³ ãšã¯ã¹ãããŒã©ãŒã«æ°ãããã©ã«ããŒã衚瀺ããããã"YoloParser" ãšããååãä»ããŸãã
å¢çããã¯ã¹ãšå¯žæ³ãäœæãã
ã¢ãã«ã«ãã£ãŠåºåãããããŒã¿ã«ã¯ãç»åå ã®ãªããžã§ã¯ãã®å¢çããã¯ã¹ã®åº§æšãšå¯žæ³ãå«ãŸããŠããŸãã ãã£ã¡ã³ã·ã§ã³ã®åºæ¬ã¯ã©ã¹ãäœæããŸãã
ãœãªã¥ãŒã·ã§ã³ ãšã¯ã¹ãããŒã©ãŒã§YoloParser ãã£ã¬ã¯ããªãå³ã¯ãªãã¯ãã>ãéžæããŸãã
[ æ°ããé ç®ã®è¿œå ] ãã€ã¢ãã° ããã¯ã¹ã§ã[ ã¯ã©ã¹ ] ãéžæãã[ åå ] ãã£ãŒã«ãã DimensionsBase.csã«å€æŽããŸãã ãã®åŸã [远å ] ãéžæããŸãã
DimensionsBase.cs ãã¡ã€ã«ãã³ãŒã ãšãã£ã¿ãŒã§éããŸãã ãã¹ãŠã®
usingãã£ã¬ã¯ãã£ããšæ¢åã®ã¯ã©ã¹å®çŸ©ãåé€ããŸããDimensionsBaseã¯ã©ã¹ã®æ¬¡ã®ã³ãŒããDimensionsBase.cs ãã¡ã€ã«ã«è¿œå ããŸããpublic class DimensionsBase { public float X { get; set; } public float Y { get; set; } public float Height { get; set; } public float Width { get; set; } }DimensionsBaseã«ã¯ã次ã®floatããããã£ããããŸãã-
Xã«ã¯ãx è»žã«æ²¿ã£ããªããžã§ã¯ãã®äœçœ®ãå«ãŸããŸãã -
Yã«ã¯ãy è»žã«æ²¿ã£ããªããžã§ã¯ãã®äœçœ®ãå«ãŸããŸãã -
Heightã«ã¯ããªããžã§ã¯ãã®é«ããå«ãŸããŠããŸãã -
Widthã«ã¯ããªããžã§ã¯ãã®å¹ ãå«ãŸããŠããŸãã
-
次ã«ãå¢çããã¯ã¹ã®ã¯ã©ã¹ãäœæããŸãã
ãœãªã¥ãŒã·ã§ã³ ãšã¯ã¹ãããŒã©ãŒã§YoloParser ãã£ã¬ã¯ããªãå³ã¯ãªãã¯ãã>ãéžæããŸãã
[ æ°ããé ç®ã®è¿œå ] ãã€ã¢ãã° ããã¯ã¹ã§ã[ ã¯ã©ã¹ ] ãéžæãã[ åå ] ãã£ãŒã«ãã YoloBoundingBox.csã«å€æŽããŸãã ãã®åŸã [远å ] ãéžæããŸãã
YoloBoundingBox.cs ãã¡ã€ã«ãã³ãŒã ãšãã£ã¿ãŒã§éããŸãã æ¬¡ã®
usingãã£ã¬ã¯ãã£ãã YoloBoundingBox.csã®å é ã«è¿œå ããŸããusing System.Drawing;æ¢åã®ã¯ã©ã¹å®çŸ©ã®ããäžã«ã
BoundingBoxDimensionsã¯ã©ã¹ããç¶æ¿ããDimensionsBaseãšããååã®æ°ããã¯ã©ã¹å®çŸ©ã远å ããŠãããããã®å¢çããã¯ã¹ã®æ¬¡å ãæ ŒçŽããŸããpublic class BoundingBoxDimensions : DimensionsBase { }æ¢åã®
YoloBoundingBoxã¯ã©ã¹å®çŸ©ãåé€ããYoloBoundingBoxã¯ã©ã¹ã®æ¬¡ã®ã³ãŒãã YoloBoundingBox.cs ãã¡ã€ã«ã«è¿œå ããŸããpublic class YoloBoundingBox { public BoundingBoxDimensions Dimensions { get; set; } public string Label { get; set; } public float Confidence { get; set; } public RectangleF Rect { get { return new RectangleF(Dimensions.X, Dimensions.Y, Dimensions.Width, Dimensions.Height); } } public Color BoxColor { get; set; } }YoloBoundingBoxã«ã¯ã次ã®ããããã£ããããŸãã-
Dimensionsã«ã¯å¢çããã¯ã¹ã®å¯žæ³ãå«ãŸããŠããŸãã -
Labelã«ã¯ãå¢çããã¯ã¹å ã§æ€åºããããªããžã§ã¯ãã®ã¯ã©ã¹ãå«ãŸããŠããŸãã -
Confidenceã«ã¯ãã¯ã©ã¹ã®ä¿¡é ŒåºŠãå«ãŸããŠããŸãã -
Rectã«ã¯ãå¢çããã¯ã¹ã®å¯žæ³ã®åè§åœ¢è¡šçŸãå«ãŸããŸãã -
BoxColorã«ã¯ãã€ã¡ãŒãžã«æç»ããããã«äœ¿çšãããããããã®ã¯ã©ã¹ã«é¢é£ä»ããããŠããè²ãå«ãŸããŠããŸãã
-
ããŒãµãŒãäœæãã
ãã£ã¡ã³ã·ã§ã³ãšå¢çããã¯ã¹ã®ã¯ã©ã¹ãäœæãããã®ã§ãããŒãµãŒãäœæããŸãã
ãœãªã¥ãŒã·ã§ã³ ãšã¯ã¹ãããŒã©ãŒã§YoloParser ãã£ã¬ã¯ããªãå³ã¯ãªãã¯ãã>ãéžæããŸãã
[ æ°ããé ç®ã®è¿œå ] ãã€ã¢ãã° ããã¯ã¹ã§ã[ ã¯ã©ã¹ ] ãéžæãã[ åå ] ãã£ãŒã«ãã YoloOutputParser.csã«å€æŽããŸãã ãã®åŸã [远å ] ãéžæããŸãã
YoloOutputParser.cs ãã¡ã€ã«ãã³ãŒã ãšãã£ã¿ãŒã§éããŸãã YoloOutputParser.csã®å é ã«æ¬¡ã®
usingãã£ã¬ã¯ãã£ãã远å ããŸããusing System; using System.Collections.Generic; using System.Drawing; using System.Linq;æ¢åã®
YoloOutputParserã¯ã©ã¹å®çŸ©å ã«ãç»åå ã®åã»ã«ã®å¯žæ³ãå«ãå ¥ãåã«ãªã£ãã¯ã©ã¹ã远å ããŸããCellDimensionsã¯ã©ã¹å®çŸ©ã®å é ã«ããDimensionsBaseã¯ã©ã¹ããç¶æ¿ããYoloOutputParserã¯ã©ã¹ã®æ¬¡ã®ã³ãŒãã远å ããŸããclass CellDimensions : DimensionsBase { }YoloOutputParserã¯ã©ã¹å®çŸ©å ã«ã次ã®å®æ°ãšãã£ãŒã«ãã远å ããŸããpublic const int ROW_COUNT = 13; public const int COL_COUNT = 13; public const int CHANNEL_COUNT = 125; public const int BOXES_PER_CELL = 5; public const int BOX_INFO_FEATURE_COUNT = 5; public const int CLASS_COUNT = 20; public const float CELL_WIDTH = 32; public const float CELL_HEIGHT = 32; private int channelStride = ROW_COUNT * COL_COUNT;-
ROW_COUNTã¯ãç»åãåå²ãããŠããã°ãªããå ã®è¡æ°ã§ãã -
COL_COUNTã¯ãç»åãåå²ãããŠããã°ãªããå ã®åã®æ°ã§ãã -
CHANNEL_COUNTã¯ãã°ãªããã® 1 ã€ã®ã»ã«ã«å«ãŸããå€ã®åèšæ°ã§ãã -
BOXES_PER_CELLã¯ãã»ã«å ã®å¢çããã¯ã¹ã®æ°ã§ãã -
BOX_INFO_FEATURE_COUNTã¯ãããã¯ã¹å ã«å«ãŸããç¹åŸŽã®æ° (xãyãé«ããå¹ ãä¿¡é ŒåºŠ) ã§ãã -
CLASS_COUNTã¯ãåå¢çããã¯ã¹ã«å«ãŸããã¯ã©ã¹äºæž¬ã®æ°ã§ãã -
CELL_WIDTHã¯ãã€ã¡ãŒãž ã°ãªããå ã® 1 ã€ã®ã»ã«ã®å¹ ã§ãã -
CELL_HEIGHTã¯ãã€ã¡ãŒãž ã°ãªããå ã® 1 ã€ã®ã»ã«ã®é«ãã§ãã -
channelStrideã¯ãã°ãªããå ã®çŸåšã®ã»ã«ã®éå§äœçœ®ã§ãã
ã¢ãã«ã¯ãã¹ã³ã¢ãªã³ã°ãšãåŒã°ããäºæž¬ãè¡ããšã
416px x 416pxå ¥åç»åã13 x 13ã®ãµã€ãºã®ã»ã«ã®ã°ãªããã«åå²ããŸãã åã»ã«ã«ã¯ã32px x 32pxãå«ãŸããŠããŸãã åã»ã«å ã«ã¯ããããã 5 ã€ã®ç¹åŸŽ (xãyãå¹ ãé«ããä¿¡é ŒåºŠ) ãå«ã 5 ã€ã®å¢çããã¯ã¹ããããŸãã ããã«ãåå¢çããã¯ã¹ã«ã¯åã¯ã©ã¹ã®ç¢ºçãå«ãŸããŸãããã®å Žå㯠20 ã§ãã ãããã£ãŠãåã»ã«ã«ã¯ 125 åã®æ å ± (5 ã€ã®ç¹åŸŽ + 20 åã®ã¯ã©ã¹ç¢ºç) ãå«ãŸããŠããŸãã-
5 ã€ã®å¢çããã¯ã¹ãã¹ãŠã«å¯ŸããŠã channelStride ã®äžã«ã¢ã³ã«ãŒã®äžèЧãäœæããŸãã
private float[] anchors = new float[]
{
1.08F, 1.19F, 3.42F, 4.41F, 6.63F, 11.38F, 9.42F, 5.11F, 16.62F, 10.52F
};
ã¢ã³ã«ãŒã¯ãå¢çããã¯ã¹ã®å®çŸ©æžã¿ã®é«ããšå¹ ã®æ¯çã§ãã ã¢ãã«ã«ãã£ãŠæ€åºãããã»ãšãã©ã®ãªããžã§ã¯ããŸãã¯ã¯ã©ã¹ã®æ¯çã¯äŒŒãŠããŸãã ããã¯ãå¢çããã¯ã¹ãäœæããå Žåã«éèŠã§ãã å¢çããã¯ã¹ãäºæž¬ãã代ããã«ãå®çŸ©æžã¿ã®ãã£ã¡ã³ã·ã§ã³ããã®ãªãã»ãããèšç®ããããããå¢çããã¯ã¹ãäºæž¬ããããã«å¿ èŠãªèšç®ãæžããŸãã éåžžããããã®ã¢ã³ã«ãŒæ¯çã¯ã䜿çšãããããŒã¿ã»ããã«åºã¥ããŠèšç®ãããŸãã ãã®å ŽåãããŒã¿ã»ãããæ¢ç¥ã§ãããå€ãäºåèšç®ãããŠãããããã¢ã³ã«ãŒãããŒãã³ãŒãã£ã³ã°ã§ããŸãã
次ã«ãã¢ãã«ãäºæž¬ããã©ãã«ãŸãã¯ã¯ã©ã¹ãå®çŸ©ããŸãã ãã®ã¢ãã«ã§ã¯ã20 åã®ã¯ã©ã¹ãäºæž¬ãããŸããããã¯ãå ã® YOLOv2 ã¢ãã«ã«ãã£ãŠäºæž¬ãããã¯ã©ã¹ã®åèšæ°ã®ãµãã»ããã§ãã
anchorsã®äžã«ã©ãã«ã®äžèЧã远å ããŸãã
private string[] labels = new string[]
{
"aeroplane", "bicycle", "bird", "boat", "bottle",
"bus", "car", "cat", "chair", "cow",
"diningtable", "dog", "horse", "motorbike", "person",
"pottedplant", "sheep", "sofa", "train", "tvmonitor"
};
åã¯ã©ã¹ã«é¢é£ä»ããããŠããè²ããããŸãã
labelsã®äžã«ã¯ã©ã¹ã®è²ãå²ãåœãŠãŸãã
private static Color[] classColors = new Color[]
{
Color.Khaki,
Color.Fuchsia,
Color.Silver,
Color.RoyalBlue,
Color.Green,
Color.DarkOrange,
Color.Purple,
Color.Gold,
Color.Red,
Color.Aquamarine,
Color.Lime,
Color.AliceBlue,
Color.Sienna,
Color.Orchid,
Color.Tan,
Color.LightPink,
Color.Yellow,
Color.HotPink,
Color.OliveDrab,
Color.SandyBrown,
Color.DarkTurquoise
};
ãã«ããŒé¢æ°ãäœæãã
åŸåŠçãã§ãŒãºã«ã¯äžé£ã®æé ãå«ãŸããŸãã ãã®ããã«ã¯ãããã€ãã®ãã«ã㌠ã¡ãœããã䜿çšã§ããŸãã
ããŒãµãŒã§äœ¿çšããããã«ã㌠ã¡ãœããã¯æ¬¡ã®ãšããã§ãã
-
Sigmoidã¯ã0 ~ 1 ã®æ°å€ãåºåããã·ã°ã¢ã€ã颿°ãé©çšããŸãã -
Softmaxã¯ãå ¥åãã¯ãã«ã確çååžã«æ£èŠåããŸãã -
GetOffsetã¯ã1 次å ã¢ãã«åºåã®èŠçŽ ãã125 x 13 x 13ãã³ãœã«å ã®å¯Ÿå¿ããäœçœ®ã«ãããããŸãã -
ExtractBoundingBoxesã§ã¯ãã¢ãã«åºåããGetOffsetã¡ãœããã䜿çšããŠå¢çããã¯ã¹ãã£ã¡ã³ã·ã§ã³ãæœåºããŸãã -
GetConfidenceã¯ãã¢ãã«ããªããžã§ã¯ããæ€åºããSigmoid颿°ã䜿çšããŠãããããŒã»ã³ããŒãžã«å€æããæ¹æ³ã瀺ãä¿¡é ŒåºŠå€ãæœåºããŸãã -
MapBoundingBoxToCellã¯å¢çããã¯ã¹ã®å¯žæ³ã䜿çšããç»åå ã®ããããã®ã»ã«ã«ãããããŸãã -
ExtractClassesã¯ãGetOffsetã¡ãœããã䜿çšããŠã¢ãã«åºåããå¢çããã¯ã¹ã®ã¯ã©ã¹äºæž¬ãæœåºããSoftmaxã¡ãœããã䜿çšããŠç¢ºçååžã«å€æããŸãã -
GetTopResultã¯ãæãé«ã確çã§äºæž¬ãããã¯ã©ã¹ã®äžèЧããã¯ã©ã¹ãéžæããŸãã -
IntersectionOverUnionã¯ã確çãäœãå¢çããã¯ã¹ãéããŠãã£ã«ã¿ãŒåŠçããŸãã
classColorsã®äžèЧã®äžã«ããã¹ãŠã®ãã«ã㌠ã¡ãœããã®ã³ãŒãã远å ããŸãã
private float Sigmoid(float value)
{
var k = (float)Math.Exp(value);
return k / (1.0f + k);
}
private float[] Softmax(float[] values)
{
var maxVal = values.Max();
var exp = values.Select(v => Math.Exp(v - maxVal));
var sumExp = exp.Sum();
return exp.Select(v => (float)(v / sumExp)).ToArray();
}
private int GetOffset(int x, int y, int channel)
{
// YOLO outputs a tensor that has a shape of 125x13x13, which
// WinML flattens into a 1D array. To access a specific channel
// for a given (x,y) cell position, we need to calculate an offset
// into the array
return (channel * this.channelStride) + (y * COL_COUNT) + x;
}
private BoundingBoxDimensions ExtractBoundingBoxDimensions(float[] modelOutput, int x, int y, int channel)
{
return new BoundingBoxDimensions
{
X = modelOutput[GetOffset(x, y, channel)],
Y = modelOutput[GetOffset(x, y, channel + 1)],
Width = modelOutput[GetOffset(x, y, channel + 2)],
Height = modelOutput[GetOffset(x, y, channel + 3)]
};
}
private float GetConfidence(float[] modelOutput, int x, int y, int channel)
{
return Sigmoid(modelOutput[GetOffset(x, y, channel + 4)]);
}
private CellDimensions MapBoundingBoxToCell(int x, int y, int box, BoundingBoxDimensions boxDimensions)
{
return new CellDimensions
{
X = ((float)x + Sigmoid(boxDimensions.X)) * CELL_WIDTH,
Y = ((float)y + Sigmoid(boxDimensions.Y)) * CELL_HEIGHT,
Width = (float)Math.Exp(boxDimensions.Width) * CELL_WIDTH * anchors[box * 2],
Height = (float)Math.Exp(boxDimensions.Height) * CELL_HEIGHT * anchors[box * 2 + 1],
};
}
public float[] ExtractClasses(float[] modelOutput, int x, int y, int channel)
{
float[] predictedClasses = new float[CLASS_COUNT];
int predictedClassOffset = channel + BOX_INFO_FEATURE_COUNT;
for (int predictedClass = 0; predictedClass < CLASS_COUNT; predictedClass++)
{
predictedClasses[predictedClass] = modelOutput[GetOffset(x, y, predictedClass + predictedClassOffset)];
}
return Softmax(predictedClasses);
}
private ValueTuple<int, float> GetTopResult(float[] predictedClasses)
{
return predictedClasses
.Select((predictedClass, index) => (Index: index, Value: predictedClass))
.OrderByDescending(result => result.Value)
.First();
}
private float IntersectionOverUnion(RectangleF boundingBoxA, RectangleF boundingBoxB)
{
var areaA = boundingBoxA.Width * boundingBoxA.Height;
if (areaA <= 0)
return 0;
var areaB = boundingBoxB.Width * boundingBoxB.Height;
if (areaB <= 0)
return 0;
var minX = Math.Max(boundingBoxA.Left, boundingBoxB.Left);
var minY = Math.Max(boundingBoxA.Top, boundingBoxB.Top);
var maxX = Math.Min(boundingBoxA.Right, boundingBoxB.Right);
var maxY = Math.Min(boundingBoxA.Bottom, boundingBoxB.Bottom);
var intersectionArea = Math.Max(maxY - minY, 0) * Math.Max(maxX - minX, 0);
return intersectionArea / (areaA + areaB - intersectionArea);
}
ãã¹ãŠã®ãã«ã㌠ã¡ãœãããå®çŸ©ãããããããã䜿çšããŠã¢ãã«ã®åºåãåŠçããŸãã
IntersectionOverUnion ã¡ãœããã®äžã«ãã¢ãã«ã«ãã£ãŠçæãããåºåãåŠçããParseOutputs ã¡ãœãããäœæããŸãã
public IList<YoloBoundingBox> ParseOutputs(float[] yoloModelOutputs, float threshold = .3F)
{
}
å¢çããã¯ã¹ãæ ŒçŽãã ParseOutputs ã¡ãœããå
ã«å€æ°ãå®çŸ©ãããªã¹ããäœæããŸãã
var boxes = new List<YoloBoundingBox>();
åç»åã¯ã 13 x 13 ã»ã«ã®ã°ãªããã«åå²ãããŸãã åã»ã«ã«ã¯ã5 ã€ã®å¢çããã¯ã¹ãå«ãŸããŠããŸãã
boxes倿°ã®äžã«ãåã»ã«ã®ãã¹ãŠã®ããã¯ã¹ãåŠçããã³ãŒãã远å ããŸãã
for (int row = 0; row < ROW_COUNT; row++)
{
for (int column = 0; column < COL_COUNT; column++)
{
for (int box = 0; box < BOXES_PER_CELL; box++)
{
}
}
}
æãå åŽã®ã«ãŒãå ã§ã1 次å ã¢ãã«åºåå ã®çŸåšã®ããã¯ã¹ã®éå§äœçœ®ãèšç®ããŸãã
var channel = (box * (CLASS_COUNT + BOX_INFO_FEATURE_COUNT));
ãã®çäžã§ã ExtractBoundingBoxDimensions ã¡ãœããã䜿çšããŠãçŸåšã®å¢çããã¯ã¹ã®å¯žæ³ãååŸããŸãã
BoundingBoxDimensions boundingBoxDimensions = ExtractBoundingBoxDimensions(yoloModelOutputs, row, column, channel);
次ã«ã GetConfidence ã¡ãœããã䜿çšããŠãçŸåšã®å¢çããã¯ã¹ã®ä¿¡é ŒåºŠãååŸããŸãã
float confidence = GetConfidence(yoloModelOutputs, row, column, channel);
ãã®åŸã MapBoundingBoxToCell ã¡ãœããã䜿çšããŠãçŸåšã®å¢çããã¯ã¹ãåŠçäžã®çŸåšã®ã»ã«ã«ãããããŸãã
CellDimensions mappedBoundingBox = MapBoundingBoxToCell(row, column, box, boundingBoxDimensions);
ãã以äžã®åŠçãè¡ãåã«ãä¿¡é ŒåºŠã®å€ãæå®ããããããå€ãè¶ ããŠãããã©ããã確èªããŸãã ããã§ãªãå Žåã¯ã次ã®ããŠã³ãã£ã³ã°ããã¯ã¹ãåŠçããŸãã
if (confidence < threshold)
continue;
ãã以å€ã®å Žåã¯ãåºåã®åŠçãç¶è¡ããŸãã æ¬¡ã®æé ã§ã¯ã ExtractClasses ã¡ãœããã䜿çšããŠãçŸåšã®å¢çããã¯ã¹ã®äºæž¬ã¯ã©ã¹ã®ç¢ºçååžãååŸããŸãã
float[] predictedClasses = ExtractClasses(yoloModelOutputs, row, column, channel);
次ã«ã GetTopResult ã¡ãœããã䜿çšããŠãçŸåšã®ããã¯ã¹ã®ç¢ºçãæãé«ãã¯ã©ã¹ã®å€ãšã€ã³ããã¯ã¹ãååŸãããã®ã¹ã³ã¢ãèšç®ããŸãã
var (topResultIndex, topResultScore) = GetTopResult(predictedClasses);
var topScore = topResultScore * confidence;
topScoreã䜿çšããŠãæå®ãããããå€ãè¶
ããå¢çããã¯ã¹ã®ã¿ãä¿æãçŽããŸãã
if (topScore < threshold)
continue;
æåŸã«ãçŸåšã®å¢çããã¯ã¹ããããå€ãè¶
ããå Žåã¯ãæ°ãã BoundingBox ãªããžã§ã¯ããäœæãã boxes ãªã¹ãã«è¿œå ããŸãã
boxes.Add(new YoloBoundingBox()
{
Dimensions = new BoundingBoxDimensions
{
X = (mappedBoundingBox.X - mappedBoundingBox.Width / 2),
Y = (mappedBoundingBox.Y - mappedBoundingBox.Height / 2),
Width = mappedBoundingBox.Width,
Height = mappedBoundingBox.Height,
},
Confidence = topScore,
Label = labels[topResultIndex],
BoxColor = classColors[topResultIndex]
});
ç»åå
ã®ãã¹ãŠã®ã»ã«ãåŠçããããã boxes ãªã¹ããè¿ããŸãã æ¬¡ã® return ã¹ããŒãã¡ã³ããã ParseOutputs ã¡ãœããã®æãå€åŽã® for ã«ãŒãã®äžã«è¿œå ããŸãã
return boxes;
éãªãåãããã¯ã¹ããã£ã«ã¿ãŒåŠçãã
ä¿¡é Œæ§ã®é«ãå¢çããã¯ã¹ããã¹ãŠã¢ãã«åºåããæœåºãããã®ã§ãéãªã£ãŠããç»åãåé€ããã«ã¯ã远å ã®ãã£ã«ã¿ãŒåŠçãè¡ãå¿
èŠããããŸãã
FilterBoundingBoxes ã¡ãœããã®äžã« ParseOutputs ãšããã¡ãœããã远å ããŸãã
public IList<YoloBoundingBox> FilterBoundingBoxes(IList<YoloBoundingBox> boxes, int limit, float threshold)
{
}
FilterBoundingBoxesã¡ãœããå
ã§ã¯ããŸããæ€åºãããããã¯ã¹ã®ãµã€ãºãšçããé
åãäœæãããã¹ãŠã®ã¹ããããã¢ã¯ãã£ããŸãã¯åŠçã®æºåãã§ããŠãããã®ãšããŠããŒã¯ããŸãã
var activeCount = boxes.Count;
var isActiveBoxes = new bool[boxes.Count];
for (int i = 0; i < isActiveBoxes.Length; i++)
isActiveBoxes[i] = true;
次ã«ãå¢çããã¯ã¹ãå«ããªã¹ããä¿¡é ŒåºŠã«åºã¥ããŠéé ã«äžŠã¹æ¿ããŸãã
var sortedBoxes = boxes.Select((b, i) => new { Box = b, Index = i })
.OrderByDescending(b => b.Box.Confidence)
.ToList();
ãã®åŸããã£ã«ã¿ãŒåŠçãããçµæãä¿æãããªã¹ããäœæããŸãã
var results = new List<YoloBoundingBox>();
åå¢çããã¯ã¹ãå埩åŠçããŠãåå¢çããã¯ã¹ã®åŠçãéå§ããŸãã
for (int i = 0; i < boxes.Count; i++)
{
}
ãã® for ã«ãŒãå ã§ãçŸåšã®ããŠã³ãã£ã³ã°ããã¯ã¹ãåŠçã§ãããã©ããã確èªããŸãã
if (isActiveBoxes[i])
{
}
ãã®å Žåã¯ãå¢çããã¯ã¹ãçµæã®äžèЧã«è¿œå ããŸãã çµæãæœåºããããã¯ã¹ã®æå®ãããå¶éãè¶ ããå Žåã¯ãã«ãŒãããæãåºããŸãã if ã¹ããŒãã¡ã³ãå ã«æ¬¡ã®ã³ãŒãã远å ããŸãã
var boxA = sortedBoxes[i].Box;
results.Add(boxA);
if (results.Count >= limit)
break;
ãã以å€ã®å Žåã¯ã飿¥ããå¢çããã¯ã¹ãèŠãŠãã ããã ããã¯ã¹å¶éãã§ãã¯ã®äžã«æ¬¡ã®ã³ãŒãã远å ããŸãã
for (var j = i + 1; j < boxes.Count; j++)
{
}
1 ã€ç®ã®ããã¯ã¹ãšåæ§ã«ã飿¥ããããã¯ã¹ãã¢ã¯ãã£ãã§ããããåŠçããæºåãã§ããŠããå Žåã¯ã IntersectionOverUnion ã¡ãœããã䜿çšããŠãæåã®ããã¯ã¹ãš 2 çªç®ã®ããã¯ã¹ãæå®ããããããå€ãè¶
ããŠãããã©ããã確èªããŸãã æãå
åŽã® for ã«ãŒãã«æ¬¡ã®ã³ãŒãã远å ããŸãã
if (isActiveBoxes[j])
{
var boxB = sortedBoxes[j].Box;
if (IntersectionOverUnion(boxA.Rect, boxB.Rect) > threshold)
{
isActiveBoxes[j] = false;
activeCount--;
if (activeCount <= 0)
break;
}
}
飿¥ããå¢çããã¯ã¹ããã§ãã¯ããæãå åŽã® for ã«ãŒãã®å€åŽã§ãåŠçããå¢çããã¯ã¹ãæ®ã£ãŠãããã©ããã確èªããŸãã ããã§ãªãå Žåã¯ãå€åŽã® for ã«ãŒãããæãåºããŸãã
if (activeCount <= 0)
break;
æåŸã«ã FilterBoundingBoxes ã¡ãœããã®æåã® for ã«ãŒãã®å€åŽã§ãçµæãè¿ããŸãã
return results;
ãããïŒ æ¬¡ã«ããã®ã³ãŒããã¹ã³ã¢ãªã³ã°çšã®ã¢ãã«ãšå ±ã«äœ¿çšããŸãã
ã¹ã³ã¢ãªã³ã°ã«ã¢ãã«ã䜿çšãã
åŸåŠçãšåæ§ã«ãã¹ã³ã¢ä»ãæé ã«ã¯ããã€ãã®æé ããããŸãã ãããæ¯æŽããã«ã¯ãã¹ã³ã¢ä»ãããžãã¯ãå«ãã¯ã©ã¹ããããžã§ã¯ãã«è¿œå ããŸãã
ãœãªã¥ãŒã·ã§ã³ ãšã¯ã¹ãããŒã©ãŒã§ãããžã§ã¯ããå³ã¯ãªãã¯ãã[远å ]ã[>ãéžæããŸãã
[ æ°ããé ç®ã®è¿œå ] ãã€ã¢ãã° ããã¯ã¹ã§ã[ ã¯ã©ã¹ ] ãéžæãã[ åå ] ãã£ãŒã«ãã OnnxModelScorer.csã«å€æŽããŸãã ãã®åŸã [远å ] ãéžæããŸãã
OnnxModelScorer.cs ãã¡ã€ã«ãã³ãŒã ãšãã£ã¿ãŒã§éããŸãã æ¬¡ã®
usingãã£ã¬ã¯ãã£ãã OnnxModelScorer.csã®å é ã«è¿œå ããŸããusing System; using System.Collections.Generic; using System.Linq; using Microsoft.ML; using Microsoft.ML.Data; using ObjectDetection.DataStructures; using ObjectDetection.YoloParser;OnnxModelScorerã¯ã©ã¹å®çŸ©å ã«ã次ã®å€æ°ã远å ããŸããprivate readonly string imagesFolder; private readonly string modelLocation; private readonly MLContext mlContext; private IList<YoloBoundingBox> _boundingBoxes = new List<YoloBoundingBox>();ãã®çŽäžã«ãåã«å®çŸ©ãã倿°ãåæåãã
OnnxModelScorerã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãŒãäœæããŸããpublic OnnxModelScorer(string imagesFolder, string modelLocation, MLContext mlContext) { this.imagesFolder = imagesFolder; this.modelLocation = modelLocation; this.mlContext = mlContext; }ã³ã³ã¹ãã©ã¯ã¿ãŒãäœæããããã€ã¡ãŒãžãšã¢ãã«ã®èšå®ã«é¢é£ãã倿°ãå«ãæ§é äœãããã€ãå®çŸ©ããŸãã ã¢ãã«ã®å ¥åãšããŠæåŸ ãããé«ããšå¹ ãæ ŒçŽããããã«ã
ImageNetSettingsãšããæ§é äœãäœæããŸããpublic struct ImageNetSettings { public const int imageHeight = 416; public const int imageWidth = 416; }ãã®åŸãã¢ãã«ã®å ¥åã¬ã€ã€ãŒãšåºåã¬ã€ã€ãŒã®ååãå«ã
TinyYoloModelSettingsãšããå¥ã®æ§é äœãäœæããŸãã ã¢ãã«ã®å ¥åã¬ã€ã€ãŒãšåºåã¬ã€ã€ãŒã®ååãèŠèŠåããã«ã¯ã Netron ãªã©ã®ããŒã«ã䜿çšã§ããŸããpublic struct TinyYoloModelSettings { // for checking Tiny yolo2 Model input and output parameter names, //you can use tools like Netron, // which is installed by Visual Studio AI Tools // input tensor name public const string ModelInput = "image"; // output tensor name public const string ModelOutput = "grid"; }次ã«ãã¹ã³ã¢ãªã³ã°ã«äœ¿çšããã¡ãœããã®æåã®ã»ãããäœæããŸãã
LoadModelã¯ã©ã¹å ã«OnnxModelScorerã¡ãœãããäœæããŸããprivate ITransformer LoadModel(string modelLocation) { }LoadModelã¡ãœããå ã«ããã°èšé²çšã®æ¬¡ã®ã³ãŒãã远å ããŸããConsole.WriteLine("Read model"); Console.WriteLine($"Model location: {modelLocation}"); Console.WriteLine($"Default parameters: image size=({ImageNetSettings.imageWidth},{ImageNetSettings.imageHeight})");ML.NET ãã€ãã©ã€ã³ã¯ã
Fitã¡ãœãããåŒã³åºããããšãã«æäœããããŒã¿ ã¹ããŒããèªèããå¿ èŠããããŸãã ãã®å Žåããã¬ãŒãã³ã°ãšåæ§ã®ããã»ã¹ã䜿çšãããŸãã ãã ããå®éã®ãã¬ãŒãã³ã°ã¯è¡ãããŸããã®ã§ã空ã®IDataViewã䜿çšããŠãããŸããŸããã 空ã®ãªã¹ããããã€ãã©ã€ã³ã®æ°ããIDataViewãäœæããŸããvar data = mlContext.Data.LoadFromEnumerable(new List<ImageNetData>());ãã®äžã§ããã€ãã©ã€ã³ãå®çŸ©ããŸãã ãã€ãã©ã€ã³ã¯ 4 ã€ã®å€æã§æ§æãããŸãã
-
LoadImagesã¯ãã€ã¡ãŒãžããããããããšããŠèªã¿èŸŒã¿ãŸãã -
ResizeImagesã¯ãæå®ããããµã€ãº (ãã®å Žåã¯416 x 416) ã«ã€ã¡ãŒãžãåã¹ã±ãŒãªã³ã°ããŸãã -
ExtractPixelsã¯ãã€ã¡ãŒãžã®ãã¯ã»ã«è¡šçŸãããããããããæ°å€ãã¯ã¿ãŒã«å€æŽããŸãã -
ApplyOnnxModel㯠ONNX ã¢ãã«ãèªã¿èŸŒã¿ãããã䜿çšããŠæäŸãããããŒã¿ã«ã¹ã³ã¢ãä»ããŸãã
Important
ä¿¡é Œã§ãããœãŒã¹ããã®ã¢ãã«ã®ã¿ãé©çšããŸãã ä¿¡é ŒãããŠããªããœãŒã¹ããã¢ãã«ãé©çšããããšã¯ãã»ãã¥ãªã㣠äžã®ãªã¹ã¯ã§ãã
LoadModel倿°ã®äžã®dataã¡ãœããã§ãã€ãã©ã€ã³ãå®çŸ©ããŸããvar pipeline = mlContext.Transforms.LoadImages(outputColumnName: "image", imageFolder: "", inputColumnName: nameof(ImageNetData.ImagePath)) .Append(mlContext.Transforms.ResizeImages(outputColumnName: "image", imageWidth: ImageNetSettings.imageWidth, imageHeight: ImageNetSettings.imageHeight, inputColumnName: "image")) .Append(mlContext.Transforms.ExtractPixels(outputColumnName: "image")) .Append(mlContext.Transforms.ApplyOnnxModel(modelFile: modelLocation, outputColumnNames: new[] { TinyYoloModelSettings.ModelOutput }, inputColumnNames: new[] { TinyYoloModelSettings.ModelInput }));次ã«ãã¹ã³ã¢ãªã³ã°ã®ããã«ã¢ãã«ãã€ã³ã¹ã¿ã³ã¹åããŸãã ãã€ãã©ã€ã³ã§
Fitã¡ãœãããåŒã³åºããããã«åŠçããããã«ãããè¿ããŸããvar model = pipeline.Fit(data); return model;-
ã¢ãã«ãèªã¿èŸŒãŸããããããã䜿çšããŠäºæž¬ãè¡ãããšãã§ããŸãã ãã®ããã»ã¹ã容æã«ããããã«ãPredictDataUsingModel ã¡ãœããã®äžã« LoadModel ãšããã¡ãœãããäœæããŸãã
private IEnumerable<float[]> PredictDataUsingModel(IDataView testData, ITransformer model)
{
}
PredictDataUsingModelå
ã«ããã°èšé²çšã®æ¬¡ã®ã³ãŒãã远å ããŸãã
Console.WriteLine($"Images location: {imagesFolder}");
Console.WriteLine("");
Console.WriteLine("=====Identify the objects in the images=====");
Console.WriteLine("");
次ã«ã Transform ã¡ãœããã䜿çšããŠããŒã¿ãã¹ã³ã¢ä»ãããŸãã
IDataView scoredData = model.Transform(testData);
äºæž¬ããã確çãæœåºãã远å åŠçã®ããã«è¿ããŸãã
IEnumerable<float[]> probabilities = scoredData.GetColumn<float[]>(TinyYoloModelSettings.ModelOutput);
return probabilities;
äž¡æ¹ã®æé ãèšå®ãããã®ã§ããããã 1 ã€ã®ã¡ãœããã«çµåããŸãã
PredictDataUsingModel ã¡ãœããã®äžã«ãScoreãšããååã®æ°ããã¡ãœããã远å ããŸãã
public IEnumerable<float[]> Score(IDataView data)
{
var model = LoadModel(modelLocation);
return PredictDataUsingModel(data, model);
}
ããããã§ãïŒ ä»ããããã¹ãŠã掻çšãããšãã§ãã
ãªããžã§ã¯ããæ€åºãã
ãã¹ãŠã®ã»ããã¢ãããå®äºããããããã€ãã®ãªããžã§ã¯ããæ€åºããŸãã
ã¢ãã«åºåã®ã¹ã³ã¢ä»ããšè§£æ
mlContext倿°ã®äœæã®äžã«ãtry-catch ã¹ããŒãã¡ã³ãã远å ããŸãã
try
{
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
try ãããã¯å
ã§ããªããžã§ã¯ãæ€åºããžãã¯ã®å®è£
ãéå§ããŸãã ãŸããããŒã¿ã IDataViewã«èªã¿èŸŒã¿ãŸãã
IEnumerable<ImageNetData> images = ImageNetData.ReadFromFile(imagesFolder);
IDataView imageDataView = mlContext.Data.LoadFromEnumerable(images);
次ã«ã OnnxModelScorer ã®ã€ã³ã¹ã¿ã³ã¹ãäœæããããã䜿çšããŠèªã¿èŸŒãŸããããŒã¿ã®ã¹ã³ã¢ä»ããè¡ããŸãã
// Create instance of model scorer
var modelScorer = new OnnxModelScorer(imagesFolder, modelFilePath, mlContext);
// Use model to score data
IEnumerable<float[]> probabilities = modelScorer.Score(imageDataView);
次ã«ãåŸåŠçã®æé ãå®è¡ããŸãã
YoloOutputParserã®ã€ã³ã¹ã¿ã³ã¹ãäœæããããã䜿çšããŠã¢ãã«ã®åºåãåŠçããŸãã
YoloOutputParser parser = new YoloOutputParser();
var boundingBoxes =
probabilities
.Select(probability => parser.ParseOutputs(probability))
.Select(boxes => parser.FilterBoundingBoxes(boxes, 5, .5F));
ã¢ãã«ã®åºåãåŠçãããããç»åã«å¢çããã¯ã¹ãæç»ããŸãã
äºæž¬ã®èŠèŠå
ã¢ãã«ãç»åã«ã¹ã³ã¢ãä»ããåºåãåŠçãããããå¢çããã¯ã¹ãç»åã«æç»ããå¿
èŠããããŸãã ãããè¡ãã«ã¯ãProgram.cså
ã® DrawBoundingBox ã¡ãœããã®äžã« GetAbsolutePath ãšããã¡ãœããã远å ããŸãã
void DrawBoundingBox(string inputImageLocation, string outputImageLocation, string imageName, IList<YoloBoundingBox> filteredBoundingBoxes)
{
}
ãŸããã€ã¡ãŒãžãèªã¿èŸŒã¿ã DrawBoundingBox ã¡ãœããã§é«ããšå¹
ã®å¯žæ³ãååŸããŸãã
Image image = Image.FromFile(Path.Combine(inputImageLocation, imageName));
var originalImageHeight = image.Height;
var originalImageWidth = image.Width;
次ã«ãfor-each ã«ãŒããäœæããŠãã¢ãã«ã«ãã£ãŠæ€åºãããåå¢çããã¯ã¹ãå埩åŠçããŸãã
foreach (var box in filteredBoundingBoxes)
{
}
for-eachã«ãŒãå ã§ãããŠã³ãã£ã³ã°ããã¯ã¹ã®å¯žæ³ãååŸããŸãã
var x = (uint)Math.Max(box.Dimensions.X, 0);
var y = (uint)Math.Max(box.Dimensions.Y, 0);
var width = (uint)Math.Min(originalImageWidth - x, box.Dimensions.Width);
var height = (uint)Math.Min(originalImageHeight - y, box.Dimensions.Height);
å¢çããã¯ã¹ã®å¯žæ³ã¯ 416 x 416ã®ã¢ãã«å
¥åã«å¯Ÿå¿ãããããå¢çããã¯ã¹ã®å¯žæ³ãã€ã¡ãŒãžã®å®éã®ãµã€ãºã«åãããŠã¹ã±ãŒãªã³ã°ããŸãã
x = (uint)originalImageWidth * x / OnnxModelScorer.ImageNetSettings.imageWidth;
y = (uint)originalImageHeight * y / OnnxModelScorer.ImageNetSettings.imageHeight;
width = (uint)originalImageWidth * width / OnnxModelScorer.ImageNetSettings.imageWidth;
height = (uint)originalImageHeight * height / OnnxModelScorer.ImageNetSettings.imageHeight;
次ã«ãåå¢çããã¯ã¹ã®äžã«è¡šç€ºãããããã¹ãã®ãã³ãã¬ãŒããå®çŸ©ããŸãã ããã¹ãã«ã¯ãããããã®å¢çããã¯ã¹å ã®ãªããžã§ã¯ãã®ã¯ã©ã¹ãšä¿¡é ŒåºŠãå«ãŸããŸãã
string text = $"{box.Label} ({(box.Confidence * 100).ToString("0")}%)";
ã€ã¡ãŒãžã«æç»ããã«ã¯ã Graphics ãªããžã§ã¯ãã«å€æããŸãã
using (Graphics thumbnailGraphic = Graphics.FromImage(image))
{
}
using ã³ãŒã ãããã¯å
ã§ãã°ã©ãã£ãã¯ã®Graphics ãªããžã§ã¯ãèšå®ã調æŽããŸãã
thumbnailGraphic.CompositingQuality = CompositingQuality.HighQuality;
thumbnailGraphic.SmoothingMode = SmoothingMode.HighQuality;
thumbnailGraphic.InterpolationMode = InterpolationMode.HighQualityBicubic;
ãã®äžã«ãããã¹ããšå¢çããã¯ã¹ã®ãã©ã³ããšè²ã®ãªãã·ã§ã³ãèšå®ããŸãã
// Define Text Options
Font drawFont = new Font("Arial", 12, FontStyle.Bold);
SizeF size = thumbnailGraphic.MeasureString(text, drawFont);
SolidBrush fontBrush = new SolidBrush(Color.Black);
Point atPoint = new Point((int)x, (int)y - (int)size.Height - 1);
// Define BoundingBox options
Pen pen = new Pen(box.BoxColor, 3.2f);
SolidBrush colorBrush = new SolidBrush(box.BoxColor);
FillRectangle ã¡ãœããã䜿çšããŠãå¢çããã¯ã¹ã®äžã«åè§åœ¢ãäœæããŠå¡ãã€ã¶ããŸãã ããã«ãããããã¹ãã®ã³ã³ãã©ã¹ããåäžããèªã¿ããããåäžããŸãã
thumbnailGraphic.FillRectangle(colorBrush, (int)x, (int)(y - size.Height - 1), (int)size.Width, (int)size.Height);
次ã«ã DrawString ã¡ãœãããš DrawRectangle ã¡ãœããã䜿çšããŠãç»åã«ããã¹ããšå¢çããã¯ã¹ãæç»ããŸãã
thumbnailGraphic.DrawString(text, drawFont, fontBrush, atPoint);
// Draw bounding box on image
thumbnailGraphic.DrawRectangle(pen, x, y, width, height);
for-each ã«ãŒãã®å€éšã§ã outputFolderã«ã€ã¡ãŒãžãä¿åããã³ãŒãã远å ããŸãã
if (!Directory.Exists(outputImageLocation))
{
Directory.CreateDirectory(outputImageLocation);
}
image.Save(Path.Combine(outputImageLocation, imageName));
ã¢ããªã±ãŒã·ã§ã³ãå®è¡æã«äºæ³ã©ããã«äºæž¬ãè¡ã£ãŠãããšãã远å ã®ãã£ãŒãããã¯ãåŸãããã«ãæ€åºããããªããžã§ã¯ããã³ã³ãœãŒã«ã«åºåããããã«ãProgram.cs ãã¡ã€ã«ã® LogDetectedObjects ã¡ãœããã®äžã« DrawBoundingBox ãšããã¡ãœããã远å ããŸãã
void LogDetectedObjects(string imageName, IList<YoloBoundingBox> boundingBoxes)
{
Console.WriteLine($".....The objects in the image {imageName} are detected as below....");
foreach (var box in boundingBoxes)
{
Console.WriteLine($"{box.Label} and its Confidence score: {box.Confidence}");
}
Console.WriteLine("");
}
äºæž¬ããèŠèŠçãªãã£ãŒãããã¯ãäœæãããã«ã㌠ã¡ãœãããçšæãããã®ã§ãã¹ã³ã¢ä»ããããåç»åãå埩åŠçãã for ã«ãŒãã远å ããŸãã
for (var i = 0; i < images.Count(); i++)
{
}
for ã«ãŒãå ã§ãã€ã¡ãŒãž ãã¡ã€ã«ã®ååãšãããã«é¢é£ä»ããããŠããå¢çããã¯ã¹ãååŸããŸãã
string imageFileName = images.ElementAt(i).Label;
IList<YoloBoundingBox> detectedObjects = boundingBoxes.ElementAt(i);
ãã®äžã§ã DrawBoundingBox ã¡ãœããã䜿çšããŠãç»åã«å¢çããã¯ã¹ãæç»ããŸãã
DrawBoundingBox(imagesFolder, outputFolder, imageFileName, detectedObjects);
æåŸã«ã LogDetectedObjects ã¡ãœããã䜿çšããŠãäºæž¬ãã³ã³ãœãŒã«ã«åºåããŸãã
LogDetectedObjects(imageFileName, detectedObjects);
try-catch ã¹ããŒãã¡ã³ãã®åŸã«ãããã»ã¹ã®å®è¡ãå®äºããããšã瀺ãããžãã¯ã远å ããŸãã
Console.WriteLine("========= End of Process..Hit any Key ========");
ããã§ãïŒ
çµæ
åã®æé ã«åŸã£ãåŸãã³ã³ãœãŒã« ã¢ããªãå®è¡ããŸã (Ctrl + F5 ããŒ)ã çµæã¯æ¬¡ã®åºåã®ããã«ãªããŸãã èŠåã衚瀺ãããããã¡ãã»ãŒãžãåŠçããããããããšããããŸãããããããããããããã«ããããã®ã¡ãã»ãŒãžã¯æ¬¡ã®çµæããåé€ãããŠããŸãã
=====Identify the objects in the images=====
.....The objects in the image image1.jpg are detected as below....
car and its Confidence score: 0.9697262
car and its Confidence score: 0.6674225
person and its Confidence score: 0.5226039
car and its Confidence score: 0.5224892
car and its Confidence score: 0.4675332
.....The objects in the image image2.jpg are detected as below....
cat and its Confidence score: 0.6461141
cat and its Confidence score: 0.6400049
.....The objects in the image image3.jpg are detected as below....
chair and its Confidence score: 0.840578
chair and its Confidence score: 0.796363
diningtable and its Confidence score: 0.6056048
diningtable and its Confidence score: 0.3737402
.....The objects in the image image4.jpg are detected as below....
dog and its Confidence score: 0.7608147
person and its Confidence score: 0.6321323
dog and its Confidence score: 0.5967442
person and its Confidence score: 0.5730394
person and its Confidence score: 0.5551759
========= End of Process..Hit any Key ========
å¢çããã¯ã¹ãããç»åã衚瀺ããã«ã¯ã assets/images/output/ ãã£ã¬ã¯ããªã«ç§»åããŸãã åŠçãããç»åã® 1 ã€ã®ãµã³ãã«ã次ã«ç€ºããŸãã
ããã§ãšãããããŸã! ããã§ãäºåãã¬ãŒãã³ã°æžã¿ã® ONNX ã¢ãã«ã ML.NET ã§åå©çšããããšã§ãç©äœæ€åºçšã®æ©æ¢°åŠç¿ã¢ãã«ãæ£åžžã«æ§ç¯ã§ããŸããã
ãã®ãã¥ãŒããªã¢ã«ã®ãœãŒã¹ ã³ãŒã㯠ãdotnet/machinelearning-samples ãªããžããªã«ãããŸãã
ãã®ãã¥ãŒããªã¢ã«ã§ã¯ãæ¬¡ã®æ¹æ³ãåŠç¿ããŸããã
- åé¡ãçè§£ãã
- ONNX ãšã¯äœããML.NET ã§ã®åäœã«ã€ããŠèª¬æããŸã
- ã¢ãã«ãçè§£ãã
- äºåãã¬ãŒãã³ã°æžã¿ã¢ãã«ãåå©çšãã
- èªã¿èŸŒãŸããã¢ãã«ã䜿çšããŠãªããžã§ã¯ããæ€åºãã
æ¡åŒµãªããžã§ã¯ãæ€åºãµã³ãã«ã調ã¹ãã«ã¯ãMachine Learning ãµã³ãã«ã® GitHub ãªããžããªãåç §ããŠãã ããã