Skip to content

Commit 4416e36

Browse files
committed
Added documentation
1 parent 48772c3 commit 4416e36

File tree

13 files changed

+153
-42
lines changed

13 files changed

+153
-42
lines changed

source/AnimaFiltering/AnimaFiltering/Services/AnimalFilteringService.cs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,30 @@
1-
using SkiaSharp;
1+
// Copyright 2024 (c) MIDIFrogs (contact https://github.com/MIDIFrogs)
2+
// Distributed under AGPL v3.0 license. See LICENSE.md file in the project root for more information
3+
using SkiaSharp;
24
using System;
35
using System.Collections.Generic;
46
using System.Diagnostics;
57
using System.IO;
68
using System.Linq;
7-
using System.Text;
89
using System.Threading.Tasks;
9-
using YoloDotNet;
1010

1111
namespace AnimaFiltering.Services
1212
{
13+
/// <summary>
14+
/// Represents a service that filters animal images.
15+
/// </summary>
16+
/// <param name="yolo">An instance of the YOLO model provider.</param>
17+
/// <param name="filters">Set of custom filters to test an image.</param>
1318
public class AnimalFilteringService(YoloProvider yolo, UserFilters filters)
1419
{
1520
public const string GoodClassName = "good";
1621
public const string BadClassName = "bad";
1722

23+
/// <summary>
24+
/// Filters all images in given directory.
25+
/// </summary>
26+
/// <param name="datasetPath">Path to a directory to filter.</param>
27+
/// <returns>An enumerable of detection results with their classes.</returns>
1828
public async IAsyncEnumerable<AnimalDetectInfo> FilterAnimalsAsync(string datasetPath)
1929
{
2030
var files = Directory.EnumerateFiles(datasetPath, "*.jpg");
@@ -29,7 +39,7 @@ public async IAsyncEnumerable<AnimalDetectInfo> FilterAnimalsAsync(string datase
2939
var result = await Task.Run(() => yolo.Yolo.RunObjectDetection(image, iou: 0.5));
3040
#if DEBUG
3141
if (++i % 20 == 0)
32-
Debug.WriteLine($"Processing image {i}/{count}...");
42+
Debug.WriteLine($"Processing image {i}/{count}...");
3343
#endif
3444
foreach (var animal in result)
3545
{
@@ -41,4 +51,4 @@ public async IAsyncEnumerable<AnimalDetectInfo> FilterAnimalsAsync(string datase
4151
#endif
4252
}
4353
}
44-
}
54+
}

source/AnimaFiltering/AnimaFiltering/Services/AppPreferences.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
1-
// Copyright 2024 (c) IOExcept10n (contact https://github.com/IOExcept10n)
2-
// Distributed under APGL v3.0 license. See LICENSE.md file in the project root for more information
1+
// Copyright 2024 (c) MIDIFrogs (contact https://github.com/MIDIFrogs)
2+
// Distributed under AGPL v3.0 license. See LICENSE.md file in the project root for more information
33
using Newtonsoft.Json;
44
using System.IO;
55

66
namespace AnimaFiltering.Services
77
{
8+
/// <summary>
9+
/// Represents preferences for the application.
10+
/// </summary>
811
public record class AppPreferences
912
{
1013
private readonly string filePath = "Options.json";
1114

15+
/// <summary>
16+
/// Minimal detection width to check.
17+
/// </summary>
1218
public int MinWidth { get; set; }
1319

20+
/// <summary>
21+
/// Minimal detection height to check.
22+
/// </summary>
1423
public int MinHeight { get; set; }
1524

25+
/// <summary>
26+
/// Determines whether the GPU with CUDA is preferred (CudNN is required).
27+
/// </summary>
1628
public bool PreferGPU { get; set; }
1729

1830
public AppPreferences()
@@ -32,11 +44,19 @@ private AppPreferences(AppPreferences prototype, string path) : this(prototype)
3244
filePath = path;
3345
}
3446

47+
/// <summary>
48+
/// Saves app settings.
49+
/// </summary>
3550
public void Save()
3651
{
3752
File.WriteAllText(filePath, JsonConvert.SerializeObject(this));
3853
}
3954

55+
/// <summary>
56+
/// Loads app settings or initializes new ones.
57+
/// </summary>
58+
/// <param name="filePath">File path to save.</param>
59+
/// <returns>An instance of the <see cref="AppPreferences"/>.</returns>
4060
public static AppPreferences LoadOrCreate(string filePath)
4161
{
4262
if (File.Exists(filePath))

source/AnimaFiltering/AnimaFiltering/Services/CameraManager.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright 2024 (c) IOExcept10n (contact https://github.com/IOExcept10n)
1+
// Copyright 2024 (c) MIDIFrogs (contact https://github.com/MIDIFrogs)
22
// Distributed under AGPL v3.0 license. See LICENSE.md file in the project root for more information
33
using Newtonsoft.Json;
44
using System.Collections.Generic;
@@ -7,6 +7,9 @@
77

88
namespace AnimaFiltering.Services
99
{
10+
/// <summary>
11+
/// Represents a collection of camera stats.
12+
/// </summary>
1013
public class CameraManager : ObservableCollection<CameraStats>
1114
{
1215
private readonly string filePath;
@@ -22,20 +25,25 @@ private CameraManager(IEnumerable<CameraStats> items, string path)
2225

2326
public CameraManager()
2427
{
25-
2628
}
2729

2830
public CameraManager(string path)
2931
{
3032
filePath = path;
3133
}
3234

35+
/// <summary>
36+
/// Loads camera stats of initializes a new ones.
37+
/// </summary>
38+
/// <param name="filePath">Path to a file with camera stats.</param>
39+
/// <returns>An instance of the <see cref="CameraManager"/>.</returns>
3340
public static CameraManager LoadOrCreate(string filePath)
3441
{
3542
if (File.Exists(filePath))
3643
{
3744
return new(JsonConvert.DeserializeObject<CameraManager>(File.ReadAllText(filePath))!, filePath);
3845
}
46+
// HACK
3947
return new(filePath)
4048
{
4149
new(){ Name = "Камера 1"},
Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,30 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using System.Text;
5-
using System.Threading.Tasks;
6-
1+
// Copyright 2024 (c) MIDIFrogs (contact https://github.com/MIDIFrogs)
2+
// Distributed under AGPL v3.0 license. See LICENSE.md file in the project root for more information
73
namespace AnimaFiltering.Services
84
{
5+
/// <summary>
6+
/// Represents configurable stats for the camera.
7+
/// </summary>
98
public class CameraStats
109
{
10+
/// <summary>
11+
/// Name of the camera.
12+
/// </summary>
1113
public required string Name { get; set; }
1214

15+
/// <summary>
16+
/// Number of images processed for all the time.
17+
/// </summary>
1318
public int ProcessedImages { get; set; }
1419

20+
/// <summary>
21+
/// Number of good images from the selected ones.
22+
/// </summary>
1523
public int GoodImages { get; set; }
1624

1725
public override string ToString()
1826
{
1927
return Name;
2028
}
2129
}
22-
}
30+
}

source/AnimaFiltering/AnimaFiltering/Services/Filters/HeadFilter.cs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
using Avalonia.Logging;
1+
// Copyright 2024 (c) MIDIFrogs (contact https://github.com/MIDIFrogs)
2+
// Distributed under AGPL v3.0 license. See LICENSE.md file in the project root for more information
3+
using Avalonia.Logging;
24
using SkiaSharp;
35
using System;
46
using YoloDotNet;
57
using YoloDotNet.Models;
68

79
namespace AnimaFiltering.Services.Filters
810
{
11+
/// <summary>
12+
/// Represents a filter that checks if animal's head is inside the bounding box.
13+
/// </summary>
14+
/// <param name="preferences"></param>
915
internal class HeadFilter(AppPreferences preferences) : IPostProcessingFilter
1016
{
1117
public const string ModelPath = "head.onnx";
@@ -20,6 +26,11 @@ public bool CheckDetection(ObjectDetection detection, SKImage image)
2026
return results.Count == 1 && results[0].BoundingBox.Width > preferences.MinWidth / 8 && results[0].BoundingBox.Height > preferences.MinHeight / 8;
2127
}
2228

29+
/// <summary>
30+
/// Initializes YOLO model for head detection.
31+
/// </summary>
32+
/// <param name="preferences">App preferences to initialize.</param>
33+
/// <returns>YOLO model that finds heads in image BBoxes.</returns>
2334
private static Yolo InitYolo(AppPreferences preferences)
2435
{
2536
if (preferences.PreferGPU)
@@ -48,4 +59,4 @@ private static Yolo InitYolo(AppPreferences preferences)
4859
});
4960
}
5061
}
51-
}
62+
}
Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,19 @@
1-
using SkiaSharp;
2-
using System;
3-
using System.Collections.Generic;
4-
using System.Linq;
5-
using System.Text;
6-
using System.Threading.Tasks;
1+
// Copyright 2024 (c) MIDIFrogs (contact https://github.com/MIDIFrogs)
2+
// Distributed under AGPL v3.0 license. See LICENSE.md file in the project root for more information
3+
using SkiaSharp;
74
using YoloDotNet.Models;
85

96
namespace AnimaFiltering.Services.Filters
107
{
8+
/// <summary>
9+
/// Filter that checks if the bounding box size is correct.
10+
/// </summary>
11+
/// <param name="preferences">App preferences for filtering.</param>
1112
internal class SizeFilter(AppPreferences preferences) : IPostProcessingFilter
1213
{
1314
public bool CheckDetection(ObjectDetection detection, SKImage image)
1415
{
1516
return detection.BoundingBox.Width >= preferences.MinWidth && detection.BoundingBox.Height >= preferences.MinHeight;
1617
}
1718
}
18-
}
19+
}

source/AnimaFiltering/AnimaFiltering/Services/Filters/UnFocusFilter.cs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
1-
using OpenCvSharp;
1+
// Copyright 2024 (c) MIDIFrogs (contact https://github.com/MIDIFrogs)
2+
// Distributed under AGPL v3.0 license. See LICENSE.md file in the project root for more information
3+
using OpenCvSharp;
24
using SkiaSharp;
3-
using YoloDotNet.Extensions;
45
using YoloDotNet.Models;
56

67
namespace AnimaFiltering.Services.Filters
78
{
9+
/// <summary>
10+
/// Filter that checks for image focus value.
11+
/// </summary>
12+
/// <param name="preferences"></param>
813
internal class UnFocus(AppPreferences preferences) : IPostProcessingFilter
914
{
15+
/// <summary>
16+
/// Converts SkiaSharp image to OpenCV Mat. Also clips an image by given clip rect.
17+
/// </summary>
18+
/// <param name="skImage">An image to clip and convert.</param>
19+
/// <param name="clipRect">Clipping rectangle.</param>
20+
/// <returns>Converted OpenCV Mat.</returns>
1021
public Mat ConvertSkiaSharpImageToMat(SKImage skImage, SKRectI clipRect)
1122
{
1223
// Step 1: Create a new SKImage from the clipped area
@@ -57,4 +68,4 @@ public bool CheckDetection(ObjectDetection detection, SKImage image)
5768
return focusMeasure > 70;
5869
}
5970
}
60-
}
71+
}
Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,21 @@
1-
using SkiaSharp;
1+
// Copyright 2024 (c) MIDIFrogs (contact https://github.com/MIDIFrogs)
2+
// Distributed under AGPL v3.0 license. See LICENSE.md file in the project root for more information
3+
using SkiaSharp;
24
using YoloDotNet.Models;
35

46
namespace AnimaFiltering.Services
57
{
8+
/// <summary>
9+
/// Represents an interface for the postprocessing filter.
10+
/// </summary>
611
public interface IPostProcessingFilter
712
{
13+
/// <summary>
14+
/// Checks if the detection result is valid.
15+
/// </summary>
16+
/// <param name="detection">Detection instance to check.</param>
17+
/// <param name="image">Source image to validate.</param>
18+
/// <returns><see langword="true"/> if the detection is valid; otherwise <see langword="false"/>.</returns>
819
bool CheckDetection(ObjectDetection detection, SKImage image);
920
}
1021
}

source/AnimaFiltering/AnimaFiltering/Services/ReportBuilder.cs

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
1-
using System;
1+
// Copyright 2024 (c) MIDIFrogs (contact https://github.com/MIDIFrogs)
2+
// Distributed under AGPL v3.0 license. See LICENSE.md file in the project root for more information
3+
using System;
24
using System.Collections.Generic;
35
using System.IO;
4-
using System.Linq;
5-
using System.Text;
66
using System.Threading.Tasks;
77

88
namespace AnimaFiltering.Services
99
{
10+
/// <summary>
11+
/// Represents a builder for the CSV reports.
12+
/// </summary>
1013
internal class ReportBuilder
1114
{
15+
/// <summary>
16+
/// Writes filtering results into CSV file.
17+
/// </summary>
18+
/// <param name="detections">Set of detections to log.</param>
19+
/// <param name="selectedCamera">A camera to save stats for.</param>
20+
/// <param name="path">Path to save CSV to.</param>
21+
/// <param name="progress">Progress handler to notify about image processing.</param>
1222
public async Task WriteToCsvAsync(IAsyncEnumerable<AnimalDetectInfo> detections, CameraStats selectedCamera, string path, IProgress<int> progress)
1323
{
1424
using var writer = new StreamWriter(path);
@@ -28,4 +38,4 @@ public async Task WriteToCsvAsync(IAsyncEnumerable<AnimalDetectInfo> detections,
2838
}
2939
}
3040
}
31-
}
41+
}

source/AnimaFiltering/AnimaFiltering/Services/ServiceRegistration.cs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,22 @@
1-
// Copyright 2024 (c) IOExcept10n (contact https://github.com/IOExcept10n)
1+
// Copyright 2024 (c) MIDIFrogs (contact https://github.com/MIDIFrogs)
22
// Distributed under AGPL v3.0 license. See LICENSE.md file in the project root for more information
33
using AnimaFiltering.ViewModels;
44
using Microsoft.Extensions.DependencyInjection;
55

66
namespace AnimaFiltering.Services
77
{
8+
/// <summary>
9+
/// Represents an utility to register app services.
10+
/// </summary>
811
internal static class ServiceRegistration
912
{
1013
private const string OptionsFileName = "Options.json";
1114
private const string CamerasFileName = "Cameras.json";
1215

16+
/// <summary>
17+
/// Adds application services to the DI container.
18+
/// </summary>
19+
/// <param name="services">Services collection to add.</param>
1320
public static IServiceCollection AddServices(this IServiceCollection services)
1421
{
1522
return services
@@ -19,13 +26,19 @@ public static IServiceCollection AddServices(this IServiceCollection services)
1926
.AddSingleton<YoloProvider>();
2027
}
2128

29+
/// <summary>
30+
/// Adds app view models to the DI container.
31+
/// </summary>
2232
public static IServiceCollection AddViewModels(this IServiceCollection services)
2333
{
2434
return services
2535
.AddTransient<StatsViewModel>()
2636
.AddTransient<MainViewModel>();
2737
}
2838

39+
/// <summary>
40+
/// Adds image filters to the DI container.
41+
/// </summary>
2942
public static IServiceCollection AddFilters(this IServiceCollection services)
3043
{
3144
return services
@@ -35,6 +48,9 @@ public static IServiceCollection AddFilters(this IServiceCollection services)
3548
.AddSingleton<ReportBuilder>();
3649
}
3750

51+
/// <summary>
52+
/// Adds app options to the DI container.
53+
/// </summary>
3854
public static IServiceCollection AddOptions(this IServiceCollection services)
3955
{
4056
AppPreferences options = AppPreferences.LoadOrCreate(OptionsFileName);

0 commit comments

Comments
 (0)