Indholdsfortegnelse:
- Trin 1: BoM - regning af materiale
- Trin 2: Installation af OpenCV 3 -pakken
- Trin 3: Testning af dit kamera
- Trin 4: Ansigtsregistrering
- Trin 5: Dataindsamling
- Trin 6: Træner
- Trin 7: Genkender
- Trin 8: Konklusion
Video: Ansigtsgenkendelse i realtid: et ende-til-ende-projekt: 8 trin (med billeder)
2024 Forfatter: John Day | [email protected]. Sidst ændret: 2024-01-30 08:29
På min sidste tutorial, der udforskede OpenCV, lærte vi AUTOMATIC VISION OBJECT TRACKING. Nu vil vi bruge vores PiCam til at genkende ansigter i realtid, som du kan se nedenfor:
Dette projekt blev udført med dette fantastiske "Open Source Computer Vision Library", OpenCV. I denne vejledning fokuserer vi på Raspberry Pi (altså Raspbian som OS) og Python, men jeg testede også koden på min Mac, og den fungerer også fint. OpenCV er designet til beregningseffektivitet og med et stærkt fokus på applikationer i realtid. Så det er perfekt til ansigtsgenkendelse i realtid ved hjælp af et kamera.
For at oprette et komplet projekt om ansigtsgenkendelse skal vi arbejde på 3 meget forskellige faser:
- Ansigtsregistrering og dataindsamling
- Træn genkenderen
- Ansigtsgenkendelse
Nedenstående blokdiagram genoptager disse faser:
Trin 1: BoM - regning af materiale
Hoveddele:
- Raspberry Pi V3 - 32,00 US $
- 5 megapixel 1080p sensor OV5647 mini kamera videomodul - 13,00 US $
Trin 2: Installation af OpenCV 3 -pakken
Jeg bruger en Raspberry Pi V3 opdateret til den sidste version af Raspbian (Stretch), så den bedste måde at få OpenCV installeret på er at følge den fremragende vejledning udviklet af Adrian Rosebrock: Raspbian Stretch: Installer OpenCV 3 + Python på din Raspberry Pi.
Jeg prøvede flere forskellige guider til at installere OpenCV på min Pi. Adrians tutorial er den bedste. Jeg råder dig til at gøre det samme ved at følge hans retningslinje trin for trin.
Når du er færdig med Adrians tutorial, skal du have et virtuelt OpenCV -miljø klar til at køre vores eksperimenter på din Pi.
Lad os gå til vores virtuelle miljø og bekræfte, at OpenCV 3 er korrekt installeret.
Adrian anbefaler, at du kører kommandoen "kilde", hver gang du åbner en ny terminal for at sikre, at dine systemvariabler er konfigureret korrekt.
kilde ~/.profil
Lad os derefter gå ind på vores virtuelle miljø:
arbejdet cv
Hvis du ser teksten (cv) forud for din prompt, befinder du dig i det virtuelle cv -miljø:
(cv) pi@hindbær: ~ $Adrian henleder opmærksomheden på, at det virtuelle cv Python -miljø er helt uafhængigt og afsondret fra standard Python -version inkluderet i download af Raspbian Stretch. Så alle Python-pakker i den globale site-packages-bibliotek vil ikke være tilgængelige for cv-virtuelle miljø. På samme måde vil alle Python-pakker, der er installeret i sted-pakker med cv, ikke være tilgængelige for den globale installation af Python
Indtast nu din Python -tolk:
python
og bekræft, at du kører versionen 3.5 (eller nyere)
Inde i tolken (">>>" vises), importer OpenCV -biblioteket:
import cv2
Hvis der ikke vises nogen fejlmeddelelser, er OpenCV korrekt installeret PÅ DIN PYTHON VIRTUAL MILJØ.
Du kan også kontrollere den installerede OpenCV -version:
cv2._ version_
3.3.0 skal vises (eller en overlegen version, der kan frigives i fremtiden). Ovenstående Terminal PrintScreen viser de foregående trin.
Trin 3: Testning af dit kamera
Når du har installeret OpenCV i din RPi, lad os teste for at bekræfte, at dit kamera fungerer korrekt.
Jeg går ud fra, at du allerede har en PiCam installeret på din Raspberry Pi.
Indtast nedenstående Python -kode på din IDE:
import numpy som np
import cv2 cap = cv2. VideoCapture (0) cap.set (3, 640) # set Width cap.set (4, 480) # set Height while (True): ret, frame = cap.read () frame = cv2. flip (ramme, -1) # Flip kamera lodret grå = cv2.cvtColor (frame, cv2. COLOR_BGR2GRAY) cv2.imshow ('frame', frame) cv2.imshow ('grå', grå) k = cv2.waitKey (30) & 0xff hvis k == 27: # tryk på 'ESC' for at afbryde break cap.release () cv2.destroyAllWindows ()
Ovenstående kode fanger den videostream, der genereres af din PiCam, og viser begge i BGR -farve og grå tilstand.
Bemærk, at jeg roterede mit kamera lodret på grund af den måde, det er samlet på. Hvis det ikke er din sag, skal du kommentere eller slette kommandolinjen "flip".
Du kan alternativt downloade koden fra min GitHub: simpleCamTest.py
For at udføre skal du indtaste kommandoen:
python simpleCamTest.py
For at afslutte programmet skal du trykke på tasten [ESC] på dit tastatur.
Klik med musen på videovinduet, før du trykker på [ESC]
Ovenstående billede viser resultatet.
Nogle producenter fandt problemer, når de forsøgte at åbne kameraet ("Bekræftelse mislykkedes" fejlmeddelelser). Det kan ske, hvis kameraet ikke var aktiveret under OpenCv -installationen, og kameraer blev derfor ikke installeret korrekt. For at rette, brug kommandoen:
sudo modprobe bcm2835-v4l2
Du kan også tilføje bcm2835-v4l2 til den sidste linje i filen /etc /modules, så driveren indlæses ved opstart.
Hvis du vil vide mere om OpenCV, kan du følge selvstudiet: loading -video-python-opencv-tutorial
Trin 4: Ansigtsregistrering
Den mest grundlæggende opgave ved ansigtsgenkendelse er naturligvis "Ansigtsregistrering". Før noget skal du "fange" et ansigt (fase 1) for at genkende det, sammenlignet med et nyt ansigt, der er fanget i fremtiden (fase 3).
Den mest almindelige måde at registrere et ansigt (eller andre objekter) på er ved hjælp af "Haar Cascade classifier"
Objektdetektion ved hjælp af Haar-funktionsbaserede kaskadeklassificatorer er en effektiv objektdetekteringsmetode foreslået af Paul Viola og Michael Jones i deres papir, "Rapid Object Detection using a Boosted Cascade of Simple Features" i 2001. Det er en machine learning-baseret tilgang, hvor en kaskadefunktion er trænet ud fra en masse positive og negative billeder. Det bruges derefter til at registrere objekter i andre billeder.
Her vil vi arbejde med ansigtsgenkendelse. I første omgang har algoritmen brug for en masse positive billeder (billeder af ansigter) og negative billeder (billeder uden ansigter) for at træne klassifikatoren. Derefter skal vi udtrække funktioner fra det. Den gode nyhed er, at OpenCV kommer med en træner såvel som en detektor. Hvis du vil træne din egen klassifikator for ethvert objekt som bil, fly osv., Kan du bruge OpenCV til at oprette en. Dens fulde detaljer er givet her: Cascade Classifier Training.
Hvis du ikke ønsker at oprette din egen klassifikator, indeholder OpenCV allerede mange foruddannede klassifikatorer til ansigt, øjne, smil osv. Disse XML-filer kan downloades fra haarcascades bibliotek.
Nok teori, lad os oprette en ansigtsdetektor med OpenCV!
Download filen: faceDetection.py fra min GitHub.
import numpy som np
import cv2 faceCascade = cv2. CascadeClassifier ('Cascades/haarcascade_frontalface_default.xml') cap = cv2. VideoCapture (0) cap.set (3, 640) # set Width cap.set (4, 480) # set Højde mens True: ret, img = cap.read () img = cv2.flip (img, -1) grå = cv2.cvtColor (img, cv2. COLOR_BGR2GRAY) ansigter = faceCascade.detectMultiScale (grå, scaleFactor = 1.2, minNeighbors = 5, minSize = (20, 20)) for (x, y, w, h) i ansigter: cv2.rektangel (img, (x, y), (x+w, y+h), (255, 0, 0), 2) roi_gray = grå [y: y+h, x: x+w] roi_color = img [y: y+h, x: x+w] cv2.imshow ('video', img) k = cv2.waitKey (30) & 0xff hvis k == 27: # tryk på 'ESC' for at afslutte break cap.release () cv2.destroyAllWindows ()
Tro det eller ej, ovenstående få linjer med kode er alt, hvad du har brug for for at registrere et ansigt ved hjælp af Python og OpenCV.
Når du sammenligner med den sidste kode, der blev brugt til at teste kameraet, vil du indse, at få dele blev tilføjet til det. Bemærk nedenstående linje:
faceCascade = cv2. CascadeClassifier ('Cascades/haarcascade_frontalface_default.xml')
Dette er den linje, der indlæser "klassifikatoren" (der skal være i et bibliotek med navnet "Cascades/", under dit projektmappe).
Derefter vil vi indstille vores kamera og inde i sløjfen indlæse vores inputvideo i gråtonetilstand (samme som vi så før).
Nu skal vi kalde vores klassificeringsfunktion og give den nogle meget vigtige parametre, som skalafaktor, antal naboer og minimumsstørrelse på det registrerede ansigt.
ansigter = faceCascade.detectMultiScale (grå, skalaFaktor = 1,2, minNaboer = 5, minStørrelse = (20, 20))
Hvor,
- grå er input -gråtonebilledet.
- scaleFactor er parameteren, der angiver, hvor meget billedstørrelsen reduceres ved hver billedskala. Det bruges til at skabe skala -pyramiden.
- minNeighbors er en parameter, der angiver, hvor mange naboer hvert kandidatrektangel skal have for at beholde det. Et højere tal giver lavere falske positiver.
- minSize er den mindste rektangelstørrelse, der skal betragtes som et ansigt.
Funktionen registrerer ansigter på billedet. Dernæst skal vi "markere" ansigterne i billedet ved hjælp af f.eks. Et blåt rektangel. Dette gøres med denne del af koden:
for (x, y, w, h) i ansigter:
cv2.rektangel (img, (x, y), (x+w, y+h), (255, 0, 0), 2) roi_gray = grå [y: y+h, x: x+w] roi_color = img [y: y+h, x: x+w]
Hvis der findes ansigter, returnerer det positionerne for detekterede ansigter som et rektangel med venstre hjørne op (x, y) og med "w" som bredde og "h" som højde ==> (x, y, w, h). Se venligst ovenstående billede.
Når vi får disse placeringer, kan vi oprette et "ROI" (tegnet rektangel) til ansigtet og præsentere resultatet med imshow () -funktionen.
Kør ovenstående python -script i dit python -miljø ved hjælp af Rpi Terminal:
python faceDetection.py
Resultatet:
Du kan også inkludere klassifikatorer til "øjensøgning" eller endda "smilregistrering". I disse tilfælde vil du inkludere klassificeringsfunktionen og rektangeltegning inde i ansigtsløkken, for det ville ikke være fornuftigt at registrere et øje eller et smil uden for et ansigt.
Bemærk, at på en Pi vil flere klassificatorer ved samme kode forsinke behandlingen, når denne detektionsmetode (HaarCascades) bruger en stor mængde beregningseffekt. På et skrivebord er det lettere at køre det.
På min GitHub finder du andre eksempler:
faceEyeDetection.py
faceSmileDetection.py
faceSmileEyeDetection.py
Og på billedet ovenfor kan du se resultatet.
Du kan også følge nedenstående vejledning for bedre at forstå ansigtsgenkendelse:
Haar Cascade Object Detection Ansigt og øje OpenCV Python -vejledning
Trin 5: Dataindsamling
Først og fremmest skal jeg takke Ramiz Raja for hans store arbejde med ansigtsgenkendelse på fotos:
ANSIGTSANKENDELSE VED AT BRUGE OPENCV OG PYTHON: EN BEGYNDERVEJLEDNING
og også Anirban Kar, der udviklede en meget omfattende tutorial ved hjælp af video:
ANSIGTSANKENDELSE - 3 dele
Jeg anbefaler virkelig, at du kigger på begge tutorials.
Når det er sagt, lad os starte den første fase af vores projekt. Hvad vi vil gøre her, starter fra sidste trin (Ansigtsregistrering), vi vil simpelthen oprette et datasæt, hvor vi for hvert id gemmer en gruppe billeder i gråt med den del, der blev brugt til ansigtsregistrering.
Opret først et bibliotek, hvor du udvikler dit projekt, for eksempel FacialRecognitionProject:
mkdir FacialRecognitionProject
I denne mappe, udover de 3 python -scripts, som vi vil oprette til vores projekt, skal vi have gemt Facial Classifier på den. Du kan downloade den fra min GitHub: haarcascade_frontalface_default.xml
Opret derefter en underkatalog, hvor vi vil gemme vores ansigtsprøver og navngive det "datasæt":
mkdir datasæt
Og download koden fra min GitHub: 01_face_dataset.py
import cv2
import os cam = cv2. VideoCapture (0) cam.set (3, 640) # set video width cam.set (4, 480) # set video height face_detector = cv2. CascadeClassifier ('haarcascade_frontalface_default.xml') # For hver person, indtast et numerisk ansigt -id face_id = input ('\ n indtast bruger -id slut tryk ==>') udskriv ("\ n [INFO] Initialiserer ansigtsoptagelse. Se på kameraet og vent …") # Initialiser individuelle samplingtællinger = 0 mens (True): ret, img = cam.read () img = cv2.flip (img, -1) # flip videobillede lodret gråt = cv2.cvtColor (img, cv2. COLOR_BGR2GRAY) ansigter = face_detector.detectMultiScale (grå, 1,3, 5) for (x, y, w, h) i ansigter: cv2.rektangel (img, (x, y), (x+w, y+h), (255, 0, 0), 2) count + = 1 # Gem det optagede billede i datasætmappen cv2.imwrite ("datasæt/bruger." + str (face_id) + '.' + str (count) + ".jpg", grå [y: y + h, x: x+w]) cv2.imshow ('image', img) k = cv2.waitKey (100) & 0xff # Tryk på 'ESC' for at afslutte video, hvis k == 27: break elif count> = 30: # Tag 30 ansigtsprøver og stop videopause # Gør ab det af oprydningstryk ("\ n [INFO] Afslutter program og oprydningsting") cam.release () cv2.destroyAllWindows ()
Koden ligner meget den kode, vi så til ansigtsgenkendelse. Det, vi tilføjede, var en "inputkommando" for at fange et bruger -id, der skulle være et helt tal (1, 2, 3 osv.)
face_id = input ('\ n indtast bruger -id slut tryk ==>')
Og for hver enkelt af de fangede rammer skulle vi gemme den som en fil i et "datasæt" bibliotek:
cv2.imwrite ("datasæt/bruger." + str (face_id) + '.' + str (count) + ".jpg", grå [y: y + h, x: x + w])
Bemærk, at for at gemme ovenstående fil skal du have importeret biblioteket "os". Hver fils navn følger strukturen:
User.face_id.count.jpg
For eksempel for en bruger med et face_id = 1 vil den fjerde prøvefil på datasæt/ bibliotek være sådan:
Bruger.1.4.jpg
som vist på ovenstående foto fra min Pi. På min kode optager jeg 30 prøver fra hvert id. Du kan ændre det på den sidste "elif". Antallet af prøver bruges til at bryde sløjfen, hvor ansigtsprøverne fanges.
Kør Python -scriptet, og tag et par id'er. Du skal køre scriptet hver gang, du vil samle en ny bruger (eller ændre fotos for et, der allerede findes).
Trin 6: Træner
I denne anden fase skal vi tage alle brugerdata fra vores datasæt og "træne" OpenCV Recognizer. Dette gøres direkte af en specifik OpenCV -funktion. Resultatet vil være en.yml -fil, der vil blive gemt i et "træner/" bibliotek.
Så lad os begynde at oprette en underkatalog, hvor vi vil gemme de uddannede data:
mkdir træner
Download det andet python -script fra min GitHub: 02_face_training.py
import cv2
import numpy som np fra PIL import Billedimport os # Sti til ansigtsbilleddatabasesti = 'datasæt' genkender = cv2.face. LBPHFaceRecognizer_create () detektor = cv2. CascadeClassifier ("haarcascade_frontalface_default.xml"); # funktion for at hente billederne og mærke data def getImagesAndLabels (sti): imagePaths = [os.path.join (sti, f) for f i os.listdir (sti)] faceSamples = ids = for imagePath i imagePaths: PIL_img = Image.open (imagePath).convert ('L') # konverter det til gråtoner img_numpy = np.array (PIL_img, 'uint8') id = int (os.path.split (imagePath) [-1]. split (".") [1]) ansigter = detektor.detectMultiScale (img_numpy) for (x, y, w, h) i ansigter: faceSamples.append (img_numpy [y: y+h, x: x+w]) ids.append (id) return faceSamples, ids print ("\ n [INFO] Træningsflader. Det vil tage et par sekunder. Vent …") ansigter, ids = getImagesAndLabels (sti) anerkender.train (ansigter, np.array (ids)) # Gem modellen i trainer/trainer.yml anerkender.skrive ('træner/træner.yml') # genkender.save () arbejdede på Mac, men ikke på Pi # Udskriv antallet af ansigter, der er uddannet, og afslut programudskrivning ("\ n [INFO] {0} uddannede ansigter. Afslutter program".format (len (np.unique (ids))))
Bekræft, om du har PIL -biblioteket installeret på din Rpi. Hvis ikke, skal du køre nedenstående kommando i Terminal:
pip installer pude
Vi vil bruge som en genkender LBPH (LOCAL BINARY PATTERNS HISTOGRAMS) Face Recognizer, der er inkluderet i OpenCV -pakken. Vi gør dette i følgende linje:
anerkender = cv2.face. LBPHFaceRecognizer_create ()
Funktionen "getImagesAndLabels (sti)", vil tage alle fotos på biblioteket: "datasæt/" og returnere 2 arrays: "Ids" og "ansigter". Med disse arrays som input vil vi "træne vores genkender":
anerkender.træning (ansigter, id'er)
Som et resultat vil en fil med navnet "trainer.yml" blive gemt i trænermappen, der tidligere blev oprettet af os.
Det er det! Jeg inkluderede den sidste udskrivningserklæring, hvor jeg viste for bekræftelse, antallet af brugerens ansigter, vi har trænet.
Hver gang du udfører fase 1, skal fase 2 også køres
Trin 7: Genkender
Nu nåede vi den sidste fase af vores projekt. Her vil vi fange et nyt ansigt på vores kamera, og hvis denne person havde fået sit ansigt fanget og trænet før, vil vores genkender lave en "forudsigelse", der returnerer sit id og et indeks, vist hvor sikker genkenderen er med denne kamp.
Lad os downloade 3. fase python script fra mit GitHub: 03_face_recognition.py.
import cv2
import numpy as np import os anerkender = cv2.face. LBPHFaceRecognizer_create () anerkender.read ('trainer/trainer.yml') cascadePath = "haarcascade_frontalface_default.xml" faceCascade = cv2. CascadeClassifier (cascadePath); font = cv2. FONT_HERSHEY_SIMPLEX #iniciate id counter id = 0 # names related to ids: example ==> Marcelo: id = 1, etc names = ['None', 'Marcelo', 'Paula', 'Ilza', 'Z ',' W '] # Initialiser og start realtime video capture cam = cv2. VideoCapture (0) cam.set (3, 640) # sæt video widht cam.set (4, 480) # indstil videohøjde # Definer min vinduesstørrelse skal genkendes som et ansigt minW = 0,1*cam.get (3) minH = 0,1*cam.get (4) mens True: ret, img = cam.read () img = cv2.flip (img, -1) # Vend lodret grå = cv2.cvtColor (img, cv2. COLOR_BGR2GRAY) ansigter = faceCascade.detectMultiScale (grå, scaleFactor = 1.2, minNeighbors = 5, minSize = (int (minW), int (minH)),) for (x, y, w, h) i ansigter: cv2.rektangel (img, (x, y), (x+w, y+h), (0, 255, 0), 2) id, tillid = anerkender. forudsigelse (grå [y: y+h, x: x+w]) # Kontroller, om tilliden er mindre dem 100 ==> "0" er perfekt match, hvis (tillid <100): id = navne [id] tillid = "{0}% ".format (runde (100 - konfidens)) else: id =" ukendt "tillid =" {0}%". format (runde (100 - konf. idence)) cv2.putText (img, str (id), (x+5, y-5), font, 1, (255, 255, 255), 2) cv2.putText (img, str (tillid), (x+5, y+h-5), skrifttype, 1, (255, 255, 0), 1) cv2.imshow ('kamera', img) k = cv2.waitKey (10) & 0xff # Tryk på 'ESC' for at forlade video, hvis k == 27: pause # Lav en smule oprydningsprint ("\ n [INFO] Afslutning af program og oprydning") cam.release () cv2.destroyAllWindows ()
Vi inkluderer her et nyt array, så vi vil vise "navne" i stedet for nummererede id'er:
names = ['None', 'Marcelo', 'Paula', 'Ilza', 'Z', 'W']
Så for eksempel: Marcelo vil brugeren med id = 1; Paula: id = 2 osv.
Dernæst vil vi registrere et ansigt, det samme som vi gjorde før med haasCascade -klassifikatoren. Når vi har et registreret ansigt, kan vi kalde den vigtigste funktion i ovenstående kode:
id, tillid = genkender. forudsigelse (grå del af ansigtet)
Recognizer.predict (), tager som en parameter en fanget del af ansigtet, der skal analyseres, og returnerer den sandsynlige ejer, hvilket angiver dens id og hvor stor tillid genkenderen har i forhold til denne kamp.
Bemærk, at konfidensindekset returnerer "nul", hvis det betragtes som et perfekt match
Og endelig, hvis genkenderen kunne forudsige et ansigt, satte vi en tekst over billedet med det sandsynlige id, og hvor meget er "sandsynligheden" i %, at matchen er korrekt ("sandsynlighed" = 100 - konfidensindeks). Hvis ikke, sættes en "uvidende" etiket på ansigtet.
Nedenfor en-g.webp
På ovenstående billede viser jeg nogle tests udført med dette projekt, hvor jeg også har brugt fotos til at kontrollere, om genkenderen fungerer.
Trin 8: Konklusion
Som altid håber jeg, at dette projekt kan hjælpe andre med at finde vej til den spændende elektronikverden!
For detaljer og endelig kode, besøg mit GitHub-depot: OpenCV-Face-Recognition
For flere projekter, besøg min blog: MJRoBot.org
Nedenfor et glimt af en fremtidig vejledning, hvor vi vil undersøge "automatisk ansigtsspor og andre metoder til ansigtsgenkendelse":
Saludos fra den sydlige del af verden!
Vi ses i min næste instruerbare!
Tak skal du have, Marcelo
Anbefalede:
MicroPython-program: Opdater data om coronavirus (COVID-19) i realtid: 10 trin (med billeder)
MicroPython-program: Opdater data om Coronavirus-sygdom (COVID-19) i realtid: I de sidste par uger er antallet af bekræftede tilfælde af coronavirus-sygdom (COVID 19) på verdensplan overskredet 100.000, og verdenssundhedsorganisationen (WHO) har erklæret nyt coronavirus lungebetændelse udbrud for at være en global pandemi. Jeg var meget
Lys mig op! en LED-stripkontrol i realtid på tværs af platforme: 5 trin (med billeder)
Lys mig op! en LED-stripkontrol i realtid på tværs af platforme: LightMeUp! er et system, jeg opfandt til styring af en RGB LED-strip i realtid, samtidig med at omkostningerne blev holdt lave og ydeevnen høj. Serveren er skrevet i Node.js og derfor krydsplatformbar. I mit eksempel bruger jeg en Raspberry Pi 3B til langtidsbrug
Dørklokke med ansigtsgenkendelse: 7 trin (med billeder)
Dørklokke med ansigtsgenkendelse: Motivation For nylig har der været en bølge af røverier i mit land, der er målrettet ældre i deres eget hjem. Normalt gives adgang fra beboerne selv, da de besøgende overbeviser dem om, at de er omsorgspersoner/sygeplejersker. Det
Ansigtsgenkendelse Smart Lock Med LTE Pi HAT: 4 trin
Ansigtsgenkendelse Smart Lock Med LTE Pi HAT: Ansigtsgenkendelse bliver mere og mere udbredt, vi kan bruge den til at lave en smart lås
ESP32 CAM ansigtsgenkendelse med MQTT -understøttelse - AI-tænker: 4 trin
ESP32 CAM ansigtsgenkendelse med MQTT -understøttelse | AI-tænker: Hej! Jeg ville dele min kode til et projekt, hvis jeg skulle have et ESP CAM med ansigtsgenkendelse, der kunne sende data til MQTT. Så godt .. efter måske 7 timers kig igennem flere kodeeksempler og ledt efter hvad der er hvad, har jeg fini