Les fêtes de fin d’année approchant, j’ai eu l’idée de concevoir un photomaton afin de permettre aux personnes de pouvoir se prendre en photo librement , sans forcément être planté devant leurs téléphones. De plus ce système permettera de conserver un souvenir de votre soirée, où toutes les photos sont stockées au même endroit, permettant de les diffuser plus simplement.

Comme le nom de l’article le spécifie, ce projet sera découpé en deux parties. Nous allons voir aujourd’hui quelles sont les fonctionnalités que nous attendons de notre photomaton, ainsi que l’implémentation logicielle. Dans la seconde partie nous verrons l’application physique avec l’utilisation du Raspberry et du module caméra, d’un écran pour afficher la photo prise, ainsi qu’un bouton pour déclencher la prise de vues.

Pour le moment, attaquons-nous à la partie logicielle!

Étape 1: Définition des fonctionnalités du photomaton

Avant de commencer à coder, il est nécessaire de définir les fonctionnalités que nous souhaitons pour notre photomaton !

Les fonctions que nous souhaitons sont:

  • Prendre des photos (logique !)
  • Afficher en temps réel ce que la caméra retourne, en plein écran
  • Avoir un retardateur de 3 secondes (et l’afficher)
  • Allumer l’écran en blanc pour simuler un flash
  • Afficher pendant un laps de temps déterminé la photo qui vient d’être prise
  • Enregistrer les photos dans un dossier

Cette liste nous permet de nous orienter sur la conception de notre programme.

Étape 2: Conception du programme

Nous pouvons donc créer notre programme photomaton.py mais avant ça, je vous invite à créer un répertoire « Image » où nous enregistrons nos images:

mkdir Images

import des bibliothèques

import cv2
import numpy as np
import time

Nous aurons donc besoin de la bibliothèque OpenCv (ligne1) pour la capture, l’affichage et l’enregistrement des images. La bibliothèque Numpy (ligne 2) sera également utilisée pour la création de notre « Flash ». Nous finissons par importer la bibliothèque time (ligne 3) qui n’a permettra dans un premier temps à créer notre retardateur et dans un second temps à créer notre nom d’image.

Initialisation de notre système:

cap=cv2.VideoCapture(0)
pressed=False
cv2.namedWindow('display', cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty('display', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_NORMAL)
ret,image=cap.read()
taille=image.shape
white=np.ones_like(image)
white=white*255

Premièrement, nous déclarons notre objet videoCapture, ligne 5, en prenant comme entrée la source 0, correspondant à la webcam de l’ordinateur (ou le module PiCamera sur Raspberry).

Nous définissons ensuite ligne 6 une variable pressed  qui nous permettra de connaître et de conserver le temps nécessaire l’état de notre bouton. Nous initialisons cette variable à False, signifiant que l’on n’a pas appuyé sur le bouton. Dès que nous appuyons sur le bouton (la barre espace pour l’instant), l’état de pressed passera à True.

Les lignes 7 et 8, nous permettent de définir notre fenêtre d’affichage, afin de permettre l’image en plein écran.

Attention: un bug dans l’affichage de la fenêtre, fait que des bandes blanches apparaissent sur les côtés de l’écran, rien de grave à part un côté inesthétique.

Nous récupérons une première image à la ligne 9, afin de pouvoir en récupérer la taille (ligne 10), ainsi que de pouvoir créer une image blanche (ligne 11 et 12), permettant de jouer le rôle de flash.

Affichage de la caméra

while (True ):
	ret,image=cap.read()	
	if pressed==False:
		cv2.imshow('display',image)
		k = cv2.waitKey(33)
		if k==27:
			cap.release()
			break
		elif k==32:
			pressed=True
			t=time.time()

Nous allons attaquer la première partie de notre problème, à savoir afficher le retour caméra en attendant que le bouton (une touche) soit pressé .

Pour ce faire, nous commençons par faire une boucle infinie (l. 13) permettant d’afficher une image tant que la touche « échap » n’est pas pressée ( ligne 18-20). À chaque nouvelle itération, nous lisons une nouvelle image (l. 14). Dans le cas où le bouton/la touche n’est pas pressée (l. 15), nous affichons (l.16) les images au fur et à mesure du temps. La ligne 17 nous permet de récupérer la valeur d’une touche si elle est pressée. Lorsque la barre espace est pressée (k==32 l. 21), alors on définit la variable pressed  à True et on démarre un timer.

Note: si vous voulez utiliser d’autres touches, je vous invite à utiliser la script de ce post, permettant d’afficher le chiffre correspondant à chaque touche.

Création du retardateur

	if pressed==True:
		diff=int(time.time()-t)
		
		if diff==0:
			cv2.putText(image,'3',(int(taille[1]/2), int(taille[0]/2)),cv2.FONT_HERSHEY_SIMPLEX, 5, (0, 255, 0), 3)
		elif diff==1:
			cv2.putText(image,'2',(int(taille[1]/2), int(taille[0]/2)),cv2.FONT_HERSHEY_SIMPLEX, 5, (0, 255, 0), 3)
		elif diff==2:
			cv2.putText(image,'1',(int(taille[1]/2), int(taille[0]/2)), cv2.FONT_HERSHEY_SIMPLEX, 5, (0, 255, 0), 3)
		
		elif diff==3:
			cv2.imshow('display',white)
			cv2.waitKey(100)
			_,img2=cap.read()
			d=time.localtime(time.time())
			name= 'Images/img_'+ str(d.tm_year)+ '_' + str(d.tm_mon) + '_' + str(d.tm_mday) + '-' + str(d.tm_hour) + '_' + str(d.tm_min) + '_' + str(d.tm_sec) + '.jpg'

Nous avons donc lancé un timer dès que la touche à été pressée. Nous calculons ligne 26 la différence de temps entre le moment actuel (time.time()) et le moment où la touche a été pressée (t). En d’autres termes, le nombre de secondes écoulées depuis que la touche a été pressée. Ainsi si le temps est inférieur à 1 seconde (diff==0) (l. 28), on affiche le numéro 3 au centre de l’image en vert (l. 29). On fait de même à 1 seconde et à  2 secondes.

Lorsque  le timer atteint 3 secondes (l. 35), on affiche notre image « flash » (l. 36-37) et nous capturons la photographie (l. 38).

Il nous reste à trouver un nom pour nos images. En effet, si nous laissons le même nom, toutes les images de la soirée seront écrasées par la dernière en date. Pour résoudre ce problème, nous allons utiliser notre information de temps à la ligne 39. la fonction time.localtime permet de convertir le temps en secondes (time.time()) en une structure de temps local, dont nous pouvons extraire l’année (d.tm_year), le mois (d.tm_mon) et ainsi de suite .

Nous créons donc un nom pour notre image à la ligne 40, composé du nom du répertoire où nous enregistrons les images (Images/), puis du nom de l’image: ‘img’ suivi du moment (année_mois_jour_heure_minute_seconde.jpg). Ainsi chaque nom d’image sera bien différent.

Enregistrement et affichage de l’image

			cv2.imwrite(name,img2)
			cv2.imshow('display',img2)
			cv2.waitKey(1000)
			pressed=False

		cv2.imshow('display',image)
		k = cv2.waitKey(1)

Pour finir, nous enregistrons la photographie à la ligne 41 et nous l’affichons pendant un délai de 1000 ms (l. 42-43), enfin nous repassons la variable pressed à False.

Enfin, dans le cas où notre timer n’est pas égale à 3, nous affichons l’image (l. 46-47), que nous avons modifié ligne 29, 31 ou 33.

Bilan

Nous avons donc bien réussi à programmer un photomaton qui prend en compte toutes les fonctionnalités que nous souhaitions. La prochaine étape consistera en l’installation physique du procédé sur un Raspberry Pi, avec notamment l’utilisation d’un bouton à la place de la barre espace pour plus de simplicité. De plus nous verrons également comment démarrer notre programme dès l’allumage du Raspberry.


10 commentaires

Rico · 20 janvier 2019 à 12 h 16 min

Bonjour,
Je suis intéressé par votre photomaton, je me posais la question de quelle image est a déployer sur un Rpi 1 ?

    Florent · 20 janvier 2019 à 18 h 49 min

    Bonjour,
    En effet, j’ai oublié de mentionner cette étape. Vous pouvez utiliser l’image: ‘Raspbian Stretch with desktop’ disponible ici.
    Il vous faudra également installer OpenCV. J’ai réalisé plusieurs tutoriels disponible sur cette page.

      Gautier · 21 janvier 2019 à 20 h 34 min

      Nickel, merci du retour

Stéphane · 3 mars 2019 à 21 h 34 min

Bonsoir… Merci pour ce tutoriel vrai que je ne l’ai pas encore testé mais c’est très bien détaillé je vous en remerci…
Ma préoccupation est de savoir comment faire pour ajouter une image de fond tant qu’on a pas appuyé sur le bouton poussoir.. et aussi comment imprimer l’image que je viens de prendre ! Notons que j’aimerais ajouter la possibilité où l’utilisateur pourra décider reprendre la photo où alors décidé de l’imprimée … Mais si c’est compliqué on peut faire de l’impression automatique…
Aussi comment dimensionner la taille de la photo où alors prendre une série de photos et les regrouper en une seule ?
Merci bien et bonne soirée à toute la communauté

    Florent · 18 mars 2019 à 17 h 12 min

    Bonjour Stéphane,

    Voici quelques éléments de réponses à vos questions :
    Pour avoir une image de fond tant que le bouton n’est pas pressé, il suffit de modifier l’image affichée à la ligne 16.
    Pour l’impression, je ne m’y suis pas intéressé, mais une des pistes que j’ai vue est l’utilisation de CUPS et de la librairie pycups pour faire la liaison avec Python.
    Concernant la validation où non par l’utilisateur de la photo, vous pourriez, par exemple, installer un deuxième bouton et ainsi imprimer la photo lorsque l’utilisateur le souhaite. Sinon la photo sera juste sauvegardée et nous reviendrons au cas de départ.
    Enfin, vous pouvez définir la taille d’une image avec la fonction cv2.resize. Il vous est possible de redimensionner plusieurs images afin d’en former une seule.

    J’espère que cela vous aidera. N’hésitez pas à revenir vers moi si vous avez un quelconque problème.

DJOUKA · 29 mai 2019 à 13 h 44 min

Bonjour,

Je viens de me laisser dans la réalisation d’un photomaton et apprécies vraiment beaucoup votre tutoriel qui est très bien détaillé

    DJOUKA · 29 mai 2019 à 13 h 45 min

    lancer*

Julien GOGUEL · 25 juin 2019 à 8 h 12 min

Bonjour
tout d’abord merci beaucoup du temps que vous avez passé afin de créer ce TUTO, il est juste incroyable…et pour un novice comme moi c’est une mine d’or…J’ai une petite question et je ne sais vraiment pas si cela est possible, mais à la place d’imprimer je souhaiterai laisser la possibilité à la personne d’envoyer la photo sur sa boite mail. Pensez vous que cela est jouable? et si oui comment pourrais je m’y prendre?
Merci encore

Anthony Hurez · 13 août 2019 à 17 h 15 min

Bonjour,
Merci pour votre tuto très intéressant, j’avoue que je regarde depuis quelques temps les tuto de ce genre, j’ai promis à mon épouse de lui fabriquer un photomaton, simple, et j’ai découvert les rapsberry lol. et il possible d’utiliser un appareil photo numérique type reflex, à la place de la camera?
Merci

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.