tracking
This commit is contained in:
@@ -14,12 +14,12 @@ from django.contrib.auth.models import User
|
||||
|
||||
# Multi-well positions on the table for calibration and observation
|
||||
MULTIWELL_POSITION = [
|
||||
('HG', _("Haut gauche")),
|
||||
('HD', _("Haut droit")),
|
||||
('BG', _("Bas gauche")),
|
||||
('BD', _("Bas droit")),
|
||||
('BM', _("Bas milieu")),
|
||||
('HM', _("Haut milieu")),
|
||||
('HG', _("HG-Haut gauche")),
|
||||
('HD', _("HD-Haut droit")),
|
||||
('BG', _("BG-Bas gauche")),
|
||||
('BD', _("BD-Bas droit")),
|
||||
('BM', _("BM-Bas milieu")),
|
||||
('HM', _("HM-Haut milieu")),
|
||||
]
|
||||
|
||||
FOURCC_FORMAT = [
|
||||
@@ -32,6 +32,12 @@ VIDEO_TYPE = [
|
||||
('avi', _("AVI")),
|
||||
]
|
||||
|
||||
CAPTURE_TYPE = [
|
||||
('rpi', _("Arducam")),
|
||||
('webcam', _("Webcam")),
|
||||
('file', _("mp4")),
|
||||
]
|
||||
|
||||
class Configuration(models.Model):
|
||||
name = models.CharField(_("Nom de la Configuration"), help_text=_("Nom de la configuration"), max_length=100, null=True, blank=False, default=_("Configuration par défaut"))
|
||||
author = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name="Auteur", null=True, blank=True)
|
||||
@@ -44,10 +50,10 @@ class Configuration(models.Model):
|
||||
# Grbl configuration
|
||||
grbl_xmax = models.FloatField(_("Grbl Xmax"), help_text=_("CNC Grbl Xmax en mm"), blank=False, default=350.0)
|
||||
grbl_ymax = models.FloatField(_("Grbl Ymax"), help_text=_("CNC Grbl Ymax en mm"), blank=False, default=250.0)
|
||||
|
||||
|
||||
# camera configuration
|
||||
use_rpicam = models.BooleanField(_("Utiliser rpicam"), help_text=_("Par défaaut. Sinon USB webcam"), default=True)
|
||||
capture_type = models.CharField(_("Capture"), help_text=_("Type de capture"), default='rpi', max_length=8, choices=CAPTURE_TYPE, null=True, blank=False)
|
||||
|
||||
webcam_device_index = models.PositiveSmallIntegerField(_("Index de la webcam"), help_text=_("Index de la webcam (0, 1, ...) si présente"), default=2)
|
||||
image_quality = models.PositiveSmallIntegerField(_("Qualité JPEG"), help_text=_("Qualité JPEG (1-100) pour les images exportées"), default=90)
|
||||
video_jpeg_quality = models.PositiveSmallIntegerField(_("Qualité JPEG pour les vidéos"), help_text=_("Qualité JPEG (1-100) pour les images extraites des vidéos"), default=90)
|
||||
@@ -60,6 +66,10 @@ class Configuration(models.Model):
|
||||
calibration_default_feed = models.PositiveIntegerField(_("Vitesse de calibration"), help_text=_("Vitesse de déplacement pour la calibration en mm/mn"), default=1000)
|
||||
calibration_default_step = models.FloatField(_("Pas de calibration"), help_text=_("Pas de déplacement pour la calibration en mm"), default=1.0)
|
||||
calibration_default_duration = models.FloatField(_("Duruée calibration"), help_text=_("Durée de pose entre chaque puits en s"), default=3.0)
|
||||
# tracking
|
||||
tracking = models.BooleanField(_("Suivi"), help_text=_("Suivi et analyse des planaires"), default=False)
|
||||
|
||||
#
|
||||
active = models.BooleanField(_("Actif"), default=False)
|
||||
|
||||
class Meta:
|
||||
|
||||
@@ -138,9 +138,8 @@ class CameraRecordManager():
|
||||
|
||||
class ScannerProcess(Task):
|
||||
|
||||
def __init__(self, use_tracking=False):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.use_tracking = use_tracking
|
||||
self.channel_layer = get_channel_layer()
|
||||
self.group = f'scanner_proc'
|
||||
self.stop_event = Event()
|
||||
@@ -162,6 +161,7 @@ class ScannerProcess(Task):
|
||||
def start(self, *args, **kwargs):
|
||||
try:
|
||||
self.conf = models.Configuration.objects.filter(active=True).first()
|
||||
self.use_tracking = self.conf.tracking
|
||||
|
||||
self.video_quality = self.conf.video_jpeg_quality
|
||||
self.image_quality = self.conf.image_quality
|
||||
@@ -176,7 +176,9 @@ class ScannerProcess(Task):
|
||||
self.grbl_ymax = self.conf.grbl_ymax
|
||||
|
||||
self.crop = self.set_crop_radius(self.crop_radius)
|
||||
if settings.TEST_VIDEOFILE:
|
||||
|
||||
capture_type = self.conf.capture_type
|
||||
if capture_type == 'file':
|
||||
video_lists = []
|
||||
wells = models.Well.objects.all()
|
||||
for wl in wells:
|
||||
@@ -194,7 +196,7 @@ class ScannerProcess(Task):
|
||||
parent=self,
|
||||
video_lists=video_lists,
|
||||
)
|
||||
elif not self.conf.use_rpicam:
|
||||
elif capture_type == 'webcam':
|
||||
from modules.webcam_capture import WebcamCapture
|
||||
self.cam = WebcamCapture(
|
||||
device_index=self.conf.webcam_device_index,
|
||||
@@ -275,6 +277,7 @@ class ScannerProcess(Task):
|
||||
try:
|
||||
(uuid, ts, frame, metrics) = self.record_queue.get()
|
||||
labels = dict(fps=self.video_fps, session=self.data.session, detected="1" if metrics.get("detected") else "0")
|
||||
|
||||
if metrics.get("detected"):
|
||||
labels.update({
|
||||
"cx" : str(metrics["cx"]),
|
||||
@@ -283,7 +286,8 @@ class ScannerProcess(Task):
|
||||
"speed_px_s" : str(metrics["speed_px_s"]),
|
||||
"axial_pos" : str(metrics["axial_pos"]),
|
||||
"axial_speed" : str(metrics["axial_speed"]),
|
||||
})
|
||||
})
|
||||
|
||||
self.recordDB.write(uuid, frame, labels, ts=ts)
|
||||
self.record_queue.task_done()
|
||||
except Exception as e:
|
||||
|
||||
@@ -3,7 +3,6 @@ import asyncio
|
||||
from celery import shared_task, group, chord, chain
|
||||
from celery.utils.log import get_task_logger
|
||||
from django.utils import timezone
|
||||
from django.conf import settings
|
||||
|
||||
from .process import ScannerProcess, ReplayProcess
|
||||
from .export_tasks import shm_download_video, export_images_zip, export_video_mp4
|
||||
@@ -19,7 +18,7 @@ class ScannerTaskManager:
|
||||
|
||||
def start_scanner(self):
|
||||
if self.scanner is None:
|
||||
self.scanner = ScannerProcess(use_tracking=settings.TRACKING)
|
||||
self.scanner = ScannerProcess()
|
||||
self.scanner.start()
|
||||
|
||||
def stop_scanner(self):
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
<a href="{% url 'scanner:admin' %}" class="w3-bar-item w3-btn w3-hover-opacity w3-margin-left">
|
||||
<i class="fa-solid fa-gear w3-text-pink"></i> {% trans "Administration base de données" %}
|
||||
</a>
|
||||
<a href="{% url 'scanner:reductstore' %}" class="w3-bar-item w3-btn w3-hover-opacity w3-margin-left">
|
||||
<a href="{% url 'scanner:reductstore' %}" class="w3-bar-item w3-btn w3-hover-opacity w3-margin-left" target="_blank">
|
||||
<img class="w3-no-padding" src="/static/img/reductstore.png" style="width: 24px"> {% trans "Base de données Reductstore" %}
|
||||
</a>
|
||||
<a href="{% url 'scanner:adminer' %}" class="w3-bar-item w3-btn w3-hover-opacity w3-margin-left" target="_blank">
|
||||
@@ -83,13 +83,13 @@
|
||||
<!--a href="{% url 'scanner:portainer' %}" class="w3-bar-item w3-btn w3-hover-opacity" w3-margin-left target="_blank">
|
||||
<img class="w3-no-padding" src="/static/img/portainer.png" style="width: 28px"> {% trans "Portainer" %}
|
||||
</a-->
|
||||
<a href="{% url 'scanner:supervisor' %}" class="w3-bar-item w3-btn w3-hover-opacity w3-margin-left">
|
||||
<a href="{% url 'scanner:supervisor' %}" class="w3-bar-item w3-btn w3-hover-opacity w3-margin-left" target="_blank">
|
||||
<i class="fa-solid fa-gears w3-text-purple"></i> {% trans "Supervisor" %}
|
||||
</a>
|
||||
<a href="{% url 'scanner:logs_scheduler' %}" class="w3-bar-item w3-btn w3-hover-opacity w3-margin-left">
|
||||
<a href="{% url 'scanner:logs_scheduler' %}" class="w3-bar-item w3-btn w3-hover-opacity w3-margin-left" target="_blank">
|
||||
<i class="fa-regular fa-file-lines w3-text-orange"></i> {% trans "Logs des planifications" %}
|
||||
</a>
|
||||
<a href="{% url 'scanner:logs_worker' %}" class="w3-bar-item w3-btn w3-hover-opacity w3-margin-left">
|
||||
<a href="{% url 'scanner:logs_worker' %}" class="w3-bar-item w3-btn w3-hover-opacity w3-margin-left" target="_blank">
|
||||
<i class="fa-regular fa-file-lines w3-text-amber"></i> {% trans "Logs des services" %}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -133,17 +133,17 @@
|
||||
</div>
|
||||
<div class="w3-row w3-row-padding">
|
||||
<div class="w3-half">
|
||||
<button id="_calib_debug" class="w3-button w3-dark-xlight w3-round-large w3-padding-small w3-block">
|
||||
<button id="_calib_debug" class="w3-button w3-dark-xlight w3-round-large w3-padding-1" title="{% trans 'Ce mode permet les réglages graphiques' %}">
|
||||
{% trans 'Debug' %}<br><i class="fa-solid fa-triangle-exclamation w3-text-amber w3-xlarge"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w3-half">
|
||||
<button id="_median" class="w3-button w3-dark-xlight w3-round-large w3-padding-small w3-block">
|
||||
{% trans 'Axes' %} <br><i class="fa-solid fa-crosshairs w3-text-amber w3-xlarge"></i>
|
||||
<button id="_median" class="w3-button w3-dark-xlight w3-round-large w3-padding-1">
|
||||
{% trans 'Axes' %}<br><i class="fa-solid fa-crosshairs w3-text-amber w3-xlarge"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="w3-col">
|
||||
<button id="_crop" class="w3-button w3-dark-xlight w3-round-large w3-padding-small w3-margin-top w3-block">
|
||||
<button id="_crop" class="w3-button w3-dark-xlight w3-round-large w3-padding-small w3-margin-top w3-block" title="{% trans 'Ce mode actionne le pointage graphique' %}">
|
||||
{% trans 'Recadrer' %}<br><i class="fa-solid fa-crop w3-text-amber w3-xlarge"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -50,7 +50,7 @@ def admin_view(request):
|
||||
|
||||
@login_required
|
||||
def reductstore_view(request):
|
||||
return render(request, "scanner/iframe.html", context=global_context(request, link=f'http://{settings.DOMAIN_SERVER}:8383/'))
|
||||
return render(request, "scanner/redirection.html", context=global_context(request, link=f'http://{settings.DOMAIN_SERVER}:8383/'))
|
||||
|
||||
@login_required
|
||||
def adminer_view(request):
|
||||
@@ -62,15 +62,15 @@ def portainer_view(request):
|
||||
|
||||
@login_required
|
||||
def supervisor_view(request):
|
||||
return render(request, "scanner/iframe.html", context=global_context(request, link=f'http://{settings.DOMAIN_SERVER}:9001/'))
|
||||
return render(request, "scanner/redirection.html", context=global_context(request, link=f'http://{settings.DOMAIN_SERVER}:9001/'))
|
||||
|
||||
@login_required
|
||||
def supervisor_worker(request):
|
||||
return render(request, "scanner/iframe.html", context=global_context(request, link=f'http://{settings.DOMAIN_SERVER}:9001/logtail/test_tube:services'))
|
||||
return render(request, "scanner/redirection.html", context=global_context(request, link=f'http://{settings.DOMAIN_SERVER}:9001/logtail/test_tube:services'))
|
||||
|
||||
@login_required
|
||||
def supervisor_scheduler(request):
|
||||
return render(request, "scanner/iframe.html", context=global_context(request, link=f'http://{settings.DOMAIN_SERVER}:9001/logtail/test_tube:planification'))
|
||||
return render(request, "scanner/redirection.html", context=global_context(request, link=f'http://{settings.DOMAIN_SERVER}:9001/logtail/test_tube:planification'))
|
||||
|
||||
## Mainboard
|
||||
@login_required
|
||||
|
||||
Reference in New Issue
Block a user