11using System ;
22using System . Collections . Generic ;
3- using System . Drawing ;
4- using System . Drawing . Drawing2D ;
5- using System . IO ;
63using System . Linq ;
74using Microsoft . ML ;
5+ using Microsoft . ML . Data ;
6+ using ObjectDetection . DataStructures ;
7+ using ObjectDetection . YoloParser ;
88
99namespace ObjectDetection
1010{
@@ -15,13 +15,12 @@ class OnnxModelScorer
1515 private readonly MLContext mlContext ;
1616
1717 private IList < YoloBoundingBox > _boundingBoxes = new List < YoloBoundingBox > ( ) ;
18- private readonly YoloWinMlParser _parser = new YoloWinMlParser ( ) ;
1918
20- public OnnxModelScorer ( string imagesFolder , string modelLocation )
19+ public OnnxModelScorer ( string imagesFolder , string modelLocation , MLContext mlContext )
2120 {
2221 this . imagesFolder = imagesFolder ;
2322 this . modelLocation = modelLocation ;
24- mlContext = new MLContext ( ) ;
23+ this . mlContext = mlContext ;
2524 }
2625
2726 public struct ImageNetSettings
@@ -32,7 +31,7 @@ public struct ImageNetSettings
3231
3332 public struct TinyYoloModelSettings
3433 {
35- // for checking TIny yolo2 Model input and output parameter names,
34+ // for checking Tiny yolo2 Model input and output parameter names,
3635 //you can use tools like Netron,
3736 // which is installed by Visual Studio AI Tools
3837
@@ -43,139 +42,46 @@ public struct TinyYoloModelSettings
4342 public const string ModelOutput = "grid" ;
4443 }
4544
46- public void Score ( )
47- {
48- var model = LoadModel ( modelLocation ) ;
49-
50- PredictDataUsingModel ( imagesFolder , model ) ;
51- }
52-
53- private PredictionEngine < ImageNetData , ImageNetPrediction > LoadModel ( string modelLocation )
45+ private ITransformer LoadModel ( string modelLocation )
5446 {
5547 Console . WriteLine ( "Read model" ) ;
5648 Console . WriteLine ( $ "Model location: { modelLocation } ") ;
5749 Console . WriteLine ( $ "Default parameters: image size=({ ImageNetSettings . imageWidth } ,{ ImageNetSettings . imageHeight } )") ;
5850
59- var data = CreateEmptyDataView ( ) ;
51+ // Create IDataView from empty list to obtain input data schema
52+ var data = mlContext . Data . LoadFromEnumerable ( new List < ImageNetData > ( ) ) ;
6053
54+ // Define scoring pipeline
6155 var pipeline = mlContext . Transforms . LoadImages ( outputColumnName : "image" , imageFolder : "" , inputColumnName : nameof ( ImageNetData . ImagePath ) )
6256 . Append ( mlContext . Transforms . ResizeImages ( outputColumnName : "image" , imageWidth : ImageNetSettings . imageWidth , imageHeight : ImageNetSettings . imageHeight , inputColumnName : "image" ) )
6357 . Append ( mlContext . Transforms . ExtractPixels ( outputColumnName : "image" ) )
6458 . Append ( mlContext . Transforms . ApplyOnnxModel ( modelFile : modelLocation , outputColumnNames : new [ ] { TinyYoloModelSettings . ModelOutput } , inputColumnNames : new [ ] { TinyYoloModelSettings . ModelInput } ) ) ;
6559
60+ // Fit scoring pipeline
6661 var model = pipeline . Fit ( data ) ;
6762
68- var predictionEngine = mlContext . Model . CreatePredictionEngine < ImageNetData , ImageNetPrediction > ( model ) ;
69-
70- return predictionEngine ;
63+ return model ;
7164 }
7265
73- protected void PredictDataUsingModel ( string imagesFolder , PredictionEngine < ImageNetData , ImageNetPrediction > model )
66+ private IEnumerable < float [ ] > PredictDataUsingModel ( IDataView testData , ITransformer model )
7467 {
7568 Console . WriteLine ( $ "Images location: { imagesFolder } ") ;
7669 Console . WriteLine ( "" ) ;
7770 Console . WriteLine ( "=====Identify the objects in the images=====" ) ;
7871 Console . WriteLine ( "" ) ;
7972
80- var testData = GetImagesData ( imagesFolder ) ;
81-
82- foreach ( var sample in testData )
83- {
84- var probs = model . Predict ( sample ) . PredictedLabels ;
85- _boundingBoxes = _parser . ParseOutputs ( probs ) ;
86- var filteredBoxes = _parser . FilterBoundingBoxes ( _boundingBoxes , 5 , .5F ) ;
73+ IDataView scoredData = model . Transform ( testData ) ;
8774
75+ IEnumerable < float [ ] > probabilities = scoredData . GetColumn < float [ ] > ( TinyYoloModelSettings . ModelOutput ) ;
8876
89- var outputDirectory = Path . Combine ( Directory . GetParent ( sample . ImagePath ) . FullName , "output" ) ;
90- var filename = new FileInfo ( sample . ImagePath ) . Name ;
91-
92- DrawBoundingBox ( imagesFolder , outputDirectory , filename , filteredBoxes ) ;
93-
94- Console . WriteLine ( ".....The objects in the image {0} are detected as below...." , sample . Label ) ;
95- foreach ( var box in filteredBoxes )
96- {
97- Console . WriteLine ( box . Label + " and its Confidence score: " + box . Confidence ) ;
98- }
99- Console . WriteLine ( "" ) ;
100- }
77+ return probabilities ;
10178 }
10279
103- private static IEnumerable < ImageNetData > GetImagesData ( string folder )
104- {
105- List < ImageNetData > imagesList = new List < ImageNetData > ( ) ;
106- string [ ] filePaths = Directory . GetFiles ( folder ) . Where ( filePath => Path . GetExtension ( filePath ) != ".md" ) . ToArray ( ) ;
107- foreach ( var filePath in filePaths )
108- {
109- ImageNetData imagedata = new ImageNetData { ImagePath = filePath , Label = Path . GetFileName ( filePath ) } ;
110- imagesList . Add ( imagedata ) ;
111- }
112- return imagesList ;
113- }
114-
115- private IDataView CreateEmptyDataView ( )
80+ public IEnumerable < float [ ] > Score ( IDataView data )
11681 {
117- //Create empty DataView. We just need the schema to call fit()
118- List < ImageNetData > list = new List < ImageNetData > ( ) ;
119- IEnumerable < ImageNetData > enumerableData = list ;
120- var dv = mlContext . Data . LoadFromEnumerable ( enumerableData ) ;
121- return dv ;
122- }
82+ var model = LoadModel ( modelLocation ) ;
12383
124- public void DrawBoundingBox ( string inputImageLocation , string outputImageLocation , string imageName , IList < YoloBoundingBox > filteredBoundingBoxes )
125- {
126- Image image = Image . FromFile ( Path . Combine ( inputImageLocation , imageName ) ) ;
127-
128- var originalImageHeight = image . Height ;
129- var originalImageWidth = image . Width ;
130-
131- foreach ( var box in filteredBoundingBoxes )
132- {
133- // Get Bounding Box Dimensions
134- var x = ( uint ) Math . Max ( box . Dimensions . X , 0 ) ;
135- var y = ( uint ) Math . Max ( box . Dimensions . Y , 0 ) ;
136- var width = ( uint ) Math . Min ( originalImageWidth - x , box . Dimensions . Width ) ;
137- var height = ( uint ) Math . Min ( originalImageHeight - y , box . Dimensions . Height ) ;
138-
139- // Resize To Image
140- x = ( uint ) originalImageWidth * x / 416 ;
141- y = ( uint ) originalImageHeight * y / 416 ;
142- width = ( uint ) originalImageWidth * width / 416 ;
143- height = ( uint ) originalImageHeight * height / 416 ;
144-
145- // Bounding Box Text
146- string text = $ "{ box . Label } ({ ( box . Confidence * 100 ) . ToString ( "0" ) } %)";
147-
148- using ( Graphics thumbnailGraphic = Graphics . FromImage ( image ) )
149- {
150- thumbnailGraphic . CompositingQuality = CompositingQuality . HighQuality ;
151- thumbnailGraphic . SmoothingMode = SmoothingMode . HighQuality ;
152- thumbnailGraphic . InterpolationMode = InterpolationMode . HighQualityBicubic ;
153-
154- // Define Text Options
155- Font drawFont = new Font ( "Arial" , 12 , FontStyle . Bold ) ;
156- SizeF size = thumbnailGraphic . MeasureString ( text , drawFont ) ;
157- SolidBrush fontBrush = new SolidBrush ( Color . Black ) ;
158- Point atPoint = new Point ( ( int ) x , ( int ) y - ( int ) size . Height - 1 ) ;
159-
160- // Define BoundingBox options
161- Pen pen = new Pen ( box . BoxColor , 3.2f ) ;
162- SolidBrush colorBrush = new SolidBrush ( box . BoxColor ) ;
163-
164- // Draw text on image
165- thumbnailGraphic . FillRectangle ( colorBrush , ( int ) x , ( int ) ( y - size . Height - 1 ) , ( int ) size . Width , ( int ) size . Height ) ;
166- thumbnailGraphic . DrawString ( text , drawFont , fontBrush , atPoint ) ;
167-
168- // Draw bounding box on image
169- thumbnailGraphic . DrawRectangle ( pen , x , y , width , height ) ;
170- }
171- }
172-
173- if ( ! Directory . Exists ( outputImageLocation ) )
174- {
175- Directory . CreateDirectory ( outputImageLocation ) ;
176- }
177-
178- image . Save ( Path . Combine ( outputImageLocation , imageName ) ) ;
84+ return PredictDataUsingModel ( data , model ) ;
17985 }
18086 }
18187}
0 commit comments