Pymecavideo 8.0
Étude cinématique à l'aide de vidéos
etatsPointage.py
1# -*- coding: utf-8 -*-
2
3"""
4 etatsPointage, a module for pymecavideo:
5 a program to track moving points in a video frameset
6
7 Copyright (C) 2023 Georges Khaznadar <georgesk@debian.org>
8
9 This program is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21"""
22
23from PyQt6.QtCore import Qt, QObject, pyqtSignal, QTimer
24
25import os
26
27from vecteur import vecteur
28from etats import Etats_Base
29
30class Etats(Etats_Base):
31 """
32 Une classe qui permet de définir les états pour le pointageWidget
33 debut, A, AB, B, C, D, E : voir le fichier etats_pymecavideo.html
34 """
35
36 def __init__(self):
37 Etats_Base.__init__(self)
38 return
39
40 def changeEtat(self, etat):
41 """
42 Mise en place d'un état de l'interface utilisateur, voir la
43 documentation dans le fichier etat_pymecavideo.html
44
45 après l'état C, il faut tenir compte d'un ancien état, A*/D*
46 """
47 self.etat = etat
48 if etat =="debut":
49 self.label_zoom.emit(self.tr("Zoom autour de x, y ="))
50 # désactivation de widgets
51 for obj in self.spinBox_image, \
52 self.pushButton_rot_droite, self.pushButton_rot_gauche, \
53 self.pushButton_stopCalculs, \
54 self.label_nb_de_points, \
55 self.spinBox_objets, self.Bouton_Echelle, \
56 self.checkBox_auto, self.Bouton_lance_capture, \
57 self.pushButton_reinit, self.pushButton_origine, \
58 self.pushButton_defait, self.pushButton_refait, \
59 self.checkBox_abscisses, self.checkBox_ordonnees, \
60 self.label_IPS, self.lineEdit_IPS :
61
62 obj.setEnabled(False)
63
64 # désactive les contôles de l'image
65 self.imgControlImage(False)
66
67 # marque "indéf." dans l'afficheur d'échelle à gauche
68 self.affiche_echelle()
69
70 # mise à jour de styles
71 self.Bouton_Echelle.setStyleSheet("background-color:None;")
72
73 self.pushButton_stopCalculs.hide()
74 # inactive le spinner pour les incréments de plus d'une image
75 # voir la demande de Isabelle.Vigneau@ac-versailles.fr, 15 Sep 2022
76 # non encore implémentée
77 self.imgno_incr.hide()
78 self.spinBox.hide()
79 if etat =="A":
80 self.objet_courant = 1
81 self.label_zoom.emit(self.tr("Zoom autour de x, y ="))
82 if not self.echelle_image:
83 self.affiche_echelle() # marque "indéf."
84 self.echelle_modif.emit(self.tr("Définir l'échelle"),
85 "background-color:None;")
86 if self.echelle_trace:
87 self.echelle_trace.hide()
88 # active les contrôle de l'image, montre l'image
89 self.imgControlImage(True)
90 self.affiche_image()
91 # réactive plusieurs widgets
92 for obj in self.label_nb_de_points, self.pushButton_reinit, \
93 self.spinBox_objets, self.Bouton_Echelle, \
94 self.checkBox_auto, self.Bouton_lance_capture, \
95 self.pushButton_origine, \
96 self.checkBox_abscisses, self.checkBox_ordonnees, \
97 self.label_IPS, self.lineEdit_IPS, self.spinBox_objets :
98
99 obj.setEnabled(True)
100
101 # si une échelle est définie, on interdit les boutons de rotation
102 # sinon on autorise ces boutons
103 rotation_possible = not self.echelle_image
104 for obj in self.pushButton_rot_droite, self.pushButton_rot_gauche :
105 obj.setEnabled(rotation_possible)
106
107 # ajuste le nombre d'objets suivis
108 if self.suivis:
109 self.spinBox_objets.setValue(self.nb_obj)
110 else:
111 self.dimension_data.emit(1)
112 self.spinBox_objets.setValue(1)
113
114 # desactive d'autres widgets
115 self.pushButton_stopCalculs.setEnabled(False)
116 self.pushButton_stopCalculs.hide()
117 self.enableDefaire(False)
118 self.enableRefaire(False)
119 self.checkBox_abscisses.setCheckState(Qt.CheckState.Unchecked)
120 self.checkBox_ordonnees.setCheckState(Qt.CheckState.Unchecked)
121 self.checkBox_auto.setCheckState(Qt.CheckState.Unchecked)
122 """
123 Prépare une session de pointage, au niveau de la
124 fenêtre principale, et met à jour les préférences
125 """
126 d = self.prefs.defaults
127 d['lastVideo'] = self.filename
128 d['videoDir'] = os.path.dirname(self.filename)
129 d["taille_image"] = f"({self.video.image_w},{self.video.image_h})"
130 d['rotation'] = str(self.video.rotation)
131 self.prefs.save()
132 if etat =="AB":
133 self.label_zoom.emit(self.tr("Zoom autour de x, y ="))
134 # désactive plusieurs widgets
135 for obj in self.pushButton_rot_droite, self.pushButton_rot_gauche, \
136 self.label_nb_de_points, \
137 self.spinBox_objets, self.Bouton_Echelle, \
138 self.checkBox_auto, self.Bouton_lance_capture, \
139 self.pushButton_origine, \
140 self.checkBox_abscisses, self.checkBox_ordonnees, \
141 self.label_IPS, self.lineEdit_IPS :
142
143 obj.setEnabled(False)
144
145 self.imgControlImage(False)
146 # on démarre la définition des zones à suivre
147 self.capture_auto()
148 if etat =="B":
149 self.pushButton_stopCalculs.setText("STOP")
150 self.pushButton_stopCalculs.setEnabled(True)
151 self.pushButton_stopCalculs.show()
152 self.update()
153 # initialise la détection des points
154 self.detecteUnPoint()
155 if etat =="C":
156 # on prévoit un retour à l'état A ou D selon celui où on
157 # commence à définir l'échelle
158 self.etat_ancienetat_ancien = self.app.etat_ancien
159 self.label_zoom.emit(self.tr("Zoom autour de x, y ="))
160 # désactive plusieurs widgets
161 for obj in self.pushButton_rot_droite, self.pushButton_rot_gauche, \
162 self.label_nb_de_points, \
163 self.spinBox_objets, self.Bouton_Echelle, \
164 self.checkBox_auto, self.Bouton_lance_capture, \
165 self.pushButton_origine, \
166 self.checkBox_abscisses, self.checkBox_ordonnees, \
167 self.label_IPS, self.lineEdit_IPS:
168
169 obj.setEnabled(False)
170 if etat =="D":
171 self.label_zoom.emit(self.tr("Pointage ({obj}) ; x, y =").format(obj = self.suivis[0]))
172 # empêche de redimensionner la fenêtre
173 self.app.stopRedimensionnement.emit()
174 # prépare le widget video
175 self.setFocus()
176 if self.echelle_trace: self.echelle_trace.lower()
177 # on cache le bouton STOP
178 self.pushButton_stopCalculs.setEnabled(False)
179 self.pushButton_stopCalculs.hide()
180 # on force extract_image afin de mettre à jour le curseur de la vidéo
181 self.extract_image(self.horizontalSlider.value())
182
183 self.affiche_point_attendu(self.suivis[0])
184 self.lance_capture = True
185 # les widgets de contrôle de l'image sont actifs ici
186 self.imgControlImage(True)
187
188 # désactive des boutons et des cases à cocher
189 for obj in self.pushButton_origine, self.checkBox_abscisses, \
190 self.checkBox_ordonnees, self.checkBox_auto, \
191 self.Bouton_lance_capture, self.pushButton_rot_droite, \
192 self.pushButton_rot_gauche :
193
194 obj.setEnabled(False)
195
196 # si aucune échelle n'a été définie, on place l'étalon à 1 px pour 1 m.
197 if self.echelle_image.mParPx() == 1:
198 self.echelle_image.longueur_reelle_etalon = 1
199 self.echelle_image.p1 = vecteur(0, 0)
200 self.echelle_image.p2 = vecteur(0, 1)
201
202 # active le bouton de réinitialisation
203 self.pushButton_reinit.setEnabled(True)
204 self.extract_image(self.index)
205 if etat =="E":
206 self.label_zoom.emit(self.tr("Pointage ({obj}) ; x, y =").format(obj = self.objet_courant))
207 self.imgControlImage(False)
208 return
209
210 def restaureEtat(self):
211 """
212 Restauration de l'état A ou D après (re)définition de l'échelle
213 """
214 self.app.change_etat.emit(self.etat_ancienetat_ancien)
215 return
216
Une classe qui permet de définir les états pour le pointageWidget debut, A, AB, B,...
def changeEtat(self, etat)
Mise en place d'un état de l'interface utilisateur, voir la documentation dans le fichier etat_pymeca...
def restaureEtat(self)
Restauration de l'état A ou D après (re)définition de l'échelle.
Une classe qui permet de définir les états pour le pointageWidget debut, A, AB, B,...
Definition: etats.py:30
une classe pour des vecteurs 2D ; les coordonnées sont flottantes, et on peut accéder à celles-ci par...
Definition: vecteur.py:44