Lire au moyen d'une caméra, la valeur de la jauge ronde (avec aiguille)

Bonjour,

Le projet :
Lire au moyen d’une caméra, la valeur de la jauge ronde (avec aiguille) du volume de mazout dans une citerne, interpréter le résultat avec un script Python et transmettre les données en mqtt à HA

1ère étape
Traiter l’image de la jauge prise par une caméra (IP infrarouge - ancien modèle) au moyen d’un script Python s’exécutant sur un Raspberry Pi 3b.
Pour réaliser les tests, la photo est prise au moyen d’une tablette et traitée par un logiciel de retouches d’images. Après traitements, on obtient une image de 640px sur 640px avec l’image de la jauge ronde centrée (coordonnée du centre = (320,320)). Dans une étape suivante, il faudra automatiser cette tâche au moyen d’un script Python.
Les images qui vont servir pour le test du script Python de lecture de la jauge :








L’image jauge-0 sert de support (l’aiguille a été effacée)
L’image jauge-1 est la réalité actuelle (cuve presque vide)
Les images suivantes sont modifiées en plaçant une aiguille fictive (trait noir)
Le script Python (« lecture_jauge_test_3.py ») utilisé qui tourne sur un pc (windows 11 - Python 3.11.1 - Thonny) pour les tests

import numpy as np
import cv2
import math

image = cv2.imread("jauge-2.jpg")
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blur = cv2.GaussianBlur(gray, (5, 5), 0)
edges = cv2.Canny(blur, 150, 150)
lines = cv2.HoughLinesP(edges, 1, np.pi/180, threshold=55, minLineLength=100, maxLineGap=10)
if lines is not None:
    for line in lines:
        x1, y1, x2, y2 = line[0]
    
    # centre de la jauge (image carrée de 640 px sur 640 px)
    x=320
    y=320
   
    #cv2.rectangle(output, (x - 2, y - 2), (x + 2, y + 2), (0, 128, 255), -1)
    cv2.line(output, (320, 0), (320,640), (255, 255, 255), 2)# axe des y déporté en blanc
    cv2.line(output, (0,320), (640,320), (255, 255, 255), 2) # axe des x déporté en blanc
    cv2.line(output, (x, y), (x1, y1), (0, 0, 0), 5) # suivi de la flèche de la jauge en noir demi droite d1
    cv2.line(output, (x, y), (210,500),(255,255,100),5) # minimun jauge en indigo demi droite d2
    cv2.line(output, (x, y), (550,300),(255,200,200),5) # maximun jauge en violet demi droite d3
    print("x1 = ",x1," et y1 = ",y1)
    #calcul des coéfficients angulaires a1, a2 et a3 des 3 droites d1, d2 et d3
    #chacune des 3 droites passent par (320, -320) centre de la jauge en coordonnées linéaires
    # formule : a = (y2 - y1)/(x2 - x1)
    a3 = (-300 - (-320))/(550 - 320)
    print ("a3 = ",a3)
    ata3 = round(math.degrees(math.atan(a3)),2)
    print ("angle de la d3 (violet) maximum jauge - ata3 = ",ata3,"° soit 100% -> soit 2500 litre")
    
    a2 = (-500 - (-320))/(210 - 320)
    print ("a2 = ",a2)
    ata2 = round(math.degrees(math.atan(a2)) + 178,2)
    print ("angle de la d2 (indigo) minimum jauge - ata2 = ",ata2,"° soit 0% -> soit 0 litre")
    
    dm = 180 # à ajouter si (x1,y1) est à gauche de l'axe des x déporté
    if (x1 >= 320):
        dm = 0 # vaut 0 car (x1,y1) est à droite
    a1 = (-y1 - (-320))/(x1 - 320)
    print ("a1 = ",a1)
    ata1 = round(math.degrees(math.atan(a1)) + dm,2)
    print ("angle de la d1 (noir) flèche de la jauge - ata1 = ",ata1,"°")
    if ((ata1 - ata3) <= 0):
        print ("Citerne remplie à 100% soit 2500 litre")
    if (ata1 >= ata2):
        print ("Citerne vide à 0% soit 0 litre")
    if ((ata1 > ata3) and (ata1 < ata2)):
        print ("Citerne en partie remplie")
        ata = ata2 - ata3
        print ("angle de remplissage = ",ata,"° soit 100% de remplissage")
        ataconsom = ata1 - ata3
        ataconsompc = round(100-(ataconsom / ata*100),0)
        print ("% restant dans la citerne = ",ataconsompc,"% -> soit ",round(2500*ataconsompc/100,0)," litre")
        
    
    # show the output image
    cv2.imshow("output", np.hstack([image, output]))
    cv2.waitKey(0)

Pour les tests (avec Thonny), créer un dossier dans lequel se trouvera le script Python et les 7 images.
Changer le nom de l’image à traiter dans le script afin de tester les différentes positions de l’aiguille de la jauge.
Attention, il s’agit ici de TESTER …
Actuellement, cela semble fonctionner correctement (+ou- 1,6 % d’erreur sur l’estimation du volume ?)

2ème étape
Fixer la caméra en face de la jauge pour saisir une photo (dans l’obscurité de la cave donc en ir)
avec un interval de temps défini (toutes les 8h par exemple)
Problème à solutionner : comme la jauge est munie d’une vitre de protection, il y a un reflet très génant lors de la prise de la photo (en ir ou en lumière blanche). Impossible dans ce cas d’interpréter convenablement l’image obtenue. La caméra Foscam IP (ancien modèle) ne convient pas.
à suivre …

1 « J'aime »