Skip to content

Commit

Permalink
Tidy up of #41
Browse files Browse the repository at this point in the history
  • Loading branch information
djdd87 committed Dec 14, 2021
1 parent c94d904 commit d3eecaa
Show file tree
Hide file tree
Showing 10 changed files with 38 additions and 29 deletions.
3 changes: 1 addition & 2 deletions SynoAI/AIs/DeepStack/DeepStackAI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ public async override Task<IEnumerable<AIPrediction>> Process(ILogger logger, Ca
DeepStackResponse deepStackResponse = await GetResponse(response);
if (deepStackResponse.Success)
{

IEnumerable<AIPrediction> predictions = deepStackResponse.Predictions.Where(x=> x.Confidence >= minConfidence).Select(x => new AIPrediction()
IEnumerable<AIPrediction> predictions = deepStackResponse.Predictions.Where(x=> x.Confidence >= minConfidence).Select(x => new AIPrediction()
{
Confidence = x.Confidence * 100,
Label = x.Label,
Expand Down
13 changes: 13 additions & 0 deletions SynoAI/Config.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,22 @@ public static class Config
/// The artificial intelligence system to process the images with.
/// </summary>
public static AIType AI { get; private set; }
/// <summary>
/// The URL to access the AI.
/// </summary>
public static string AIUrl { get; private set; }
/// <summary>
/// Development use only. The internal path to call the AI. Potentially a better way to do this would be to support multiple AIs and have separate configs baked into each AI.
/// </summary>
public static string AIPath { get; private set; }

/// <summary>
/// The default minimum width that an object must be to be considered valid for reporting. Can be overridden on a camera by camera basis to account for different camera resolutions.
/// </summary>
public static int MinSizeX { get; private set; }
/// <summary>
/// The default minimum height that an object must be to be considered valid for reporting. Can be overridden on a camera by camera basis to account for different camera resolutions.
/// </summary>
public static int MinSizeY { get; private set; }

/// <summary>
Expand Down
26 changes: 12 additions & 14 deletions SynoAI/Controllers/CameraController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,24 +61,24 @@ public async void Get(string id)
// Get the min X and Y values for object; initialize snapshots counter.
int minX = camera.GetMinSizeX();
int minY = camera.GetMinSizeY();
int snapshotCount= 1;
int snapshotCount = 1;

// Create the stopwatches for reporting timings
Stopwatch overallStopwatch = Stopwatch.StartNew();

//Start bucle for asking snapshots until a valid prediction is found or MaxSnapshots is reached
while (snapshotCount > 0 && snapshotCount <= Config.MaxSnapshots)
// Start loop for requesting snapshots until a valid prediction is found or MaxSnapshots is reached
while (snapshotCount <= Config.MaxSnapshots)
{
_logger.LogInformation($"Snapshot {snapshotCount} of {Config.MaxSnapshots} asked at EVENT TIME {overallStopwatch.ElapsedMilliseconds}ms.");
// Take the snapshot from Surveillance Station
_logger.LogInformation($"Snapshot {snapshotCount} of {Config.MaxSnapshots} asked at EVENT TIME {overallStopwatch.ElapsedMilliseconds}ms.");
byte[] snapshot = await GetSnapshot(id);
_logger.LogInformation($"Snapshot {snapshotCount} of {Config.MaxSnapshots} received at EVENT TIME {overallStopwatch.ElapsedMilliseconds}ms.");

//See if the image needs to be rotated (or further processing in the future ?) previous to being analyzed by AI
// See if the image needs to be rotated (or further processing in the future ?) before being analyzed by the AI
snapshot = PreProcessSnapshot(camera, snapshot);

// Use the AI to get the valid predictions and then get all the valid predictions, which are all the AI predictions where the result from the AI is
// in the list of types and where the size of the object is bigger than the defined value.
// Use the AI to get the valid predictions and then get all the valid predictions (which are all the AI predictions where the result from the AI is
// in the list of types and where the size of the object is bigger than the defined value).
IEnumerable<AIPrediction> predictions = await GetAIPredications(camera, snapshot);

_logger.LogInformation($"Snapshot {snapshotCount} of {Config.MaxSnapshots} processed {predictions.Count()} objects at EVENT TIME {overallStopwatch.ElapsedMilliseconds}ms.");
Expand All @@ -92,7 +92,6 @@ public async void Get(string id)

if (validPredictions.Count() > 0)
{

// Because we don't want to process the image if it isn't even required, then we pass the snapshot manager to the notifiers. It will then perform
// the necessary actions when it's GetImage method is called.
SnapshotManager snapshotManager = new SnapshotManager(snapshot, predictions, validPredictions, _snapshotManagerLogger);
Expand All @@ -105,12 +104,13 @@ public async void Get(string id)
}

// Generate text for notifications
IList<String> labels = new List<String>();

List<String> labels = new List<String>();
if (Config.AlternativeLabelling && Config.DrawMode == DrawMode.Matches)
{
if (validPredictions.Count() == 1)
{
// If there is only a single object, then don't add a correlating number and instead just
// write out the label.
decimal confidence = Math.Round(validPredictions.First().Confidence, 0, MidpointRounding.AwayFromZero);
labels.Add($"{validPredictions.First().Label.FirstCharToUpper()} {confidence}%");
}
Expand All @@ -131,12 +131,10 @@ public async void Get(string id)
labels = validPredictions.Select(x => x.Label.FirstCharToUpper()).ToList();
}

//Send Notifications
// Send Notifications
await SendNotifications(camera, snapshotManager, labels);
_logger.LogInformation($"{id}: Valid object found in snapshot {snapshotCount} of {Config.MaxSnapshots} at EVENT TIME {overallStopwatch.ElapsedMilliseconds}ms.");

//Stop snapshot bucle iteration:
snapshotCount = -1;
break;
}
else if (predictions.Count() > 0)
{
Expand Down
2 changes: 1 addition & 1 deletion SynoAI/Notifiers/Email/Email.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ public class Email : NotifierBase
/// <param name="snapshotManager">A thread safe object for fetching the processed image.</param>
/// <param name="foundTypes">The list of types that were found.</param>
/// <param name="logger">A logger.</param>
public override async Task SendAsync(Camera camera, ISnapshotManager snapshotManager, IList<string> foundTypes, ILogger logger)
public override async Task SendAsync(Camera camera, ISnapshotManager snapshotManager, IEnumerable<string> foundTypes, ILogger logger)
{
using (logger.BeginScope($"Email '{Destination}'"))
{
Expand Down
2 changes: 1 addition & 1 deletion SynoAI/Notifiers/INotifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public interface INotifier
/// <summary>
/// Handles the send of the notification.
/// </summary>
Task SendAsync(Camera camera, ISnapshotManager snapshotManager, IList<string> foundTypes, ILogger logger);
Task SendAsync(Camera camera, ISnapshotManager snapshotManager, IEnumerable<string> foundTypes, ILogger logger);
}
}
4 changes: 2 additions & 2 deletions SynoAI/Notifiers/NotifierBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ namespace SynoAI.Notifiers
public abstract class NotifierBase : INotifier
{
public IEnumerable<string> Cameras { get; set;}
public abstract Task SendAsync(Camera camera, ISnapshotManager fileAccessor, IList<string> foundTypes, ILogger logger);
public abstract Task SendAsync(Camera camera, ISnapshotManager fileAccessor, IEnumerable<string> foundTypes, ILogger logger);

protected string GetMessage(Camera camera, IList<string> foundTypes)
protected string GetMessage(Camera camera, IEnumerable<string> foundTypes)
{
if (Config.AlternativeLabelling && Config.DrawMode == DrawMode.Matches)
{
Expand Down
2 changes: 1 addition & 1 deletion SynoAI/Notifiers/Pushbullet/Pushbullet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public class Pushbullet : NotifierBase
/// <param name="snapshotManager">A thread safe object for fetching the processed image.</param>
/// <param name="foundTypes">The list of types that were found.</param>
/// <param name="logger">A logger.</param>
public override async Task SendAsync(Camera camera, ISnapshotManager snapshotManager, IList<string> foundTypes, ILogger logger)
public override async Task SendAsync(Camera camera, ISnapshotManager snapshotManager, IEnumerable<string> foundTypes, ILogger logger)
{
// Pushbullet file uploads are a two part process. First we need to request to upload a file
using (HttpClient client = new HttpClient())
Expand Down
2 changes: 1 addition & 1 deletion SynoAI/Notifiers/Telegram/Telegram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class Telegram : NotifierBase
/// <param name="snapshotManager">A thread safe object for fetching the processed image.</param>
/// <param name="foundTypes">The list of types that were found.</param>
/// <param name="logger">A logger.</param>
public override async Task SendAsync(Camera camera, ISnapshotManager snapshotManager, IList<string> foundTypes, ILogger logger)
public override async Task SendAsync(Camera camera, ISnapshotManager snapshotManager, IEnumerable<string> foundTypes, ILogger logger)
{
using (logger.BeginScope($"Telegram '{ChatID}'"))
{
Expand Down
2 changes: 1 addition & 1 deletion SynoAI/Notifiers/Webhook/Webhook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public class Webhook : NotifierBase
/// <param name="snapshotManager">A thread safe object for fetching a readonly file stream.</param>
/// <param name="foundTypes">The list of types that were found.</param>
/// <param name="logger">A logger.</param>
public override async Task SendAsync(Camera camera, ISnapshotManager snapshotManager, IList<string> foundTypes, ILogger logger)
public override async Task SendAsync(Camera camera, ISnapshotManager snapshotManager, IEnumerable<string> foundTypes, ILogger logger)
{
logger.LogInformation($"{camera.Name}: Webhook: Processing");
using (HttpClient client = new HttpClient())
Expand Down
11 changes: 5 additions & 6 deletions SynoAI/Services/SnapshotManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,11 @@ private SKBitmap ProcessImage(Camera camera)
StrokeWidth = Config.StrokeWidth
});

//Label creation, either classic label or alternative labelling (and only if there is more than one object)
// Label creation, either classic label or alternative labelling (and only if there is more than one object)
string label = String.Empty;

if (Config.AlternativeLabelling && Config.DrawMode == DrawMode.Matches)
{
//On alternatie labelling, just place a reference number and only if there is more than one object
// On alternatie labelling, just place a reference number and only if there is more than one object
if (_validPredictions.Count() > 1)
{
label = counter.ToString();
Expand All @@ -130,11 +129,11 @@ private SKBitmap ProcessImage(Camera camera)
label = $"{prediction.Label.FirstCharToUpper()} {confidence}%";
}

//Label positioning
// Label positioning
int x = prediction.MinX + Config.TextOffsetX;
int y = prediction.MinY + Config.FontSize + Config.TextOffsetY;

//Consider below box placement
// Consider below box placement
if (Config.LabelBelowBox)
{
y += prediction.SizeY;
Expand Down Expand Up @@ -190,7 +189,7 @@ private static string SaveImage(ILogger logger, Camera camera, SKBitmap image, s
{
fileName += "_" + suffix;
}
fileName+= ".jpeg";
fileName += ".jpeg";

string filePath = Path.Combine(directory, fileName);
logger.LogInformation($"{camera}: Saving image to '{filePath}'.");
Expand Down

0 comments on commit d3eecaa

Please sign in to comment.