feat: Add support for thumbnail inclusion in AI processing and enhance UI bindings
This commit is contained in:
parent
cb41c42bb5
commit
7e105e3738
9 changed files with 235 additions and 27 deletions
|
|
@ -16,6 +16,7 @@ using System.Text;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Input;
|
||||
using AIFotoONLUS.Core;
|
||||
using AutoMapper;
|
||||
using MaddoShared;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
|
@ -117,6 +118,7 @@ namespace ImageCatalog_2
|
|||
|
||||
// Load available fonts
|
||||
AvailableFonts = LoadAvailableFonts();
|
||||
RefreshNumberAiGpuCapabilities();
|
||||
RefreshFaceExecutableCapabilities();
|
||||
}
|
||||
|
||||
|
|
@ -131,6 +133,16 @@ namespace ImageCatalog_2
|
|||
{
|
||||
// user cancelled
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "AI extraction failed");
|
||||
if (UseNumberAiGpu)
|
||||
{
|
||||
RefreshNumberAiGpuCapabilities();
|
||||
}
|
||||
|
||||
await ShowErrorMessageAsync("Errore AI", ex.GetBaseException().Message).ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
MainToken = null;
|
||||
|
|
@ -162,12 +174,19 @@ namespace ImageCatalog_2
|
|||
{
|
||||
SearchRoot = searchRoot,
|
||||
Recursive = recursive,
|
||||
IncludeThumbnails = IncludeNumberAiThumbnails,
|
||||
ModelsFolderPath = ModelsFolderPath,
|
||||
UseGpu = UseNumberAiGpu,
|
||||
CsvOutputPath = CsvOutputPath
|
||||
},
|
||||
token,
|
||||
result => InvokeOnUiThreadAsync(() => PreviewResults.Add(result)),
|
||||
result => InvokeOnUiThreadAsync(() =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(result.Text))
|
||||
{
|
||||
PreviewResults.Add(result);
|
||||
}
|
||||
}),
|
||||
progress => InvokeOnUiThreadAsync(() => AiProgress = progress)).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
|
|
@ -200,7 +219,11 @@ namespace ImageCatalog_2
|
|||
public string ModelsFolderPath
|
||||
{
|
||||
get => _ai.ModelsFolderPath;
|
||||
set => _ai.ModelsFolderPath = value;
|
||||
set
|
||||
{
|
||||
_ai.ModelsFolderPath = value;
|
||||
RefreshNumberAiGpuCapabilities();
|
||||
}
|
||||
}
|
||||
|
||||
public string CsvOutputPath
|
||||
|
|
@ -212,7 +235,19 @@ namespace ImageCatalog_2
|
|||
public bool UseNumberAiGpu
|
||||
{
|
||||
get => _ai.UseNumberAiGpu;
|
||||
set => _ai.UseNumberAiGpu = value;
|
||||
set => SetUseNumberAiGpu(value);
|
||||
}
|
||||
|
||||
public bool NumberAiGpuOptionEnabled
|
||||
{
|
||||
get => _ai.NumberAiGpuOptionEnabled;
|
||||
private set => _ai.NumberAiGpuOptionEnabled = value;
|
||||
}
|
||||
|
||||
public bool IncludeNumberAiThumbnails
|
||||
{
|
||||
get => _ai.IncludeNumberAiThumbnails;
|
||||
set => _ai.IncludeNumberAiThumbnails = value;
|
||||
}
|
||||
|
||||
public string FaceExecutablePath
|
||||
|
|
@ -1302,23 +1337,6 @@ namespace ImageCatalog_2
|
|||
},
|
||||
speed => { SpeedCounter = speed; }).ConfigureAwait(false);
|
||||
|
||||
// AI integration: OCR runs over processed output so it matches the face AI input folder.
|
||||
if (ExtractNumbers)
|
||||
{
|
||||
try
|
||||
{
|
||||
await RunAiExtractionCoreAsync(token, useDestination: true, recursive: true);
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_logger.LogInformation("AI extraction canceled");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "AI extraction failed");
|
||||
}
|
||||
}
|
||||
|
||||
SpeedCounter = runResult.FinalSpeedCounter;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
|
|
@ -1762,6 +1780,71 @@ namespace ImageCatalog_2
|
|||
}
|
||||
}
|
||||
|
||||
private void RefreshNumberAiGpuCapabilities()
|
||||
{
|
||||
if (!TryBuildNumberAiModelConfiguration(out var configuration))
|
||||
{
|
||||
NumberAiGpuOptionEnabled = false;
|
||||
_ai.UseNumberAiGpu = false;
|
||||
return;
|
||||
}
|
||||
|
||||
NumberAiGpuOptionEnabled = NumberRecognitionEngine.TryValidateGpuRuntime(configuration, _logger, out _);
|
||||
if (!NumberAiGpuOptionEnabled)
|
||||
{
|
||||
_ai.UseNumberAiGpu = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetUseNumberAiGpu(bool value)
|
||||
{
|
||||
if (!NumberAiGpuOptionEnabled)
|
||||
{
|
||||
_ai.UseNumberAiGpu = false;
|
||||
return;
|
||||
}
|
||||
|
||||
_ai.UseNumberAiGpu = value;
|
||||
}
|
||||
|
||||
private bool TryBuildNumberAiModelConfiguration(out ModelConfiguration configuration)
|
||||
{
|
||||
configuration = null!;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(ModelsFolderPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var modelsRoot = Path.GetFullPath(ModelsFolderPath.Trim().Trim('"'));
|
||||
if (!Directory.Exists(modelsRoot))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
configuration = new ModelConfiguration
|
||||
{
|
||||
DetectionCfg = Path.Combine(modelsRoot, "detection.cfg"),
|
||||
DetectionWeights = Path.Combine(modelsRoot, "detection.weights"),
|
||||
RecognitionCfg = Path.Combine(modelsRoot, "recognition.cfg"),
|
||||
RecognitionWeights = Path.Combine(modelsRoot, "recognition.weights"),
|
||||
UseGpu = true
|
||||
};
|
||||
|
||||
return File.Exists(configuration.DetectionCfg)
|
||||
&& File.Exists(configuration.DetectionWeights)
|
||||
&& File.Exists(configuration.RecognitionCfg)
|
||||
&& File.Exists(configuration.RecognitionWeights);
|
||||
}
|
||||
|
||||
private Task ShowErrorMessageAsync(string title, string message)
|
||||
{
|
||||
return InvokeOnUiThreadAsync(() =>
|
||||
{
|
||||
ShowMessageRequested?.Invoke(this, Tuple.Create(title, message, 0));
|
||||
});
|
||||
}
|
||||
|
||||
private void SetUseFaceGpu(bool value)
|
||||
{
|
||||
var currentValue = _ai.UseFaceGpu;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue