Personenzählung mit OpenCV, Python und Ubidots

Die digitale Bildverarbeitung (Digital Image Processing, DIP) wächst rasant, was zum großen Teil der Zunahme verfügbarer Techniken des maschinellen Lernens , auf die Entwickler über die Cloud zugreifen können. Durch die Möglichkeit, digitale Bilder über die Cloud zu verarbeiten, sind keine speziellen Hardware-Anforderungen erforderlich, was DIP letztendlich zur ersten Wahl macht. Als kostengünstigste und vielseitigste Methode zur Bildverarbeitung hat DIP vielfältige Anwendungsmöglichkeiten gefunden. Eine der gebräuchlichsten Methoden ist die Fußgängererkennung und -zählung – eine nützliche Messgröße für Flughäfen, Bahnhöfe, Einzelhandelsgeschäfte, Stadien, öffentliche Veranstaltungen und Museen.

Herkömmliche Personenzähler von der Stange sind nicht nur teuer – die von ihnen generierten Daten sind oft an proprietäre Systeme gebunden, die Ihre Möglichkeiten zur Datenextraktion und KPI-Optimierung einschränken. Umgekehrt spart ein eingebettetes DIP mit Ihrer eigenen Kamera und SBC nicht nur Zeit und Geld, sondern gibt Ihnen auch die Freiheit, Ihre Anwendung an die für Sie wichtigen KPIs anzupassen und Erkenntnisse aus der Cloud zu gewinnen, die sonst nicht möglich wären .

Die Nutzung der Cloud zur Aktivierung Ihrer DIP- IoT Anwendung ermöglicht eine verbesserte Gesamtfunktionalität. Mit erweiterten Funktionen in Form von Visualisierungen , Berichten, Warnungen und Querverweisen auf externe Datenquellen (z. B. Wetter, Live-Preisgestaltung von Anbietern oder Geschäftsverwaltungssysteme) bietet DIP Entwicklern die Freiheit, die sie sich wünschen.

Stellen Sie sich einen Lebensmittelhändler mit einem Eiskühlschrank vor: Er möchte die Anzahl der Passanten verfolgen und ein Produkt auswählen, außerdem die Häufigkeit, mit der die Tür geöffnet wurde, und die Innentemperatur des Kühlschranks. Anhand dieser wenigen Datenpunkte kann ein Einzelhändler eine Korrelationsanalyse durchführen, um seine Produktpreise und den Gesamtenergieverbrauch des Kühlschranks besser zu verstehen und zu optimieren.

Um mit Ihrer digitalen Bildverarbeitungsanwendung zu beginnen, Ubidots Tutorial zum Personenzählsystem mit OpenCV und Python erstellt . Erweitern Sie Ihre Anwendungen über das bloße Zählen von Personen hinaus mit den zusätzlichen Ressourcen der IoT Entwicklungsplattform Ubidots Hier können Sie ein echtes dashboard zur Personenzählung das mit Ubidots .

OpenCV und Ubidots einen Personenzähler zu erstellen . Dieses Beispiel funktioniert am besten mit jeder Linux-basierten Distribution und auch in einem Raspberry Pi, Orange Pi oder ähnlichen eingebetteten Systemen.

Für weitere Integrationsanfragen wenden Sie sich an Ubidots -Support und erfahren Sie, wie Ihr Unternehmen von dieser wertschöpfenden Technologie profitieren kann.

Inhaltsverzeichnis:

  1. Bewerbungsvoraussetzungen
  2. Codierung – 8 Unterabschnitte
  3. Testen
  4. Erstellen Sie Ihr Dashboard
  5. Ergebnisse

1) Bewerbungsvoraussetzungen

  • Jedes eingebettete Linux mit einer abgeleiteten Version von Ubuntu
  • Python 3 oder neuer ist in Ihrem Betriebssystem installiert.
  • OpenCV 3.0 oder höher ist in Ihrem Betriebssystem installiert. Wenn Sie Ubuntu oder seine Derivate verwenden, befolgen Sie das offizielle Installations-Tutorial oder führen Sie den folgenden Befehl aus:
pip installiere opencv-contrib-python
  • Sobald Sie Python 3 und OpenCV erfolgreich installiert haben, überprüfen Sie Ihre Konfiguration, indem Sie diesen kleinen Code ausführen (geben Sie einfach „python“ in Ihr Terminal ein):
cv2 cv2.__version__ importieren

Sie sollten einen Druckbildschirm mit Ihrer OpenCV-Version erhalten:

  • Installieren Sie Numpy, indem Sie den offiziellen Anweisungen folgen oder einfach den folgenden Befehl ausführen:
pip install numpy
  • Installieren Sie imutils
pip install imutils
  • Installationsanfragen
pip-Installationsanfragen

2) Codierung

Die gesamte Routine zur Erkennung und zum Senden von Daten finden Sie hier . Zur besseren Erläuterung unserer Codierung werden wir den Code in acht Abschnitte aufteilen, um jeden Aspekt des Codes für Ihr besseres Verständnis besser zu erläutern.

Abschnitt 1:

from imutils.object_detection import non_max_suppression import numpy as np import imutils import cv2 import request import time import argparse URL_EDUCATIONAL = "http://things. ubidots .com" URL_INDUSTRIAL = "http://industrial.api. ubidots .com" INDUSTRIAL_USER = True # Setzen Sie dies auf False, wenn Sie ein Bildungsbenutzer sind. TOKEN = "...." # Geben Sie hier Ihr Ubidots TOKEN ein. DEVICE = "detector" # Gerät, auf dem das Ergebnis gespeichert wird. VARIABLE = "people" # Variable, in der gespeichert wird das Ergebnis # Opencv vorab trainierte SVM mit HOG-Personenfunktionen HOGCV = cv2.HOGDescriptor() HOGCV.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())

In Abschnitt 1 importieren wir die notwendigen Bibliotheken, um unseren Detektor zu implementieren. Imutils ist ein nützliches Bibliothekstool für DIP und ermöglicht es uns, verschiedene Transformationen unserer Ergebnisse durchzuführen. cv2 ist unser OpenCV-Python-Wrapper. Mit Anfragen können wir unsere Daten/Ergebnisse senden HTTP zu Ubidots und argparse ermöglichen es uns, Befehle von unserem Befehlsterminal in unserem Skript zu lesen.

WICHTIG: Vergessen Sie nicht, diesen Code mit Ihrem Ubidots -Konto-TOKEN . Wenn Sie ein Bildungsbenutzer , stellen Sie sicher, dass INDUSTRIAL_USER auf FALSE .

Nachdem die Bibliothek importiert wurde, initialisieren wir unseren Histogram Oriented Object-Deskriptor. Kurz gesagt, HOG ist eine der beliebtesten Techniken zur Objekterkennung und wurde in mehreren Anwendungen mit erfolgreichen Ergebnissen implementiert. Zu unserem Glück hat OpenCV bereits eine effiziente Kombination des HOG-Algorithmus mit einer Support-Vektor-Maschine , oder SVM, eine klassische Technik des maschinellen Lernens für Vorhersagezwecke.

Diese Deklaration: cv2.HOGDescriptor_getDefaultPeopleDetector() ruft das vorab trainierte Modell zur Personenerkennung von OpenCV auf und speist unsere Support-Vector-Machine-Funktionsbewertungsfunktion.

Abschnitt 2

def detector(image): ''' @image ist ein Numpy-Array ''' image = imutils.resize(image, width=min(400, image.shape[1])) clone = image.copy() (rects, Gewichte) = HOGCV.detectMultiScale(image, winStride=(8, 8), padding=(32, 32), scale=1.05) # Wendet nicht-maximale Unterdrückung aus dem imutils-Paket an, um überlappende # Boxen anzustoßen rects = np.array ([[x, y, x + w, y + h] für (x, y, w, h) in rects]) result = non_max_suppression(rects, probs=None,laplapThresh=0.65) Ergebnis zurückgeben

der detector() geschieht die „Magie“, sie empfängt ein RGB-Bild, das in drei Farbkanäle aufgeteilt ist. Um Leistungsprobleme zu vermeiden, ändern wir die Größe des Bildes mithilfe von Imutils und rufen dann die discoverMultiScale() von unserem HOG-Objekt aus auf. Mit der Erkennungs-Multiskalen-Methode können wir dann das Bild analysieren und mithilfe des Klassifizierungsergebnisses unserer SVM feststellen, ob eine Person existiert. Die Parameter dieser Methode gehen über den Rahmen dieses Tutorials hinaus. Wenn Sie jedoch mehr wissen möchten, lesen Sie die offiziellen OpenCV-Dokumente oder lesen Sie die großartige Erklärung von Adrian Rosebrock .

Die HOG-Analyse generiert einige Capture-Boxen (erkannte Objekte), aber manchmal überlappen sich diese Boxen, was zu Fehlalarmen oder Erkennungsfehlern führt. Um diese Verwirrung zu umgehen, verwenden wir das Dienstprogramm zur Nichtmaxima-Unterdrückung aus der imutils -Bibliothek, um die überlappenden Kästchen zu entfernen – wie unten dargestellt:

Bilder reproduziert von https://www.pyimagesearch.com

Abschnitt 3:

def localDetect(image_path): result = [] image = cv2.imread(image_path) if len(image) <= 0: print("[ERROR] konnte Ihr lokales Bild nicht lesen") return result print("[INFO] Detecting people") result = detector(image) # zeigt das Ergebnis für (xA, yA, xB, yB) in result: cv2.rectangle(image, (xA, yA), (xB, yB), (0, 255, 0 ), 2) cv2.imshow("result", image) cv2.waitKey(0) cv2.destroyAllWindows() return (result, image)

In diesem Teil unseres Codes müssen wir nun eine Funktion definieren, um ein Bild aus einer lokalen Datei zu lesen und alle darin enthaltenen Personen zu erkennen. Funktion detector() aufgerufen und eine einfache Schleife hinzugefügt, um die runden Kästchen für den Detektor zu malen. Es gibt die Anzahl der erkannten Kästchen und das Bild mit der gemalten Erkennung zurück. Anschließend erstellen Sie das Ergebnis einfach in einem neuen Betriebssystemfenster neu.

Abschnitt 4:

def cameraDetect(token, device, variable, sample_time=5): cap = cv2.VideoCapture(0) init = time.time() # Zulässige Abtastzeit für Ubidots ist 1 Punkt/Sekunde, wenn sample_time < 1: sample_time = 1 while( True): # Bild für Bild erfassen ret, frame = cap.read() frame = imutils.resize(frame, width=min(400, frame.shape[1])) result = detector(frame.copy() ) # zeigt das Ergebnis für (xA, yA, xB, yB) im Ergebnis: cv2.rectangle(frame, (xA, yA), (xB, yB), (0, 255, 0), 2) cv2.imshow( 'frame', Frame) # Sendet Ergebnisse, wenn time.time() - init >= sample_time: print("[INFO] Aktuelle Frame-Ergebnisse werden gesendet") # Konvertiert das Bild in Base 64 und fügt es dem Kontext hinzu b64 = Convert_to_base64( Frame) context = {"image": b64} sendTo Ubidots (token, device, variable, len(result), context=context) init = time.time() if cv2.waitKey(1) & 0xFF == ord(' q'): break # Wenn alles erledigt ist, lassen Sie die Aufnahme los cap.release() cv2.destroyAllWindows() def Convert_to_base64(image): image = imutils.resize(image, width=400) img_str = cv2.imencode('.png ', image)[1].tostring() b64 = base64.b64encode(img_str) return b64.decode('utf-8')

Ähnlich wie die Funktion in Abschnitt 3 ruft diese in Abschnitt 4 detector() und die Malboxen auf und das Bild wird mithilfe der VideoCapture() von OpenCV direkt von der Webcam abgerufen. offizielle OpenCV leicht modifiziert, alle „n“ Sekunden Ubidots sendTo Ubidots () wird später in diesem Tutorial besprochen). Die Funktion „convert_to_base64()“ konvertiert Ihr Bild in einen Basis-64-String. Dieser String ist sehr wichtig, um unsere Ergebnisse in Ubidots mithilfe von JavaScript-Code in einem HTML-Canvas-Widget anzusehen.

Abschnitt 5:

def discoverPeople(args): image_path = args["image"] camera = True if str(args["camera"]) == 'true' else False # Routine zum Lesen des lokalen Bildes, wenn image_path != None und nicht camera: print („[INFO] Bildpfad angegeben, versucht, Bild zu lesen“) (result, image) = localDetect(image_path) print(“[INFO] Ergebnisse senden“) # Konvertiert das Bild in Basis 64 und fügt es dem Kontext b64 = hinzu Convert_to_base64(image) context = {"image": b64} # Sendet das Ergebnis req = sendTo Ubidots (TOKEN, DEVICE, VARIABLE, len(result), context=context) if req.status_code >= 400: print("[ERROR ] Daten konnten nicht an Ubidots gesendet werden") return req # Routine zum Lesen von Bildern von der Webcam, wenn Kamera: print("[INFO] Kamerabilder lesen") cameraDetect(TOKEN, DEVICE, VARIABLE)

Diese Methode dient dazu, die Argumente über Ihr Terminal einzufügen und eine Routine auszulösen, die in einer lokal gespeicherten Bilddatei oder über Ihre Webcam nach Personen sucht.

Abschnitt 6:

def buildPayload(variable, value, context): return {variable: {"value": value, "context": context}} def sendTo Ubidots (token, device, variable, value, context={}, industrial=True): # Erstellt den Endpunkt url = URL_INDUSTRIAL, wenn industriell, sonst URL_EDUCATIONAL url = "{}/api/v1.6/devices/{}".format(url, device) payload = buildPayload(variable, value, context) headers = {"X -Auth-Token“: Token, „Content-Type“: „application/json“} Versuche = 0 Status = 400, während Status >= 400 und Versuche <= 5: req = request.post(url=url, headers=headers , json=payload) status = req.status_code versucht += 1 time.sleep(1) return req

Diese beiden Funktionen von Abschnitt 6 bilden die Grundlage für die Übermittlung Ihrer Ergebnisse an Ubidots um Ihre Daten zu verstehen und zu visualisieren. Die erste Funktion def buildPayload erstellt die Nutzlast innerhalb der Anfrage, während die zweite Funktion def sendTo Ubidots Ihre Ubidots Parameter (TOKEN , die Variable und Gerätebezeichnungen) empfängt, um die Ergebnisse zu speichern. In diesem Fall handelt es sich um die Länge der von OpenCV erkannten Roundboxen. Optional kann auch ein Kontext gesendet werden, um die Ergebnisse als Base64-Bild zu speichern, damit sie später abgerufen werden können.

Abschnitt 7:

def argsParser(): ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", default=None, help="Pfad zum Verzeichnis der Bildtestdatei") ap.add_argument("-c" , „--camera“, default=False, help="Auf true setzen, wenn Sie die Kamera verwenden möchten") args = vars(ap.parse_args()) Rückgabeargumente

In Abschnitt 7 erreichen wir nun das Ende unserer Codeanalyse. Die Funktion argsParser() analysiert einfach die Argumente, die über Ihr Terminal an unser Skript übergeben wurden, und gibt sie als Wörterbuch zurück. Im Parser gibt es zwei Argumente:

  • image: Der Pfad zur Image-Datei in Ihrem System
  • camera: Eine Variable, die, wenn sie auf „true“ gesetzt ist, die cameraDetect()-Methode aufruft.

Abschnitt 8:

def main(): args = argsParser() discoverPeople(args) if __name__ == '__main__': main()

Abschnitt 8 und der letzte Teil unseres Codes ist die main() , die einfach die Argumente von der Konsole aus aufruft und die angegebene Routine startet.

Vergessen Sie nicht, dass der gesamte Code hier von Github .

3) Testen

Öffnen Sie Ihren bevorzugten Textprozessor (Sublime-Text, Notepad, Nano usw.) und kopieren Sie den vollständigen Code, der hier . Aktualisieren Sie den Code mit Ihrem spezifischen Ubidots -TOKEN und speichern Sie Ihre Datei als „peopleCounter.py“.

Wenn Ihr Code ordnungsgemäß gespeichert ist, testen wir die nächsten vier zufälligen Bilder, die aus dem Caltech-Datensatz und dem öffentlichen Pexels-Datensatz ausgewählt wurden:

Um diese Bilder zu analysieren, müssen Sie sie zunächst auf Ihrem Laptop oder PC speichern und den Pfad zur Analyse der Bilder verfolgen.

Python peopleCounter.py PATH_TO_IMAGE_FILE

In meinem Fall habe ich die Bilder in einem Pfad mit der Bezeichnung „Datensatz“ gespeichert. Um einen gültigen Befehl auszuführen, führen Sie den folgenden Befehl aus, jedoch mit dem Pfad Ihres Bildes.

python peopleCounter.py -i dataset/image_1.png

Wenn Sie Bilder von Ihrer Kamera statt einer lokalen Datei aufnehmen möchten, führen Sie einfach den folgenden Befehl aus:

Python peopleCounter.py -c true

Testergebnisse:

Zusätzlich zu diesen Testprüfungen sehen Sie in Echtzeit auch die Ergebnisse dieser Tests, die in Ihrem Ubidots -Konto gespeichert sind:

4) Erstellen Sie Ihr Dashboard

Wir werden einen HTML-Canvas verwenden, um unsere Ergebnisse in Echtzeit anzusehen. Dieses Tutorial ist nicht für HTML-Canvas-Widgets gedacht. Wenn Sie also nicht wissen, wie man sie verwendet, lesen Sie bitte die folgenden Artikel:

Wir werden das grundlegende Echtzeitbeispiel mit geringfügigen Modifikationen verwenden, um unsere Bilder anzusehen. Unten sehen Sie den Codeausschnitt des Widgets

HTML

<img id="img" width="400px" height="auto"/>

JS

Var-Sockel; var srv = "industrial. ubidots .com:443"; // var srv = "app. ubidots .com:443" // Kommentieren Sie diese Zeile aus, wenn Sie ein Bildungsbenutzer sind var VAR_ID = "5ab402dabbddbd3476d85967"; // Geben Sie hier Ihre Var-ID ein. var TOKEN = "" // Geben Sie hier Ihr Token ein $ ( document ).ready(function() { function renderImage(imageBase64){ if (!imageBase64) return; $ ('#img'). attr('src', 'data:image/png;base64, ' + imageBase64); } // Funktion zum Abrufen des letzten Werts, sie wird nur einmal ausgeführt function getDataFromVariable(variable, token, callback) { var url = 'https: //things. ubidots .com/api/v1.6/variables/' + variable + '/values'; var headers = { 'X-Auth-Token': token, 'Content-Type': 'application/json' }; $ .ajax({ url: url, method: 'GET', headers: headers, data : { page_size: 1 }, success: function (res) { if (results.length > 0){ renderImage(res .results[0].context.image); } callback(); } } // Implementiert die Verbindung zum Server socket = io.connect("https://"+ srv, {path: '/notifications '}); var subscribedVars = []; // Funktion zum Veröffentlichen der Variablen-ID var subscribeVariable = function (variable, callback) { // Veröffentlicht die Variablen-ID, die abgehört werden soll socket.emit('rt/variables/id/last_value ', { Variable: Variable }); // Hört auf Änderungen socket.on('rt/variables/' + variable + '/last_value', callback); subscribedVars.push(variable); }; // Funktion zum Abmelden zum Abhören var unSubscribeVariable = function (variable) { socket.emit('unsub/rt/variables/id/last_value', { variable: variable }); var pst = subscribedVars.indexOf(variable); if (pst !== -1){ subscribedVars.splice(pst, 1); } }; var connectSocket = function (){ // Implementiert die Socket-Verbindung socket.on('connect', function(){ console.log('connect'); socket.emit('authentication', {token: TOKEN}); } ); window.addEventListener('online', function () { console.log('online'); socket.emit('authentication', {token: TOKEN}); }); socket.on('authenticated', function () { console.log('authenticated'); subscribedVars.forEach(function (variable_id) { socket.emit('rt/variables/id/last_value', { variable: variable_id }) ; }); } /* Hauptroutine */ getDataFromVariable(VAR_ID, TOKEN, function(){ connectSocket(); }); connectSocket(); //connectSocket(); // Variable mit Ihrem eigenen Code abonnieren. subscribeVariable(VAR_ID, function(value){ var parsedValue = JSON.parse(value); console.log(parsedValue); // $ ('#img').attr('src', 'data:image/png;base64 , ' + parsedValue.context.image); renderImage(parsedValue.context.image }) });

-TOKEN und die Variablen-ID am Anfang des Code-Snippets anzugeben

Bibliotheken Dritter

Fügen Sie die nächsten Bibliotheken von Drittanbietern hinzu:

Sobald Sie Ihr Widget gespeichert haben, sollten Sie etwas wie das Folgende erhalten:

5) Ergebnisse

Link können Sie sich die dashboards mit den Ergebnissen .

In diesem Artikel haben wir untersucht, wie man mithilfe von DIP (Bildverarbeitung), OpenCV und Ubidots IoT . Mit diesen Diensten ist Ihre DIP-Anwendung bei der Erkennung und Identifizierung der Unterschiede zwischen Personen, Orten oder Dingen weitaus genauer als PIR- oder andere optische Sensoren – so erhalten Sie einen effizienten Personenzähler ohne die statische Aufladung früher Datenmanipulationen.

Teilen Sie uns Ihre Meinung mit, indem Sie Ubidots einen Kommentar in unseren Community-Foren hinterlassen oder sich einfach über Facebook , Twitter oder Hackster Ubidots .

Viel Spaß beim Hacken!

Empfohlene Artikel