splitting python complete

This commit is contained in:
Oleksandr Bezdieniezhnykh
2025-08-12 14:48:56 +03:00
parent fc6e5db795
commit ad782bcbaa
31 changed files with 834 additions and 369 deletions
+10 -10
View File
@@ -94,6 +94,7 @@ public class AnnotationService : IAnnotationService
await SaveAnnotationInner(
msg.CreatedDate,
msg.OriginalMediaName,
msg.Name,
msg.Time,
JsonConvert.DeserializeObject<List<Detection>>(msg.Detections) ?? [],
msg.Source,
@@ -136,16 +137,16 @@ public class AnnotationService : IAnnotationService
public async Task<Annotation> SaveAnnotation(AnnotationImage a, CancellationToken ct = default)
{
a.Time = TimeSpan.FromMilliseconds(a.Milliseconds);
return await SaveAnnotationInner(DateTime.UtcNow, a.OriginalMediaName, a.Time, a.Detections.ToList(),
return await SaveAnnotationInner(DateTime.UtcNow, a.OriginalMediaName, a.Name, a.Time, a.Detections.ToList(),
SourceEnum.AI, new MemoryStream(a.Image), _api.CurrentUser.Role, _api.CurrentUser.Email, token: ct);
}
//Manual
public async Task<Annotation> SaveAnnotation(string originalMediaName, TimeSpan time, List<Detection> detections, Stream? stream = null, CancellationToken token = default) =>
await SaveAnnotationInner(DateTime.UtcNow, originalMediaName, time, detections, SourceEnum.Manual, stream,
public async Task<Annotation> SaveAnnotation(string originalMediaName, string annotationName, TimeSpan time, List<Detection> detections, Stream? stream = null, CancellationToken token = default) =>
await SaveAnnotationInner(DateTime.UtcNow, originalMediaName, annotationName, time, detections, SourceEnum.Manual, stream,
_api.CurrentUser.Role, _api.CurrentUser.Email, token: token);
private async Task<Annotation> SaveAnnotationInner(DateTime createdDate, string originalMediaName, TimeSpan time,
private async Task<Annotation> SaveAnnotationInner(DateTime createdDate, string originalMediaName, string annotationName, TimeSpan time,
List<Detection> detections, SourceEnum source, Stream? stream,
RoleEnum userRole,
string createdEmail,
@@ -153,21 +154,20 @@ public class AnnotationService : IAnnotationService
CancellationToken token = default)
{
var status = AnnotationStatus.Created;
var fName = originalMediaName.ToTimeName(time);
var annotation = await _dbFactory.RunWrite(async db =>
{
var ann = await db.Annotations
.LoadWith(x => x.Detections)
.FirstOrDefaultAsync(x => x.Name == fName, token: token);
.FirstOrDefaultAsync(x => x.Name == annotationName, token: token);
await db.Detections.DeleteAsync(x => x.AnnotationName == fName, token: token);
await db.Detections.DeleteAsync(x => x.AnnotationName == annotationName, token: token);
if (ann != null) //Annotation is already exists
{
status = AnnotationStatus.Edited;
var annotationUpdatable = db.Annotations
.Where(x => x.Name == fName)
.Where(x => x.Name == annotationName)
.Set(x => x.Source, source);
if (userRole.IsValidator() && source == SourceEnum.Manual)
@@ -188,7 +188,7 @@ public class AnnotationService : IAnnotationService
ann = new Annotation
{
CreatedDate = createdDate,
Name = fName,
Name = annotationName,
OriginalMediaName = originalMediaName,
Time = time,
ImageExtension = Constants.JPG_EXT,
@@ -264,6 +264,6 @@ public class AnnotationService : IAnnotationService
public interface IAnnotationService
{
Task<Annotation> SaveAnnotation(AnnotationImage a, CancellationToken ct = default);
Task<Annotation> SaveAnnotation(string originalMediaName, TimeSpan time, List<Detection> detections, Stream? stream = null, CancellationToken token = default);
Task<Annotation> SaveAnnotation(string originalMediaName, string annotationName, TimeSpan time, List<Detection> detections, Stream? stream = null, CancellationToken token = default);
Task ValidateAnnotations(List<string> annotationNames, bool fromQueue = false, CancellationToken token = default);
}
+7 -7
View File
@@ -237,11 +237,11 @@ public class GalleryService(
.ToList();
if (annotation.Detections.Any())
{
var labelsMinX = labels.Min(x => x.X);
var labelsMaxX = labels.Max(x => x.X + x.Width);
var labelsMinX = labels.Min(x => x.Left);
var labelsMaxX = labels.Max(x => x.Left + x.Width);
var labelsMinY = labels.Min(x => x.Y);
var labelsMaxY = labels.Max(x => x.Y + x.Height);
var labelsMinY = labels.Min(x => x.Top);
var labelsMaxY = labels.Max(x => x.Top + x.Height);
var labelsHeight = labelsMaxY - labelsMinY + 2 * border;
var labelsWidth = labelsMaxX - labelsMinX + 2 * border;
@@ -270,7 +270,7 @@ public class GalleryService(
var color = _annotationConfig.DetectionClassesDict[label.ClassNumber].Color;
var brush = new SolidBrush(Color.FromArgb(color.A, color.R, color.G, color.B));
g.DrawRectangle(new Pen(brush, width: 3), (float)((label.X - frameX) / scale), (float)((label.Y - frameY) / scale), (float)(label.Width / scale), (float)(label.Height / scale));
g.DrawRectangle(new Pen(brush, width: 3), (float)((label.Left - frameX) / scale), (float)((label.Top - frameY) / scale), (float)(label.Width / scale), (float)(label.Height / scale));
}
bitmap.Save(annotation.ThumbPath, ImageFormat.Jpeg);
@@ -291,10 +291,10 @@ public class GalleryService(
var color = detClass.Color;
var brush = new SolidBrush(Color.FromArgb(color.A, color.R, color.G, color.B));
var det = new CanvasLabel(detection, new Size(originalImage.Width, originalImage.Height));
g.DrawRectangle(new Pen(brush, width: 3), (float)det.X, (float)det.Y, (float)det.Width, (float)det.Height);
g.DrawRectangle(new Pen(brush, width: 3), (float)det.Left, (float)det.Top, (float)det.Width, (float)det.Height);
var label = detection.Confidence >= 0.995 ? detClass.UIName : $"{detClass.UIName}: {detection.Confidence * 100:F0}%";
g.DrawTextBox(label, new PointF((float)(det.X + det.Width / 2.0), (float)(det.Y - 24)), brush, Brushes.Black);
g.DrawTextBox(label, new PointF((float)(det.Left + det.Width / 2.0), (float)(det.Top - 24)), brush, Brushes.Black);
}
var imagePath = Path.Combine(_dirConfig.ResultsDirectory, $"{annotation.Name}{Constants.RESULT_PREFIX}.jpg");
+1 -1
View File
@@ -49,7 +49,7 @@ public class InferenceClient : IInferenceClient
Arguments = $"-p {_inferenceClientConfig.ZeroMqPort} -lp {_loaderClientConfig.ZeroMqPort} -a {_inferenceClientConfig.ApiUrl}",
CreateNoWindow = true
};
process.Start();
//process.Start();
}
catch (Exception e)
{
+18 -23
View File
@@ -18,10 +18,8 @@ public class TileResult
public static class TileProcessor
{
private const int MaxTileWidth = 1280;
private const int MaxTileHeight = 1280;
private const int Border = 10;
public const int BORDER = 10;
public static List<TileResult> Split(Size originalSize, List<CanvasLabel> detections, CancellationToken cancellationToken)
{
var results = new List<TileResult>();
@@ -30,7 +28,7 @@ public static class TileProcessor
while (processingDetectionList.Count > 0 && !cancellationToken.IsCancellationRequested)
{
var topMostDetection = processingDetectionList
.OrderBy(d => d.Y)
.OrderBy(d => d.Top)
.First();
var result = GetDetectionsInTile(originalSize, topMostDetection, processingDetectionList);
@@ -42,11 +40,8 @@ public static class TileProcessor
private static TileResult GetDetectionsInTile(Size originalSize, CanvasLabel startDet, List<CanvasLabel> allDetections)
{
var tile = new CanvasLabel(
left: Math.Max(startDet.X - Border, 0),
right: Math.Min(startDet.Right + Border, originalSize.Width),
top: Math.Max(startDet.Y - Border, 0),
bottom: Math.Min(startDet.Bottom + Border, originalSize.Height));
var tile = new CanvasLabel(startDet.Left, startDet.Right, startDet.Top, startDet.Bottom);
var maxSize = new List<double> { startDet.Width + BORDER, startDet.Height + BORDER, Constants.AI_TILE_SIZE }.Max();
var selectedDetections = new List<CanvasLabel>{startDet};
foreach (var det in allDetections)
@@ -55,26 +50,26 @@ public static class TileProcessor
continue;
var commonTile = new CanvasLabel(
left: Math.Max(Math.Min(tile.X, det.X) - Border, 0),
right: Math.Min(Math.Max(tile.Right, det.Right) + Border, originalSize.Width),
top: Math.Max(Math.Min(tile.Y, det.Y) - Border, 0),
bottom: Math.Min(Math.Max(tile.Bottom, det.Bottom) + Border, originalSize.Height)
left: Math.Min(tile.Left, det.Left),
right: Math.Max(tile.Right, det.Right),
top: Math.Min(tile.Top, det.Top),
bottom: Math.Max(tile.Bottom, det.Bottom)
);
if (commonTile.Width > MaxTileWidth || commonTile.Height > MaxTileHeight)
if (commonTile.Width + BORDER > maxSize || commonTile.Height + BORDER > maxSize)
continue;
tile = commonTile;
selectedDetections.Add(det);
}
//normalization, width and height should be at least half of 1280px
tile.Width = Math.Max(tile.Width, MaxTileWidth / 2.0);
tile.Height = Math.Max(tile.Height, MaxTileHeight / 2.0);
//boundaries check after normalization
tile.Right = Math.Min(tile.Right, originalSize.Width);
tile.Bottom = Math.Min(tile.Bottom, originalSize.Height);
// boundary-aware centering
var centerX = selectedDetections.Average(x => x.CenterX);
var centerY = selectedDetections.Average(d => d.CenterY);
tile.Width = maxSize;
tile.Height = maxSize;
tile.Left = Math.Max(0, Math.Min(originalSize.Width - maxSize, centerX - tile.Width / 2.0));
tile.Top = Math.Max(0, Math.Min(originalSize.Height - maxSize, centerY - tile.Height / 2.0));
return new TileResult(tile, selectedDetections);
}