4 coordWidget, a module for pymecavideo:
5 a program to track moving points
in a video frameset
7 Copyright (C) 2007 Jean-Baptiste Butet <ashashiwa
@gmail.com>
8 Copyright (C) 2023 Georges Khaznadar <georgesk
@debian.org>
10 This program
is free software: you can redistribute it
and/
or modify
11 it under the terms of the GNU General Public License
as published by
12 the Free Software Foundation, either version 3 of the License,
or
13 (at your option) any later version.
15 This program
is distributed
in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License
for more details.
20 You should have received a copy of the GNU General Public License
21 along
with this program. If
not, see <http://www.gnu.org/licenses/>.
24from PyQt6.QtCore import QThread, pyqtSignal, QLocale, QTranslator, Qt, \
25 QSize, QTimer, QObject, QRect, QPoint, QPointF, QEvent
26from PyQt6.QtGui
import QKeySequence, QIcon, QPixmap, QImage, QPainter, \
27 QCursor, QPen, QColor, QFont, QResizeEvent, QShortcut
28from PyQt6.QtWidgets
import QApplication, QMainWindow, QWidget, QLayout, \
29 QFileDialog, QTableWidgetItem, QInputDialog, QLineEdit, QMessageBox, \
30 QTableWidgetSelectionRange, QPushButton
32import os, time, re, sys
35from version
import Version
36from vecteur
import vecteur
37from image_widget
import ImageWidget
38from globdef
import cible_icon, DOCUMENT_PATH, inhibe, pattern_float
39from toQimage
import toQImage
40from suivi_auto
import SelRectWidget
41from detect
import filter_picture
42from cadreur
import Cadreur, openCvReader
43from export
import Export, EXPORT_FORMATS
46import interfaces.icon_rc
48from interfaces.Ui_coordWidget
import Ui_coordWidget
49from etatsCoord
import Etats
53 Widget principal de l'onglet coordonnées
55 paramètres du constructeur :
56 @param parent l
'onglet des coordonnées
58 def __init__(self, parent):
59 QWidget.__init__(self, parent)
60 Ui_coordWidget.__init__(self)
66 for key
in sorted(EXPORT_FORMATS.keys()):
67 self.
exportCombo.addItem(EXPORT_FORMATS[key][
'nom'])
74 Crée des liens avec la fenêtre principale, le débogueur,
76 @param app la fenêtre principale
85 Connecte les signaux des sous-widgets
95 def export(self, choix_export=None):
96 self.
dbg.p(2,
"rentre dans 'export'")
98 Traite le signal venu de exportCombo, puis remet l\'index de ce
109 Export(self, choix_export)
112 def recommence_echelle(self):
113 self.
app.new_echelle.emit()
118 lancée à chaque affichage du tableau, recalcule les coordonnées
119 à afficher à partir des listes de points.
121 self.dbg.p(2, "rentre dans 'affiche_tableau'")
149 colonne_refait_points = self.
pointage.nb_obj * (2 + colonnes_sup) + 1
153 self.
tableWidget.setItem(i, 0, QTableWidgetItem(f
"{t:.3f}"))
156 def cb_point(i, t, j, obj, p, v):
161 col = 1 + (2 + colonnes_sup) * j
164 i, col, QTableWidgetItem(f
"{p.x:.4g}"))
167 i, col, QTableWidgetItem(f
"{p.y:.4g}"))
174 Ec = 0.5 * m * v.norme ** 2
176 i, col, QTableWidgetItem(f
"{Ec:.4g}"))
182 i, col, QTableWidgetItem(f
"{Epp:.4g}"))
188 i, col, QTableWidgetItem(f
"{Ec+Epp:.4g}"))
192 derniere = self.
pointage.nb_obj * (2 + colonnes_sup) +1
199 unite =
"m" if self.
pointage.echelle_image
else "px")
203 colonne = self.
pointage.nb_obj * (2 + colonnes_sup) +1
204 if self.
pointage.premiere_image()
is None:
return
205 if self.
pointage.premiere_image() > 1:
206 i = self.
pointage.premiere_image() - 2
214 """Sélectionne la totalité du tableau de coordonnées
215 et l'exporte dans le presse-papier (l'exportation est implicitement
216 héritée de la classe utilisée pour faire le tableau). Les
217 séparateurs décimaux sont automatiquement remplacés par des virgules
218 si la locale est française.
220 self.dbg.p(2, "rentre dans 'presse_papier'")
222 trange = QTableWidgetSelectionRange(0, 0,
232 for i
in range(selected[0].topRow(), selected[0].bottomRow() + 1):
233 for j
in range(selected[0].leftColumn(), selected[0].rightColumn() + 1):
236 except AttributeError:
239 texte = texte[:-1] +
"\n"
241 QApplication.clipboard().setText(texte)
246 Crée un tableau de coordonnées neuf dans l'onglet idoine.
247 @param nb_suivis le nombre d
'objets suivis (1 par défaut)
249 self.dbg.p(2, "rentre dans 'cree_tableau'")
259 self.
tableWidget.setColumnCount(nb_suivis * (2 + colonnes_sup) + 2)
264 0, QTableWidgetItem(
't (s)'))
266 for i
in range(nb_suivis):
267 unite =
"m" if self.
pointage.echelle_image \
270 1 + (2+colonnes_sup) * i, QTableWidgetItem(
271 f
"X{i + 1} ({unite})"))
273 2 + (2+colonnes_sup) * i, QTableWidgetItem(
274 f
"Y{i + 1} ({unite})"))
275 for j
in range(colonnes_sup):
279 3+cptr + (2+colonnes_sup)*i, QTableWidgetItem(f
"Ec{1 + i} (J)"))
283 3+cptr + (2+colonnes_sup)*i, QTableWidgetItem(f
"Epp{1 + i} (J)"))
287 3+cptr + (2+colonnes_sup)*i, QTableWidgetItem(f
"Em{1 + i} (J)"))
291 nb_suivis * 2 + 1 + colonnes_sup*nb_suivis,
292 QTableWidgetItem(
"Refaire le point"))
297 permet de remplir le tableau des coordonnées à la demande.
298 Se produit quand on ouvre un fichier pymecavideo ou quand on
301 self.dbg.p(2, "rentre dans 'recalculLesCoordonnees'")
306 self.
tableWidget.setItem(i, 0, QTableWidgetItem(f
"{t:.3f}"))
309 def cb_point(i, t, j, obj, p, v):
314 i, j*(nb_suivis)+1, QTableWidgetItem(str(p.x)))
316 i, j*(nb_suivis) + 2, QTableWidgetItem(str(p.y)))
320 self.
pointage.iteration_data(cb_temps, cb_point, unite =
"m")
325 Crée un bouton servant à refaire un pointage, pour la donnée
326 affichée dans une ligne du tableau
327 @param ligne une ligne du tableau (indexée à partir de 0)
331 b.setIcon(QIcon(":/data/icones/curseur_cible.svg"))
332 b.setToolTip(self.tr(
333 "refaire le pointage\n de l'image {numero}").format(
336 b.clicked.connect(
lambda state: \
337 self.
pointage.refait_point_depuis_tableau( b ))
338 b.index_image = ligne + 1
341 def masse(self, obj):
343 Renseigne la masse d'un objet. L'implémentation est actuellement
344 incomplète : une seule masse est autorisée, pour tous les objets
345 donc on ne tient pas compte du paramètre obj
346 @param obj un objet suivi
347 @return la masse de cet objet
350 masse_objet_raw, ok = QInputDialog.getText(
352 self.tr(
"Masse de l'objet"),
353 self.tr(
"Quelle est la masse de l'objet ? (en kg)"),
355 masse_objet_raw = masse_objet_raw.replace(
",",
".")
356 ok = ok
and pattern_float.match(masse_objet_raw)
357 masse_objet = float(masse_objet_raw)
358 if masse_objet <= 0
or not ok:
359 self.affiche_statut.emit(self.tr(
360 "Merci d'indiquer une masse valable"))
Une classe qui permet de définir les états pour le ccordWidget debut, A, AB, B, C,...
Une classe qui gère l'exportation des données.