AI Pettorali

This commit is contained in:
MaddoScientisto 2026-05-09 17:27:05 +02:00
commit cb41c42bb5
11 changed files with 379 additions and 55 deletions

View file

@ -5,6 +5,7 @@ using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AIFotoONLUS.Core;
using ImageCatalog_2.Models;
using Microsoft.Extensions.Logging;
@ -35,36 +36,14 @@ public class AiExtractionService : IAiExtractionService
|| f.EndsWith(".gif", StringComparison.OrdinalIgnoreCase))
.ToList();
if (imageFiles.Count == 0)
{
return;
}
var extractedResults = new List<AiResultItem>();
var modelConfiguration = BuildModelConfiguration(request.ModelsFolderPath, request.UseGpu);
Type? aiProcessorType = null;
object? aiProcessor = null;
try
{
var assembly = AppDomain.CurrentDomain.GetAssemblies()
.FirstOrDefault(a => a.GetName().Name?.Equals("AIFotoONLUS.Core", StringComparison.OrdinalIgnoreCase) == true);
if (assembly != null)
{
aiProcessorType = assembly.GetType("AIFotoONLUS.Core.AiProcessor");
if (aiProcessorType != null)
{
aiProcessor = Activator.CreateInstance(aiProcessorType);
}
}
}
catch (Exception ex)
{
_logger.LogDebug(ex, "AIFotoONLUS.Core not available or failed to load via reflection");
}
using var engine = new NumberRecognitionEngine(modelConfiguration, _logger);
var processed = 0;
var total = imageFiles.Count;
var failed = 0;
foreach (var file in imageFiles)
{
@ -72,39 +51,30 @@ public class AiExtractionService : IAiExtractionService
var extracted = string.Empty;
if (aiProcessorType is not null && aiProcessor is not null)
try
{
try
{
var method = aiProcessorType.GetMethod("ExtractNumbersFromImage")
?? aiProcessorType.GetMethod("ExtractTextFromImage");
if (method is not null)
{
var value = method.Invoke(aiProcessor, new object[] { file });
if (value != null)
{
extracted = value.ToString() ?? string.Empty;
}
}
}
catch (Exception ex)
{
_logger.LogWarning(ex, "Error invoking AI processor for {File}", file);
}
extracted = engine.ProcessImage(file).Text;
}
catch (Exception ex)
{
failed++;
_logger.LogWarning(ex, "Error processing AI OCR for {File}", file);
}
if (!string.IsNullOrWhiteSpace(extracted))
{
var result = new AiResultItem { Path = file, Text = extracted };
extractedResults.Add(result);
await onResult(result).ConfigureAwait(false);
}
var result = new AiResultItem { Path = file, Text = extracted };
extractedResults.Add(result);
await onResult(result).ConfigureAwait(false);
processed++;
var percent = total > 0 ? (processed * 100.0 / total) : 100.0;
await onProgress(percent).ConfigureAwait(false);
}
if (imageFiles.Count > 0 && failed == imageFiles.Count)
{
throw new InvalidOperationException($"AI OCR failed for all {imageFiles.Count} image(s). See previous log entries for details.");
}
if (!string.IsNullOrWhiteSpace(request.CsvOutputPath))
{
try
@ -129,4 +99,27 @@ public class AiExtractionService : IAiExtractionService
}
}
}
private static ModelConfiguration BuildModelConfiguration(string modelsFolderPath, bool useGpu)
{
if (string.IsNullOrWhiteSpace(modelsFolderPath))
{
throw new InvalidOperationException("AI models folder is not configured.");
}
var modelsRoot = Path.GetFullPath(modelsFolderPath.Trim().Trim('"'));
if (!Directory.Exists(modelsRoot))
{
throw new DirectoryNotFoundException($"AI models folder not found: {modelsRoot}");
}
return 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 = useGpu
};
}
}