add generating result image to Results directory

This commit is contained in:
Alex Bezdieniezhnykh
2025-04-03 11:06:00 +03:00
parent 83ae6a0ae9
commit c9800107a6
15 changed files with 86 additions and 61 deletions
-3
View File
@@ -331,14 +331,11 @@ public partial class Annotator
{ {
try try
{ {
_logger.LogInformation($"remove annotation {existingResult.TimeStr} {existingResult.ClassName}!");
_formState.AnnotationResults.Remove(existingResult); _formState.AnnotationResults.Remove(existingResult);
_logger.LogInformation($"removed {existingResult.TimeStr} {existingResult.ClassName} sucessfully!");
} }
catch (Exception e) catch (Exception e)
{ {
_logger.LogError(e, e.Message); _logger.LogError(e, e.Message);
//Console.WriteLine(e);
throw; throw;
} }
+1
View File
@@ -63,6 +63,7 @@ public class Constants
public const int DEFAULT_THUMBNAIL_BORDER = 10; public const int DEFAULT_THUMBNAIL_BORDER = 10;
public const string THUMBNAIL_PREFIX = "_thumb"; public const string THUMBNAIL_PREFIX = "_thumb";
public const string RESULT_PREFIX = "_result";
#endregion #endregion
+1 -1
View File
@@ -121,7 +121,7 @@ public class DetectionControl : Border
var rect = new Rectangle() // small rectangles at the corners and sides var rect = new Rectangle() // small rectangles at the corners and sides
{ {
ClipToBounds = false, ClipToBounds = false,
Margin = new Thickness(-RESIZE_RECT_SIZE), Margin = new Thickness(-RESIZE_RECT_SIZE * 0.7),
HorizontalAlignment = ha, HorizontalAlignment = ha,
VerticalAlignment = va, VerticalAlignment = va,
Width = RESIZE_RECT_SIZE, Width = RESIZE_RECT_SIZE,
+1
View File
@@ -58,6 +58,7 @@ public class ConfigUpdater : IConfigUpdater
{ {
LeftPanelWidth = Constants.DEFAULT_LEFT_PANEL_WIDTH, LeftPanelWidth = Constants.DEFAULT_LEFT_PANEL_WIDTH,
RightPanelWidth = Constants.DEFAULT_RIGHT_PANEL_WIDTH, RightPanelWidth = Constants.DEFAULT_RIGHT_PANEL_WIDTH,
GenerateAnnotatedImage = false
}, },
DirectoriesConfig = new DirectoriesConfig DirectoriesConfig = new DirectoriesConfig
+1
View File
@@ -4,4 +4,5 @@ public class UIConfig
{ {
public double LeftPanelWidth { get; set; } public double LeftPanelWidth { get; set; }
public double RightPanelWidth { get; set; } public double RightPanelWidth { get; set; }
public bool GenerateAnnotatedImage { get; set; }
} }
@@ -30,6 +30,7 @@ public class AnnotationService : INotificationHandler<AnnotationsDeletedEvent>
private readonly IAuthProvider _authProvider; private readonly IAuthProvider _authProvider;
private readonly QueueConfig _queueConfig; private readonly QueueConfig _queueConfig;
private Consumer _consumer = null!; private Consumer _consumer = null!;
private readonly UIConfig _uiConfig;
private static readonly Guid SaveTaskId = Guid.NewGuid(); private static readonly Guid SaveTaskId = Guid.NewGuid();
public AnnotationService( public AnnotationService(
@@ -37,6 +38,7 @@ public class AnnotationService : INotificationHandler<AnnotationsDeletedEvent>
IDbFactory dbFactory, IDbFactory dbFactory,
FailsafeAnnotationsProducer producer, FailsafeAnnotationsProducer producer,
IOptions<QueueConfig> queueConfig, IOptions<QueueConfig> queueConfig,
IOptions<UIConfig> uiConfig,
IGalleryService galleryService, IGalleryService galleryService,
IMediator mediator, IMediator mediator,
IHardwareService hardwareService, IHardwareService hardwareService,
@@ -49,6 +51,7 @@ public class AnnotationService : INotificationHandler<AnnotationsDeletedEvent>
_hardwareService = hardwareService; _hardwareService = hardwareService;
_authProvider = authProvider; _authProvider = authProvider;
_queueConfig = queueConfig.Value; _queueConfig = queueConfig.Value;
_uiConfig = uiConfig.Value;
Task.Run(async () => await Init()).Wait(); Task.Run(async () => await Init()).Wait();
} }
@@ -184,7 +187,12 @@ public class AnnotationService : INotificationHandler<AnnotationsDeletedEvent>
} }
await YoloLabel.WriteToFile(detections, annotation.LabelPath, token); await YoloLabel.WriteToFile(detections, annotation.LabelPath, token);
if (generateThumbnail) if (generateThumbnail)
{
await _galleryService.CreateThumbnail(annotation, token); await _galleryService.CreateThumbnail(annotation, token);
if (_uiConfig.GenerateAnnotatedImage)
await _galleryService.CreateAnnotatedImage(annotation, token);
}
if (!fromQueue) //Send to queue only if we're not getting from queue already if (!fromQueue) //Send to queue only if we're not getting from queue already
await _producer.SendToInnerQueue(annotation, token); await _producer.SendToInnerQueue(annotation, token);
+19
View File
@@ -265,6 +265,24 @@ public class GalleryService(
logger.LogError(e, e.Message); logger.LogError(e, e.Message);
} }
} }
public async Task CreateAnnotatedImage(Annotation annotation, CancellationToken token)
{
var originalImage = Image.FromStream(new MemoryStream(await File.ReadAllBytesAsync(annotation.ImagePath, token)));
using var g = Graphics.FromImage(originalImage);
foreach (var detection in annotation.Detections)
{
var detClass = _annotationConfig.DetectionClassesDict[detection.ClassNumber];
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);
var label = detection.Confidence >= 0.995 ? detClass.UIName : $"{detClass.UIName}: {detection.Confidence * 100:F0}%";
g.DrawString(label, new Font(FontFamily.GenericSerif, 14), brush, new PointF((float)(det.X + det.Width / 2.0), (float)det.Y));
}
originalImage.Save(Path.Combine(_dirConfig.ResultsDirectory, $"{annotation.Name}{Constants.RESULT_PREFIX}.jpg"), ImageFormat.Jpeg);
}
} }
public interface IGalleryService public interface IGalleryService
@@ -275,4 +293,5 @@ public interface IGalleryService
Task RefreshThumbnails(); Task RefreshThumbnails();
Task ClearThumbnails(CancellationToken cancellationToken = default); Task ClearThumbnails(CancellationToken cancellationToken = default);
Task CreateAnnotatedImage(Annotation annotation, CancellationToken token);
} }
-2
View File
@@ -4,8 +4,6 @@ from PyInstaller.utils.hooks import collect_all
datas = [] datas = []
binaries = [] binaries = []
hiddenimports = ['constants', 'annotation', 'credentials', 'file_data', 'user', 'security', 'secure_model', 'api_client', 'hardware_service', 'remote_command', 'ai_config', 'inference_engine', 'inference', 'remote_command_handler'] hiddenimports = ['constants', 'annotation', 'credentials', 'file_data', 'user', 'security', 'secure_model', 'api_client', 'hardware_service', 'remote_command', 'ai_config', 'inference_engine', 'inference', 'remote_command_handler']
tmp_ret = collect_all('pyyaml')
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
tmp_ret = collect_all('jwt') tmp_ret = collect_all('jwt')
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
tmp_ret = collect_all('requests') tmp_ret = collect_all('requests')
+4 -4
View File
@@ -32,8 +32,8 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Azaion.Common\Azaion.Common.csproj" /> <ProjectReference Include="..\Azaion.Common\Azaion.Common.csproj" />
<ProjectReference Include="..\Azaion.Annotator\Azaion.Annotator.csproj" /> <ProjectReference Include="..\dummy\Azaion.Annotator\Azaion.Annotator.csproj" />
<ProjectReference Include="..\Azaion.Dataset\Azaion.Dataset.csproj" /> <ProjectReference Include="..\dummy\Azaion.Dataset\Azaion.Dataset.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -61,8 +61,8 @@
<Target Name="PostBuild" AfterTargets="Build"> <Target Name="PostBuild" AfterTargets="Build">
<MakeDir Directories="$(TargetDir)dummy" /> <MakeDir Directories="$(TargetDir)dummy" />
<Copy SourceFiles="$(TargetDir)Azaion.Annotator.dll" DestinationFolder="$(TargetDir)dummy" /> <Move SourceFiles="$(TargetDir)Azaion.Annotator.dll" DestinationFolder="$(TargetDir)dummy" />
<Copy SourceFiles="$(TargetDir)Azaion.Dataset.dll" DestinationFolder="$(TargetDir)dummy" /> <Move SourceFiles="$(TargetDir)Azaion.Dataset.dll" DestinationFolder="$(TargetDir)dummy" />
<Exec Command="upload.cmd $(ConfigurationName) stage" /> <Exec Command="upload.cmd $(ConfigurationName) stage" />
</Target> </Target>
+2 -2
View File
@@ -74,7 +74,7 @@
BorderBrush="DimGray" BorderBrush="DimGray"
BorderThickness="0,0,0,1" BorderThickness="0,0,0,1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Text="admin@azaion.com" Text=""
/> />
<TextBlock Text="Пароль" <TextBlock Text="Пароль"
Grid.Row="2" Grid.Row="2"
@@ -89,7 +89,7 @@
Width="300" Width="300"
BorderThickness="0,0,0,1" BorderThickness="0,0,0,1"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Password="Az@1on1000Odm$n"/> Password=""/>
</Grid> </Grid>
<Button x:Name="LoginBtn" <Button x:Name="LoginBtn"
Content="Вхід" Content="Вхід"
+2 -1
View File
@@ -22,6 +22,7 @@
}, },
"UIConfig": { "UIConfig": {
"LeftPanelWidth": 220.0, "LeftPanelWidth": 220.0,
"RightPanelWidth": 230.0 "RightPanelWidth": 230.0,
"GenerateAnnotatedImage": true
} }
} }
+28
View File
@@ -0,0 +1,28 @@
setlocal enabledelayedexpansion
set API_URL=https://api.azaion.com
set SOURCE_FILE=%1
set DESTINATION=%2
set "SOURCE_FILE=%SOURCE_FILE:\=/%"
set EMAIL=uploader@azaion.com
set PASSWORD=Az@1on_10Upl0@der
for /f "tokens=*" %%i in ('curl -s -X POST -H "Content-Type: application/json" ^
-d "{\"email\":\"%EMAIL%\",\"password\":\"%PASSWORD%\"}" %API_URL%/login') do set RESPONSE=%%i
for /f "tokens=2 delims=:" %%a in ('echo %RESPONSE% ^| findstr /i "token"') do (
set "TOKEN=%%a"
set "TOKEN=!TOKEN:~1,-1!"
set "TOKEN=!TOKEN:~0,-2!"
)
set UPLOAD_URL=%API_URL%/resources/%DESTINATION%
echo Uploading %SOURCE_FILE% to %UPLOAD_URL%...
curl --location %UPLOAD_URL% ^
-H "Authorization: Bearer %TOKEN%" ^
-H "Content-Type: multipart/form-data" ^
--form "data=@%SOURCE_FILE%"
echo Upload complete!
+3 -38
View File
@@ -1,45 +1,10 @@
setlocal enabledelayedexpansion
set CONFIG=%1
@echo off @echo off
set API_URL=https://api.azaion.com set CONFIG=%1
set RESOURCES_FOLDER=%2 set RESOURCES_FOLDER=%2
set EMAIL=uploader@azaion.com
set PASSWORD=Az@1on_10Upl0@der
echo %cd%
set FILE1_TO_UPLOAD=%cd%\..\Azaion.Annotator\bin\%CONFIG%\net8.0-windows\Azaion.Annotator.dll set FILE1_TO_UPLOAD=%cd%\..\Azaion.Annotator\bin\%CONFIG%\net8.0-windows\Azaion.Annotator.dll
set "FILE1_TO_UPLOAD=%FILE1_TO_UPLOAD:\=/%" call upload-file %FILE1_TO_UPLOAD% %RESOURCES_FOLDER%
set FILE2_TO_UPLOAD=%cd%\..\Azaion.Dataset\bin\%CONFIG%\net8.0-windows\Azaion.Dataset.dll set FILE2_TO_UPLOAD=%cd%\..\Azaion.Dataset\bin\%CONFIG%\net8.0-windows\Azaion.Dataset.dll
set "FILE2_TO_UPLOAD=%FILE2_TO_UPLOAD:\=/%" call upload-file %FILE2_TO_UPLOAD% %RESOURCES_FOLDER%
echo Logging in and retrieving token...
for /f "tokens=*" %%i in ('curl -s -X POST -H "Content-Type: application/json" ^
-d "{\"email\":\"%EMAIL%\",\"password\":\"%PASSWORD%\"}" %API_URL%/login') do set RESPONSE=%%i
for /f "tokens=2 delims=:" %%a in ('echo %RESPONSE% ^| findstr /i "token"') do (
set "TOKEN=%%a"
set "TOKEN=!TOKEN:~1,-1!"
set "TOKEN=!TOKEN:~0,-2!"
)
:: Step 2: Upload the DLL file
set UPLOAD_URL=%API_URL%/resources/%RESOURCES_FOLDER%
echo Uploading file %FILE1_TO_UPLOAD% to %UPLOAD_URL%...
curl --location %UPLOAD_URL% ^
-H "Authorization: Bearer %TOKEN%" ^
-H "Content-Type: multipart/form-data" ^
--form "data=@%FILE1_TO_UPLOAD%"
echo Uploading file %FILE2_TO_UPLOAD% to %UPLOAD_URL%...
curl --location %UPLOAD_URL% ^
-H "Authorization: Bearer %TOKEN%" ^
-H "Content-Type: multipart/form-data" ^
--form "data=@%FILE2_TO_UPLOAD%"
echo Done!
+2 -2
View File
@@ -1,12 +1,12 @@
[Setup] [Setup]
AppId={{CCFEC8E2-0FCC-4B03-8EEA-00AF20D265E5}} AppId={{CCFEC8E2-0FCC-4B03-8EEA-00AF20D265E5}}
AppName=Azaion Suite AppName=Azaion Suite
AppVersion=1.3.2 AppVersion=1.4.2
AppPublisher=Azaion Ukraine AppPublisher=Azaion Ukraine
DefaultDirName={localappdata}\Azaion\Azaion Suite DefaultDirName={localappdata}\Azaion\Azaion Suite
DefaultGroupName=Azaion Suite DefaultGroupName=Azaion Suite
OutputDir=..\ OutputDir=..\
OutputBaseFilename=AzaionSuiteInstaller OutputBaseFilename=AzaionSuite1.4.2
SetupIconFile=..\dist\logo.ico SetupIconFile=..\dist\logo.ico
UninstallDisplayName=Azaion Suite UninstallDisplayName=Azaion Suite
UninstallDisplayIcon={app}\Azaion.Suite.exe UninstallDisplayIcon={app}\Azaion.Suite.exe
+13 -7
View File
@@ -5,9 +5,11 @@ echo Build .net app
dotnet build -c Release dotnet build -c Release
cd Azaion.Suite cd Azaion.Suite
call upload.cmd Release call upload Release
echo %cd%
call upload-file %cd%\config.secured.json
call upload-file %cd%\config.system.json
echo Publish .net app
dotnet publish -r win-x64 -p:SatelliteResourceLanguages="en" -p:DebugSymbols=false -p:ForPublish=true --self-contained true dotnet publish -r win-x64 -p:SatelliteResourceLanguages="en" -p:DebugSymbols=false -p:ForPublish=true --self-contained true
cd .. cd ..
rmdir dist /s /q rmdir dist /s /q
@@ -21,6 +23,8 @@ move dist\Azaion.Dataset.dll dist\dummy\
echo Build Cython app echo Build Cython app
cd Azaion.Inference cd Azaion.Inference
rmdir dist /s /q
.\venv\Scripts\pyinstaller --name=azaion-inference ^ .\venv\Scripts\pyinstaller --name=azaion-inference ^
--collect-all jwt ^ --collect-all jwt ^
--collect-all requests ^ --collect-all requests ^
@@ -48,7 +52,13 @@ cd Azaion.Inference
--hidden-import inference ^ --hidden-import inference ^
--hidden-import remote_command_handler ^ --hidden-import remote_command_handler ^
start.py start.py
move dist\start.exe ..\dist\azaion-inference.exe
xcopy /E dist\azaion-inference ..\dist\
copy venv\Lib\site-packages\tensorrt_libs\nvinfer_10.dll ..\dist
copy venv\Lib\site-packages\tensorrt_libs\nvinfer_plugin_10.dll ..\dist
copy venv\Lib\site-packages\tensorrt_libs\nvonnxparser_10.dll ..\dist
copy config.production.yaml ..\dist\config.yaml copy config.production.yaml ..\dist\config.yaml
cd.. cd..
@@ -70,9 +80,5 @@ copy %cudnn-folder%\* dist\*
del dist\cudnn_adv64_9.dll del dist\cudnn_adv64_9.dll
echo building installer... echo building installer...
iscc build\installer.iss iscc build\installer.iss
cd build\
echo uploading installer...
call cdn_manager.exe upload suite AzaionSuiteInstaller.exe ..\AzaionSuiteInstaller.exe