forked from amkovkov/GranuSightSoftware2
1) remove unused components: camera view (due it causes segmentation faults), compute resources and all related, illuminator controller (due in useless without camera view), image storage service, temperature and humidity service 2) database schema - reduce tables references, features storing in records themselves in compressed form, add records creation and editing date and time, add separator comment column 3) analysis - rework of pipeline and ui, now database storing only raw data and all display values calculated from it 4) lights service - add reconnection if disconnected 5) add width and height command line arguments 6) fix some typos and other issues
121 lines
4.4 KiB
C#
121 lines
4.4 KiB
C#
|
|
using System.Collections.ObjectModel;
|
|
using System.Drawing;
|
|
|
|
using GSS2.Core.Extensions;
|
|
using GSS2.Core.Hardware;
|
|
|
|
using Microsoft.Extensions.Logging;
|
|
|
|
using OpenCvSharp;
|
|
|
|
namespace GSS2.Core.Analysis.AmineContent;
|
|
|
|
public class ImageCapturerService : IImageCapturerService
|
|
{
|
|
// Список интенсивностей освещения для каждого кадра
|
|
public static readonly ReadOnlyCollection<(double visible, double uv365, double uv254)> IlluminatorIntensities =
|
|
[
|
|
(0.02500, 0.0, 0.0),
|
|
(0.01250, 0.0, 0.0),
|
|
(0.00625, 0.0, 0.0),
|
|
(0.00000, 1.0, 0.0),
|
|
(0.00000, 0.0, 1.0),
|
|
(0.00000, 1.0, 1.0),
|
|
(0.01250, 1.0, 0.0),
|
|
(0.01250, 0.0, 1.0),
|
|
(0.01250, 1.0, 1.0),
|
|
(0.00625, 1.0, 0.0),
|
|
(0.00625, 0.0, 1.0),
|
|
(0.00625, 1.0, 1.0)
|
|
];
|
|
|
|
private readonly ILogger<ImageCapturerService> _logger;
|
|
private readonly CameraService _camera;
|
|
private readonly IlluminatorService _illuminator;
|
|
private readonly LightsService _lights;
|
|
|
|
public ImageCapturerService(
|
|
ILogger<ImageCapturerService> logger,
|
|
CameraService camera,
|
|
IlluminatorService illuminator,
|
|
LightsService lights
|
|
)
|
|
{
|
|
_logger = logger;
|
|
_camera = camera;
|
|
_illuminator = illuminator;
|
|
_lights = lights;
|
|
}
|
|
|
|
public async Task CaptureImages(Action<(int i, double visible, double uv365, double uv254, Mat image)> callback, CancellationToken cancellationToken) =>
|
|
await CaptureImages(async (data) => callback(data), cancellationToken);
|
|
|
|
public async Task CaptureImages(Func<(int i, double visible, double uv365, double uv254, Mat image), Task> callback, CancellationToken cancellationToken)
|
|
{
|
|
// Включаем осветитель
|
|
_illuminator.TurnOn();
|
|
|
|
// Если ViewFinder запущен, то для съёмки изображений его нужно остановить
|
|
// потом после съёмки снова запустить
|
|
var needRestartViewFinder = _camera.ViewFinderStarted;
|
|
|
|
try
|
|
{
|
|
// Для каждой интенсивности
|
|
foreach (var (i, (visible, uv365, uv254)) in IlluminatorIntensities.Enumerate())
|
|
{
|
|
// Выбрасываем исключение если задача отменена
|
|
cancellationToken.ThrowIfCancellationRequested();
|
|
|
|
// Логгируем прогресс
|
|
_logger.LogInformation("Capturing images: {} / {} ({};{};{})", i + 1, IlluminatorIntensities.Count(), visible, uv365, uv254);
|
|
// Отображаем прогресс на светодиодах
|
|
_lights.Load(0.3, 1, (double)(i + 1) / IlluminatorIntensities.Count * 100, (double)i / IlluminatorIntensities.Count * 100, Color.Yellow);
|
|
|
|
// Устанавливаем интенсивность
|
|
_illuminator.SetIntensity(visible, uv365, uv254);
|
|
// Ждём разогрева светодиодов
|
|
await Task.Delay(200);
|
|
|
|
// Получаем изображение
|
|
Mat? image;
|
|
image = await _camera.CaptureImage(cancellationToken, 2);
|
|
if (image is null)
|
|
throw new Exception("Image capture failed");
|
|
|
|
// Вызываем коллбек
|
|
await callback.Invoke((i, visible, uv365, uv254, image));
|
|
}
|
|
|
|
// Если ошибок не было, то мигаем светодиодами зелёным
|
|
_ = Task.Run(async () =>
|
|
{
|
|
await Task.Delay(1000);
|
|
_lights.Flash(1, 1, Color.Green);
|
|
await Task.Delay(3000);
|
|
_lights.Disconnect();
|
|
});
|
|
}
|
|
catch (OperationCanceledException)
|
|
{ }
|
|
catch
|
|
{
|
|
// Если была ошибка, то мигаем светодиодами красным
|
|
_ = Task.Run(async () =>
|
|
{
|
|
await Task.Delay(1000);
|
|
_lights.Flash(1, 1, Color.Red);
|
|
await Task.Delay(3000);
|
|
_lights.Disconnect();
|
|
});
|
|
throw;
|
|
}
|
|
finally
|
|
{
|
|
// В любом случае отключаем осветитель
|
|
_illuminator.TurnOff();
|
|
}
|
|
}
|
|
}
|