# -*- coding: utf-8 -*- # ----------------------------------------------------------------------------- # Importation des libraries # ----------------------------------------------------------------------------- # Librairie qui permet de manipuler les répertoires, les fichiers import os # Librairie qui permet de manipuler les dates from datetime import datetime # Utilisation de la librairie OpenCV import cv2 # Utilisation de la librairie Numpy import numpy as np # ----------------------------------------------------------------------------- # Déclaration des constantes (configuration modifiable) # ----------------------------------------------------------------------------- # Les différents modes : # Veille ---> Live ---> Décompte ---> Photo ---> Veille # - Veille : un écran de veille est affiché, il faut appuyer sur une touche/bouton pour en sortir. # - Live : affichage de la vidéo en direct # - Décompte : une photo va être prise au bout d'un certain temps # - Photo : la photo est prise et est affichée pendant un certain temps MODE_VEILLE = 0 MODE_LIVE = 1 MODE_DECOMPTE = 2 MODE_PHOTO = 3 # Nom de la fenêtre d'affichage NOM_FENETRE = "Photomaton" # Durée d'attente dans le mode décompte, avant prise de photo, en millisecondes DUREE_MODE_DECOMPTE = 5000 # Durée d'attente dans le mode photo : affichage de la photo, en millisecondes DUREE_MODE_PHOTO = 5000 # Temps d'attente entre chaque acquisition d'images pour la vidéo en direct, en millisecondes DUREE_ATTENTE_TOUCHE = 40 # Temps de retour en mode veille, en millisecondes DUREE_MODE_LIVE = 5000 # Texte sur l'écran de veille SLEEP_SCREEN_TEXT = "Appuyer ..." # Chemin de base (répertoire) sui contiendra les sous-répertoires avec les dates de prises de photos BASE_PATH = "Images" # Valeur du compteur en mode décompte VALEUR_COMPTEUR_DECOMPTE = 5 # Résolution de l'écran d'affichage ECRAN_RESOLUTION_X = 1024 ECRAN_RESOLUTION_Y = 780 # Police de texte du mode veille POLICE_TEXTE_VEILLE = cv2.FONT_HERSHEY_DUPLEX # Echelle du texte du mode veille ECHELLE_TEXTE_VEILLE = 0.5 # Couleur du texte du mode veille COULEUR_TEXT_VEILLE = (255, 0, 255) # Vitesse de mouvement du texte en mode veille VITESSE_TEXTE_VEILLE = 5 # Epaisseur du texte en mode veille EPAISSEUR_TEXTE_VEILLE = 1 # Police de texte du mode décompte POLICE_TEXTE_DECOMPTE = cv2.FONT_HERSHEY_DUPLEX # Echelle du texte du mode décompte ECHELLE_TEXTE_DECOMPTE = 5.0 # Couleur du texte de décompte COULEUR_TEXT_DECOMPTE = (255, 0, 255) # Epaisseur du texte en mode décompte EPAISSEUR_TEXTE_DECOMPTE = 10 # ----------------------------------------------------------------------------- # Déclaration (et initialisation) des variables # ----------------------------------------------------------------------------- # Compteur de temps en millisecondes où l'on est en mode VEILLE compteur_mode_veille = 0 # Compteur de temps en millisecondes où l'on est en mode LIVE compteur_mode_live = 0 # Compteur de temps en millisecondes où l'on est en mode DECOMPTE compteur_mode_decompte = 0 # Compteur de temps en millisecondes où l'on est en mode PHOTO compteur_mode_photo = 0 # Valeur du compteur de décompte à afficher valeur_compteur_decompte = VALEUR_COMPTEUR_DECOMPTE # Coordonnées X et Y du texte en mode veille texte_veille_x = 0 texte_veille_y = 0 # Incrémentation / décrémentation X et Y pour la position du texte en mode veille inc_veille_x = 0 inc_veille_y = 0 # Mode de fonctionnement : cf. constantes ci-dessus mode = MODE_VEILLE # True si la photo a été enregistrée photo_enregistree = False # ----------------------------------------------------------------------------- # Déclaration des fonctions # ----------------------------------------------------------------------------- def affiche_error(): """ Fonction qui permet d'afficher un écran d'erreur. """ # Construction de l'image à afficher (noir) image_error = np.zeros( (ECRAN_RESOLUTION_Y, ECRAN_RESOLUTION_X, 3), np.uint8) # Ajout d'une bordure image_bord = cv2.copyMakeBorder( src=image_error, top=5, bottom=5, left=5, right=5, borderType=cv2.BORDER_CONSTANT, value=[0, 0, 255]) # Affichage de l'image cv2.imshow(NOM_FENETRE, image_bord) def affiche_veille(): """ Fonction qui affiche un écran de veille. """ # Lecture du compteur en mode veille global compteur_mode_veille # Coordonnées X et Y du texte global texte_veille_x global texte_veille_y # Incrementation / décrémentation global inc_veille_x global inc_veille_y # Construction de l'image à afficher (noir) image_veille = np.zeros( (ECRAN_RESOLUTION_Y, ECRAN_RESOLUTION_X, 3), np.uint8) # Calcul de la position du texte # Le texte a une largeur et une hauteur taille_texte = cv2.getTextSize( text=SLEEP_SCREEN_TEXT, fontFace=POLICE_TEXTE_VEILLE, fontScale=ECHELLE_TEXTE_VEILLE, thickness=EPAISSEUR_TEXTE_VEILLE) largeur_texte = taille_texte[0][0] hauteur_texte = taille_texte[0][1] # On place du texte cv2.putText( img=image_veille, # Image text=SLEEP_SCREEN_TEXT, # Texte org=(texte_veille_x, texte_veille_y), # Origine fontFace=POLICE_TEXTE_VEILLE, # Police de caractères fontScale=ECHELLE_TEXTE_VEILLE, # Echelle de police color=COULEUR_TEXT_VEILLE, # Couleur thickness=EPAISSEUR_TEXTE_VEILLE) cv2.imshow(NOM_FENETRE, image_veille) # On prend le compteur de temps pour faire bouger les choses texte_veille_x += inc_veille_x texte_veille_y += inc_veille_y # Modification des incréments si on arrive aux bords de l'image # En largeur if (texte_veille_x + largeur_texte) > ECRAN_RESOLUTION_X: inc_veille_x = -VITESSE_TEXTE_VEILLE if texte_veille_x <= 0: inc_veille_x = VITESSE_TEXTE_VEILLE # En hauteur if (texte_veille_y + hauteur_texte) > ECRAN_RESOLUTION_Y: inc_veille_y = -VITESSE_TEXTE_VEILLE if texte_veille_y <= 0: inc_veille_y = VITESSE_TEXTE_VEILLE def affiche_decompte(image): """ Fonction qui permet d'afficher un écran de décompte. Paramètres : - image : image sur laquelle on ajoute le texte. Retourne l'image avec le texte. """ # Valeur du compteur de décompte global valeur_compteur_decompte # Valeur du compteur à afficher texte = f"{valeur_compteur_decompte}" # Si décompte à 0 -> affiche un texte if valeur_compteur_decompte == 0: texte = "Souriez !!!" # Le texte a une largeur et une hauteur taille_texte = cv2.getTextSize( text=texte, fontFace=POLICE_TEXTE_DECOMPTE, fontScale=ECHELLE_TEXTE_DECOMPTE, thickness=EPAISSEUR_TEXTE_DECOMPTE) largeur_texte = taille_texte[0][0] hauteur_texte = taille_texte[0][1] # On centre le texte en largeur et hauteur pos_texte_x = int(ECRAN_RESOLUTION_X / 2 - largeur_texte / 2) pos_texte_y = int(ECRAN_RESOLUTION_Y / 2 - hauteur_texte / 2) # On place du texte cv2.putText( img=image, # Image text=texte, # Texte org=(pos_texte_x, pos_texte_y), # Origine fontFace=POLICE_TEXTE_DECOMPTE, # Police de caractères fontScale=ECHELLE_TEXTE_DECOMPTE, # Echelle de police color=COULEUR_TEXT_DECOMPTE, # Couleur thickness=EPAISSEUR_TEXTE_DECOMPTE) # On retourne l'image avec le compteur return image # ----------------------------------------------------------------------------- # ETAPE 1 - Créeation des répertoires # ----------------------------------------------------------------------------- # Répertoire qui va contenir les images enregistrées # On utilise la fonction "strftime" de la librairie "datetime" pour # construire une chaine de caractères contenant la date du jour. # C'est le répertoire de base + le répertoire sous forme de date. IMAGES_DIR = BASE_PATH + "/" + datetime.strftime( datetime.now(), # Date du jour "%Y-%m-%d") # Format de la chaine de caractères # Teste si le répertoire existe if not os.path.exists(IMAGES_DIR): # Le répertoire n'existe pas, on le crée os.makedirs(IMAGES_DIR) # ----------------------------------------------------------------------------- # ETAPE 2 - Ouverture de la caméra, création de la fenêtre # ----------------------------------------------------------------------------- # Création d'une fenêtre pour affichage cv2.namedWindow(NOM_FENETRE) # Ouverture de la camera camera = cv2.VideoCapture(0) # Récupération des capacités de la caméra : résolution # ----------------------------------------------------------------------------- # ETAPE 3 - Mise en veille de l'écran # ----------------------------------------------------------------------------- # ----------------------------------------------------------------------------- # ETAPE 4 - Affichage de la video "en direct" sur la fenêtre # ----------------------------------------------------------------------------- while True: # Selon le mode if mode == MODE_VEILLE: # Si c'est le mode veille, on affiche l'écran de veille affiche_veille() # On augmente le compteur de temps en mode veille compteur_mode_veille += DUREE_ATTENTE_TOUCHE elif mode == MODE_LIVE: # Si c'est le mode live, on prend une photo ret, photo = camera.read() # Redimensionne la photo sur l'écran resize_photo = cv2.resize(photo, (ECRAN_RESOLUTION_X, ECRAN_RESOLUTION_Y)) # Test de l'erreur if ret: # On montre l'image sur la fenêtre cv2.imshow(NOM_FENETRE, resize_photo) else: # Test de l'erreur affiche_error() # Si on ne fait rien, on augmente le compteur de temps # pour déclencher le retour en mode veille compteur_mode_live += DUREE_ATTENTE_TOUCHE # Si le temps écoulé sans rien faire est dépassé if compteur_mode_live > DUREE_MODE_LIVE: # Reset de tous les compteurs compteur_mode_veille = 0 compteur_mode_live = 0 compteur_mode_decompte = 0 compteur_mode_photo = 0 # Retourne en mode veille mode = MODE_VEILLE elif mode == MODE_DECOMPTE: # Si on est en mode décompte, on prend la photo ret, photo = camera.read() # Test de l'erreur if ret: # Redimensionne la photo sur l'écran resize_photo = cv2.resize(photo, (ECRAN_RESOLUTION_X, ECRAN_RESOLUTION_Y)) # Demande l'affichage du compteur de décompte photo_decompte = affiche_decompte(resize_photo) # On montre l'image sur la fenêtre cv2.imshow(NOM_FENETRE, photo_decompte) # Si décompte à 0 -> affiche un texte if valeur_compteur_decompte == 0: cv2.waitKey(1000) # Augmente le temps en mode décompte compteur_mode_decompte += DUREE_ATTENTE_TOUCHE # Décrémente le décompte, toutes les secondes if compteur_mode_decompte % 1000 == 0: valeur_compteur_decompte -= 1 # Si le temps écoulé, on passe en mode photo if compteur_mode_decompte > DUREE_MODE_DECOMPTE: # Reset de tous les compteurs compteur_mode_veille = 0 compteur_mode_live = 0 compteur_mode_decompte = 0 compteur_mode_photo = 0 # Retourne en mode photo mode = MODE_PHOTO else: # Si erreur ... Affichage du message affiche_error() elif mode == MODE_PHOTO: # Si on est en mode décompte, on prend la photo ret, photo = camera.read() # Test de l'erreur if ret: # Si la photo n'est pas enregistrée if not photo_enregistree: # On retient la photo à enregistrer photo_fixe = photo # On construit une chaine de caractères contenant la date actuelle. # Cette chaine de caractères permettra de nommer le fichier image. date_str = datetime.strftime( datetime.now(), # La date courante "%Y-%m-%d_%H-%M-%S") # Le format du résultat, sous forme : année-mois-jour_heure-minutes-secondes # Nom de fichier à enregistrer photo_filename = IMAGES_DIR + "/" + date_str + ".jpg" # Enregistre la photo cv2.imwrite(photo_filename, photo_fixe) # Photo enregistrée photo_enregistree = True # Redimensionne la photo sur l'écran resize_photo = cv2.resize(photo_fixe, (ECRAN_RESOLUTION_X, ECRAN_RESOLUTION_Y)) # On montre l'image sur la fenêtre cv2.imshow(NOM_FENETRE, resize_photo) # Augmente le temps en mode décompte compteur_mode_photo += DUREE_ATTENTE_TOUCHE # Si le temps écoulé, on passe en mode live if compteur_mode_photo > DUREE_MODE_PHOTO: # Reset de tous les compteurs compteur_mode_veille = 0 compteur_mode_live = 0 compteur_mode_decompte = 0 compteur_mode_photo = 0 valeur_compteur_decompte = VALEUR_COMPTEUR_DECOMPTE # Photo n'est plus enregistrée photo_enregistree = False # Retourne en mode live mode = MODE_LIVE else: # Si erreur ... Affichage du message affiche_error() # Attente d'appui sur une touche (40ms), c.-à-d. 25 images par seconde key = cv2.waitKey(DUREE_ATTENTE_TOUCHE) # Si on appuie sur la touche "Esc" if key == 27: # On casse la boucle infinie : on sort du programme break # Si on appuie sur la touche "Barre d'espace" if key == 32: # Reset du compteur "idle" count_idle = 0 # Si on est en mode veille, on passe en mode live if mode == MODE_VEILLE: mode = MODE_LIVE # Si on est en mode live, on passe en mode décompte elif mode == MODE_LIVE: mode = MODE_DECOMPTE # Si on est en mode décompte, on passe en mode photo elif mode == MODE_DECOMPTE: mode = MODE_PHOTO # ----------------------------------------------------------------------------- # ETAPE 5 - Fermeture de la caméra, de la fenêtre # ----------------------------------------------------------------------------- # On éjecte la caméra camera.release() # On détruit toutes les fenêtres construites cv2.destroyAllWindows()