Raspberry, faire un stream html de sa picaméra et opencv en python

Désireux de faire un stream de votre Picaméra que vous pouvez voir sur une page internet, voici un tuto qui vous permettra de réaliser cette prouesse et le tout simplement en python.Alors oui, vous avez certainement vu des articles pour l’utilisation de la Picaméra en python, vous avez également vu des tutoriels pour utiliser Opencv avec Python et vous êtes sûrement tombés sur des articles pour utiliser la Picaméra et Opencv en python mais ce que je vous propose est encore mieux.

Enfin, je ne sais pas, j’ai beaucoup recherché sur internet un moyen de faire un stream vers une page internet de ma Picaméra, sans jamais y arriver, pourtant de nombreux de sites proposent de faire un stream de sa Picamera sur une page web (comme celui-ci : lien) mais cela ne va pas vous permettre d’utiliser les fonctionnalités d’Opencv, d’autres sites vous donneront la possibilité d’utiliser votre webcam avec OpenCv. Ce que je vous propose ici est un exemple qui vous permettra d’utiliser OpenCv, une Picamera et python.

Matériel requis

Pour ce tuto, j’ai utilisé un Raspberry Pi 3 B (disponible ici) ainsi qu’une Picamera V2 (ici), pour l’installation et le test, vous pouvez lire cette page.

Du coté software, rien de transcendant, n’hésitez pas à jeter un œil sur cet article , pour l’installation d’OpenCv en Python et cet article pour la PiCamera, plus un paquet qui permettra à PiCamera de transformer les images pour que OpenCv les traitent ainsi que le paquet numpy qui est utile pour les calculs et enfin Flask qui permettra le streraming.

Pour résumer, faites un petit sudo apt-get update && sudo apt-get upgrade -y, puis :

sudo apt-get install python-picamera python3-picamera python-opencv python3-opencv python3-numpy python-numpy
pip3 install "picamera[array]" Flask
pip install "picamera[array]" Flask

Cela sera complet pour python 2.7 et python 3.

Le script

Alors, placez vous dans votre dossier de travail, créez un dossier templates, y créer un fichier index.html contenant :

<html>
  <header>
    <title>Démonstration du stream picamera opencv</title>
  </header>
  <body>
    <h1>Démonstration du stream picamera opencv</h1>
    <img src="/video_feed" />
  </body>
</html>

Maintenant, notre script que l’on va appeler app.py et qui va contenir :

#!/usr/bin/python3

from flask import Flask, render_template, Response

import numpy as np

from picamera.array import PiRGBArray
from picamera import PiCamera
import time
import cv2

class Camera():
  def __init__(self):
    print("Initialisation de de la camera")
    self.camera = PiCamera()
    self.camera.resolution = (640,480)
    self.camera.rotation = 180
    self.camera.framerate = 15
    self.rawCapture = PiRGBArray(self.camera, size=(640, 480))
    time.sleep(1)
    print("Caméra initialisée")

  def get_frame(self):
    heure = time.strftime('%H:%M:%S', time.localtime())
    for frame in self.camera.capture_continuous(self.rawCapture, format='bgr', use_video_port=True):
      image = frame.array
      cv2.putText(image, heure, (10,400), cv2.FONT_HERSHEY_SIMPLEX, 1, (255,0,0), 2)
#     cv2.imshow('frame', image)
#     key = cv2.waitKey(1) & 0xFF
      self.rawCapture.truncate(0)
#			if key == ord('q') :
#				break
      frame = cv2.imencode('.jpeg', image)[1].tostring()
      return frame

app = Flask(__name__)
@app.route("/")
def index():
  return render_template('index.html')

def gen(camera):
  while True:
    frame = camera.get_frame()
    yield (b'--frame\r\n'
      b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n')

@app.route("/video_feed")
def video_feed():
  return Response(gen(Camera()), mimetype="multipart/x-mixed-replace; boundary=frame")

if __name__ == '__main__':
  app.run(host='0.0.0.0', threaded=True, debug=True)

Explications

Si vous avez lancé le script (celui-ci est en python 3), vous avez pu voir :

Python, stream de la picamera avec opencv
Python, stream de la picamera avec opencv

Maintenant, intéressons-nous au script, dans la première partie, nous retrouvons notre importation des librairies.

Ensuite, nous trouvons notre classe Camera avec le constructeur qui permet de l’initialiser plus quelques petits réglages et la méthode get_frame() qui va retourner une image qui pourra être streamée.

Ce qui faut retenir pour le constructeur est l’appel de PiRGBArray qui va permettre de transformer l’image de la PiCamera pour qu’OpenCv puisse la traiter.

OpenCv voit une image comme un tableau multidimensionnel.

Dans la méthode get_frame(), nous créons une bouche de la laquelle nous sortons à la première itération, on récupère une image sur laquelle on insère du texte (ici l’heure, cela vous permet de montrer qu’on dispose donc des outils d’OpenCv), puis en encode l’image en jpeg et en texte. Enfin elle est retournée.

Dans la seconde partie, nous créons notre instance qui permettra de streamer, elle est composée d’une page d’index et du lien video_feed qui va correspondre au lien vers notre stream. La fonction gen(camera) va permettre de générer et notre image.

Enfin, nous avons le lancement de notre application de stream.

Je ne vais pas plus rentrer dans les détails car cela ne nous intéresse pas plus que ça.

Vous aurez sûrement remarqué que lorsque vous fermez votre navigateur, vous êtes obligés de relancer le script, je corrigerai cela dans un second temps.

Conclusion

Les possibilités d’OpenCv sont énormes (reconnaissance, tracking …), couplées avec un Raspberry et une Picamera, vous allez avoir des solutions qui seront peu gourmandes en énergies avec une bonne qualité, dans notre exemple, nous passons par un navigateur, nous pouvons certainement ajouter des boutons à notre vidéo et obtenir un retour vidéo d’un objet télécommandé.

Laisser un commentaire

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