- Objectdetectie met SIFT
- Objectdetectie met behulp van ORB
- Histogram van georiënteerde verlopen (HOG's)
- Histogram van georiënteerde verlopen (HOG's), stap voor stap:
- HAAR cascade classificaties
- Gezichts- en oogherkenning
- Live gezichts- en oogdetectie
- Cascade-classificatoren afstemmen
- Auto- en voetgangersdetectie in video's
We zijn begonnen met het installeren van Python OpenCV op Windows en hebben tot dusver enkele basisbeeldverwerking, beeldsegmentatie en objectdetectie gedaan met Python, die worden behandeld in onderstaande tutorials:
- Aan de slag met Python OpenCV: installatie en basisbeeldverwerking
- Beeldmanipulaties in Python OpenCV (deel 1)
- Beeldmanipulaties in OpenCV (deel 2)
- Afbeeldingssegmentatie met behulp van OpenCV - Specifieke gebieden van een afbeelding extraheren
We leerden ook over verschillende methoden en algoritmen voor objectdetectie, waarbij enkele sleutelpunten voor elk object werden geïdentificeerd met behulp van verschillende algoritmen. In deze tutorial gaan we die algoritmen gebruiken om echte objecten te detecteren, hier zouden we SIFT en ORB gebruiken voor de detectie.
Objectdetectie met SIFT
Hier wordt objectdetectie gedaan met behulp van live webcamstream, dus als het object herkent, wordt het gevonden object vermeld. In de code wordt de hoofdrol gespeeld door de functie die wordt genoemd als SIFT-detector, het grootste deel van de verwerking wordt gedaan door deze functie.
En in de andere helft van de code beginnen we met het openen van de webcamstream, en laden vervolgens de afbeeldingssjabloon, dwz het referentiebeeld, dat wil zeggen dat het programma daadwerkelijk door de webcamstream kijkt.
Vervolgens leggen we continu de beelden van de webcamstream vast met behulp van de oneindige while- lus en leggen we vervolgens de corresponderende hoogte en breedte van het webcamframe vast, en definiëren daarna de parameters van het gebied van interesse (ROI) waarin ons object past in door de corresponderende hoogte en breedte van het webcamframe te nemen. En dan tekenen we de rechthoek uit de ROI-parameters die we hierboven hadden gedefinieerd. Snijd vervolgens de rechthoek uit en voer deze in het SWIFT-detectorgedeelte van de code.
Nu heeft de SIFT-detector in feite twee ingangen, één is de bijgesneden afbeelding en de andere is de afbeeldingssjabloon die we eerder hebben gedefinieerd en geeft ons vervolgens enkele overeenkomsten, dus overeenkomsten zijn in feite het aantal objecten of sleutelpunten dat vergelijkbaar is in de bijgesneden afbeelding en het doelbeeld. Vervolgens definiëren we een drempelwaarde voor de overeenkomsten, als de overeenkomstwaarde groter is dan de drempel, plaatsen we de afbeelding op ons scherm met de groene kleur van de ROI-rechthoek.
Laten we nu teruggaan naar het hoofdgedeelte van de code, de functie die wordt genoemd als SIFT-detector, het neemt de invoer als twee afbeeldingen, een is de afbeelding waar het naar het object zoekt en het andere is het object dat we proberen te matchen naar (afbeeldingsjabloon). Schaal vervolgens de eerste afbeelding in grijstinten en definieer de afbeeldingssjabloon als tweede afbeelding. Vervolgens maken we een SIFT-detectorobject en voeren we de OpenCV SIFT-detectie- en berekeningsfunctie uit, om de sleutelpunten te detecteren en de descriptoren te berekenen, descriptoren zijn in feite de vectoren die de informatie over de sleutelpunten opslaan, en het is erg belangrijk omdat we de matching doen tussen de descriptoren van de afbeeldingen.
En dan de op FLANN gebaseerde matcher definiëren, we gaan niet in op de wiskundige theorie van matching erachter, maar je kunt er gemakkelijk over googelen. Definieer eerst de index kdtree op nul en vervolgens stellen we de index en zoekparameters in het woordenboekformaat in, we definiëren alleen het algoritme dat we gaan gebruiken, namelijk KDTREE, en het aantal bomen dat we gaan gebruiken, hoe meer boom we gebruiken hoe ingewikkelder het wordt en langzamer. En definieer in de zoekparameter het aantal controles, wat in feite het aantal overeenkomsten is dat het gaat voltooien.
En maak vervolgens ons op FLANN gebaseerde matcher-object door de parameter te laden die we eerder hebben gedefinieerd, namelijk indexparameters en zoekparameters en op basis hiervan onze op FLANN gebaseerde matcher te maken, een KNN-matcher waarbij KNN K-dichtstbijzijnde buren is, in feite is het een manier waarop we zoeken naar dichtstbijzijnde matchers en descriptors en we doen de matching met initialisatieconstante k. Nu retourneert deze op FLANN gebaseerde matcher het aantal overeenkomsten dat we krijgen.
Op FLANN gebaseerde matching is slechts een benadering, dus om de nauwkeurigheid van de op FLANN gebaseerde matcher te vergroten, voeren we een Lowe's ratio-test uit en wat het doet is het zoeken naar de matches van de op knn flann gebaseerde matcher en enkele matrixparameters definiëren die hier de afstand is, waarvoor afstand een numpy-functie is, en zodra deze aan de criteria voldoet, voegt u de overeenkomsten toe aan de goede overeenkomsten en retourneert de gevonden goede overeenkomsten, zodat de live videostream het aantal gevonden overeenkomsten in de hoek van het scherm vertelt.
Laten we nu eens kijken naar de code voor de bovenstaande beschrijving:
import cv2 import numpy als np def sift_detector (new_image, image_template): # Functie die invoerafbeelding vergelijkt met sjabloon # Het retourneert vervolgens het aantal SIFT-overeenkomsten tussen hen image1 = cv2.cvtColor (new_image, cv2.COLOR_BGR2GRAY) image2 = image_template # Create SIFT-detectorobject #sift = cv2.SIFT () sift = cv2.xfeatures2d.SIFT_create () # Verkrijg de sleutelpunten en descriptoren met behulp van SIFT keypoints_1, descriptors_1 = sift.detectAndCompute (afbeelding1, Geen) keypoints_2, descriptors_2 = sift.detectAndCompute (afbeelding2, None) # Definieer parameters voor onze Flann Matcher FLANN_INDEX_KDTREE = 0 index_params = dict (algoritme = FLANN_INDEX_KDTREE, trees = 3) search_params = dict (controle = 100) # Maak de Flann Matcher object flann = cv2.FlannBasedMatcher (index_params, search_params) # verkrijgen wedstrijden met behulp van K-Naaste buur Method # het resultaat 'matchs' is het aantal gelijksoortige overeenkomsten gevonden in beide beelden wedstrijden = flann.knnMatch (descriptors_1, descriptors_2, k = 2) # Bewaar goede overeenkomsten met behulp van Lowe's ratio test good_matches = voor m, n in overeenkomsten: if m.distance <0.7 * n.distance: good_matches.append (m) retourneer len (good_matches) cap = cv2.VideoCapture (0) # Laad onze afbeelding sjabloon, dit is onze referentie afbeelding image_template = cv2.imread ('phone.jpg', 0) while True: # Ontvang webcam afbeeldingen ret, frame = cap.read () # Verkrijg hoogte en breedte van webcam frame hoogte, width = frame.shape # Definieer ROI Box afmetingen top_left_x = int (breedte / 3) top_left_y = int ((hoogte / 2) + (hoogte / 4)) bottom_right_x = int ((breedte / 3) * 2) bottom_right_y = int ((hoogte / 2) - (hoogte / 4)) # Teken een rechthoekig venster voor ons interessegebied cv2. Rechthoek (frame, (top_left_x, top_left_y), (bottom_right_x, bottom_right_y), 255, 3) # Bijsnijdvenster van observatie die we hierboven hebben gedefinieerd cropped = frame # Draai frame-oriëntatie horizontaal frame = cv2.flip (frame, 1) # Haal aantal SIFT-overeenkomsten op = sift_detector (bijgesneden, image_template) # Statusstring weergeven met het huidige nr. of matches cv2.putText (frame, str (matches), (450,450), cv2.FONT_HERSHEY_COMPLEX, 2, (0,255,0), 1) # Onze drempelwaarde om objectdeteciton aan te geven # We gebruiken 10 omdat de SIFT-detector kleine fout-positieven teruggeeft drempel = 10 # Als overeenkomsten onze drempel overschrijden, is het object gedetecteerd als overeenkomsten> drempel: cv2.rectangle (frame, (top_left_x, top_left_y), (bottom_right_x, bottom_right_y), (0,255,0), 3) cv2.putText (frame, 'Object Gevonden', (50,50), cv2.FONT_HERSHEY_COMPLEX, 2, (0,255,0), 2) cv2.imshow ('Objectdetector met SIFT', frame) if cv2.waitKey (1) == 13: # 13 is de Enter-toets break cap.release () cv2.destroyAllWindows ()
Objectdetectie met behulp van ORB
Objectdetectie met behulp van SIFT is vrij cool en nauwkeurig, omdat het een veel nauwkeurig aantal overeenkomsten genereert op basis van sleutelpunten, maar het is gepatenteerd en dat maakt het moeilijk om het te gebruiken voor commerciële toepassingen, de andere uitweg daarvoor is het ORB-algoritme voor objectdetectie.
Vergelijkbaar met de methode van objectdetectie door SIFT waarin we het programma in twee delen hebben verdeeld, zal hier hetzelfde worden gevolgd.
Ten eerste definiëren we de functie ORB_detector die twee ingangen nodig heeft, een is het livestream-beeld afkomstig van de webcam en het andere is de afbeeldingssjabloon op basis waarvan we onze afbeelding gaan matchen. Vervolgens schalen we ons webcambeeld in grijstinten en initialiseren we onze ORB-detector, en we stellen het hier in op 1000 sleutelpunten en schaalparameters van 1.2. je kunt gemakkelijk met deze parameters spelen en vervolgens de sleutelpunten (kp) en descriptors (des) detecteren voor zowel de afbeeldingen en de tweede parameter die we definiëren in de detectANDCompute- functie is GEEN, het vraagt om het gebruik van een afbeeldingsmasker of niet en we ontkennen het hier.
Ga dan naar de detector waar we eerder op FLANN gebaseerde matcher gebruikten, maar hier zullen we BFMatcher gebruiken en binnen BFMatcher definiëren we twee parameters, een is NORM_HAMMING en de andere is de crossCheck waarvan de waarde TRUE is.
Bereken vervolgens de overeenkomsten de overeenkomsten tussen die twee afbeeldingen met behulp van de hierboven gedefinieerde descriptoren, die in totaal het aantal overeenkomsten retourneren, aangezien deze overeenkomsten geen benadering zijn en daarom is het niet nodig om de verhoudingsproef van Lowe uit te voeren, in plaats daarvan sorteren we de overeenkomsten op basis van afstand, tenminste de afstand meer de overeenkomst is beter (hier betekent de afstand afstand tussen de punten), en aan het einde geven we het aantal overeenkomsten terug met behulp van de lengtefunctie.
En in de hoofdfunctie stellen we de drempel op een veel hogere waarde in, aangezien de orb-detector veel ruis genereert.
Laten we nu eens kijken naar code voor op ORB gebaseerde detectie
import cv2 import numpy als np def ORB_detector (new_image, image_template): # Functie die invoerafbeelding vergelijkt met sjabloon # Het retourneert vervolgens het aantal ORB-overeenkomsten tussen hen image1 = cv2.cvtColor (new_image, cv2.COLOR_BGR2GRAY) # Maak ORB-detector met 1000 sleutelpunten met een schaalpiramidefactor van 1,2 orb = cv2.ORB_create (1000, 1,2) # Detecteer sleutelpunten van originele afbeelding (kp1, des1) = orb.detectAndCompute (afbeelding1, Geen) # Detecteer sleutelpunten van geroteerde afbeelding (kp2, des2) = orb.detectAndCompute (image_template, None) # Create matcher # Let op: we gebruiken niet langer Flann-based matching bf = cv2.BFMatcher (cv2.NORM_HAMMING, crossCheck = True) # Doe overeenkomende overeenkomsten = bf.match (des1, des2) # Sorteer de overeenkomsten op basis van afstand. Minste afstand # is beter matches = gesorteerd (matches, key = lambda val: val.distance) return len (matches) cap = cv2.VideoCapture (0) # Laad ons afbeeldingsjabloon, dit is onze referentie afbeelding image_template = cv2.imread ('phone.jpg', 0) # image_template = cv2.imread ('images / kitkat.jpg', 0) terwijl True: # Get webcambeelden ret, kader = cap.read () # Get hoogte en breedte van webcam gestel hoogte, width = frame.shape # Definieer ROI Box-afmetingen ( merk op dat sommige van deze dingen buiten de lus moeten vallen) top_left_x = int (width / 3) top_left_y = int ((hoogte / 2) + (hoogte / 4)) bottom_right_x = int ((breedte / 3) * 2) bottom_right_y = int ((hoogte / 2) - (hoogte / 4)) # Teken rechthoekig venster voor onze interessegebied cv2.rectangle (frame, (top_left_x, top_left_y), (bottom_right_x, bottom_right_y), 255, 3) # Uitsnede observatievenster dat we hierboven hebben gedefinieerd cropped = frame # Frame oriëntatie horizontaal omdraaien frame = cv2.flip (frame, 1) # Haal het aantal ORB-overeenkomsten op = ORB_detector (cropped, image_template) # Geef de statusstring weer die het huidige nr. of matches output_string = "Matches =" + str (matches) cv2.putText (frame, output_string, (50,450), cv2.FONT_HERSHEY_COMPLEX, 2, (250,0,150), 2) # Onze drempelwaarde om objectdetectie aan te geven # Voor nieuwe afbeeldingen of belichtingsomstandigheden moet u wellicht een beetje experimenteren # Opmerking: de ORB-detector om de top 1000 overeenkomsten te krijgen, 350 is in wezen een min 35% overeenkomstdrempel = 250 # Als overeenkomsten onze drempel dan is object gedetecteerd als overeenkomsten> drempel: cv2.rectangle (frame, (top_left_x, top_left_y), (bottom_right_x, bottom_right_y), (0,255,0), 3) cv2.putText (frame, 'Object Found', (50, 50), cv2.FONT_HERSHEY_COMPLEX, 2, (0,255,0), 2) cv2.imshow ('Object Detector using ORB', frame) als cv2.waitKey (1) == 13: # 13 is de Enter Key break cap.release () cv2.destroyAllWindows ()
Histogram van georiënteerde verlopen (HOG's)
Laten we het nu hebben over een andere descriptor, namelijk Histogram of Oriented Gradients (HOG's).
HOG's zijn best coole en nuttige descriptors en ze worden op grote schaal en met succes gebruikt voor objectdetectie, zoals eerder gezien de afbeeldingsdescriptors zoals SIFT en ORB waar we sleutelpunten moeten berekenen en dan descriptoren moeten berekenen uit die sleutelpunten, HOG's doen dat proces anders. Het stelt objecten voor als een enkele kenmerkvector in tegenstelling tot een set kenmerkvectoren waarbij elk een segment van de afbeelding vertegenwoordigt. Dit betekent dat we een enkele vectorfunctie hebben voor de hele afbeelding.
Het wordt berekend door een schuifvensterdetector over een afbeelding, waarbij een HOG-descriptor wordt berekend voor elke positie. En dan wordt elke positie gecombineerd voor een enkele feature-vector.
Net als SIFT wordt de schaal van de afbeelding aangepast door middel van piramiden.
Eerder hebben we matchers zoals FLANN en BFMatcher gebruikt, maar HOG's doen het anders met behulp van SVM-classificaties (support vector machine), waarbij elke HOG-descriptor die wordt berekend, naar een SVM-classificator wordt gestuurd om te bepalen of het object is gevonden of niet.
Hier is de link naar een Great Paper van Dalal & Triggs over het gebruik van HOG's voor menselijke detectie:
Histogram van georiënteerde verlopen (HOG's), stap voor stap:
Het begrijpen van HOG's kan behoorlijk complex zijn, maar hier gaan we alleen de theorie van HOG's behandelen zonder dieper in te gaan op de wiskunde die ermee verband houdt.
Dus laten we deze foto nemen, hij is een beetje pixelachtig, en in de bovenhoek is hier een 8x8 pixel box, dus in deze box berekenen we de verloopvector of randoriëntaties bij elke pixel. Het betekent dus dat we in dit vak de afbeeldingsgradiëntvector berekenen van pixels in het vak (ze zijn een soort richting of stroom van de beeldintensiteit zelf), en dit genereert 64 (8 x 8) gradiëntvectoren die vervolgens worden weergegeven als een histogram. Stel je dus een histogram voor dat elke verloopvector vertegenwoordigt. Dus als alle punten of intensiteiten in één richting liggen, het histogram voor die richting laten we zeggen 45 graden, zou het histogram een piek hebben bij 45 graden.
Dus wat we nu doen, is dat we elke cel opsplitsen in hoekige bakken, waarbij elke bak overeenkomt met een verlooprichting (bijv. X, y). In het document Dalal en Triggs gebruikten ze 9 bakken van 0-180 ° (20 ° elke bak). Dit reduceert effectief 64 vectoren tot slechts 9 waarden. Dus wat we hebben gedaan, is het formaat verkleinen, maar alle belangrijke informatie behouden die nodig is.
De volgende stap bij het berekenen van het varken is de normalisatie, we normaliseren de gradiënten om ervoor te zorgen dat de verlichtingsveranderingen onveranderlijk zijn, dwz helderheid en contrast.
In deze afbeelding worden de intensiteitswaarden in het vierkant weergegeven volgens de respectieve richting en hebben ze allemaal een verschil van 50 tussen elkaar
∆ H = 50, ∆ v = 50; │∆│ = √50 2 +50 = 70,72, 70,72 / 100 = 0,707
We delen de vectoren door de gradiëntgroottes die we voor iedereen 0,707 krijgen, dit is normalisatie.
Evenzo krijgen we de onderstaande waarden als we de intensiteit of het contrast wijzigen.
∆ H = 50, ∆ v = 50; │∆│ = √50 2 +50 = 70,72, 70,72 / 100 = 0,707; ∆ H = 100, ∆ v = 100; │∆│ = √100 2 +100 = 141,42, 141,42 / 100 = 1,41
Normalisatie vindt niet plaats op celniveau, maar vindt plaats op blokniveau, dus hier zijn de blokken in feite een groep van 4 cellen, dit houdt rekening met naburige blokken en normaliseert dus rekening met grotere segmenten van het beeld.
Laten we nu eens naar de code kijken
import numpy als np import cv2 import matplotlib.pyplot als plt # Laad afbeelding en vervolgens grijswaardenafbeelding = cv2.imread ('elephant.jpg') grey = cv2.cvtColor (afbeelding, cv2.COLOR_BGR2GRAY) # Toon originele afbeelding cv2.imshow (' Input Image ', image) cv2.waitKey (0) #de parameters, celgrootte en blokgrootte definiëren # hxw in pixels cell_size = (8, 8) # hxw in cellen block_size = (2, 2) # aantal oriëntatiebakken nbins = 9 # Gebruikmakend van OpenCV's HOG Descriptor # winSize is de grootte van de afbeelding die is bijgesneden tot een veelvoud van de celgrootte hog = cv2.HOGDescriptor (_winSize = (grey.shape // cell_size * cell_size, gray.shape // cell_size * cell_size), _blockSize = (block_size * cell_size, block_size * cell_size), _blockStride = (cell_size, cell_size), _cellSize = (cell_size, cell_size), _nbins = nbins) # Maak numpy array-vorm die we gebruiken om hog_features n_cells = (grey.shape // cell_size, grey.shape // cell_size) te maken # We indexeren blokken eerst op rijen. # hog_feats bevat nu de gradiëntamplitudes voor elke richting, # voor elke cel van zijn groep voor elke groep. Indexeren gebeurt in rijen en vervolgens in kolommen. hog_feats = hog.compute (grijs).reshape (n_cells - block_size + 1, n_cells - block_size + 1, block_size, block_size, nbins).transpose ((1, 0, 2, 3, 4)) # Maak onze reeks met gradiënten met nbin-dimensies om gradiënten met verlooporiëntaties op te slaan = np.zeros ((n_cells, n_cells, nbins)) # Maak een array van dimensies cell_count = np.full ((n_cells, n_cells, 1), 0, dtype = int) # Block Normalization for off_y in range (block_size): voor off_x in range (block_size): verlopen - block_size + off_y + 1, off_x: n_cells - block_size + off_x + 1] + = \ hog_feats cell_count - block_size + off_y + 1, off_x: n_cells - block_size + off_x + 1] + = 1 # Gemiddelde gradiënten gradiënten / = cell_count # Plot HOG's met Matplotlib # hoek is 360 / nbins * direction color_bins = 5 plt.pcolor (verlopen) plt.gca (). invert_yaxis () plt.gca (). set_aspect ('gelijk', instelbaar = 'doos') plt.colorbar () plt.show () cv2.destroyAllWindows ()
De afbeelding laat zien hoe de invoerafbeelding wordt weergegeven als HOG-weergave.
HAAR cascade classificaties
Zoals eerder besproken, kunnen we functies uit een afbeelding extraheren en die functies gebruiken om objecten te classificeren of te detecteren.
Wat zijn HAAR Cascade-classificaties?
Een objectdetectiemethode die Haar-kenmerken invoert in een reeks classificaties (cascade) om objecten in een afbeelding te identificeren. Ze zijn getraind om één type object te identificeren, maar we kunnen er meerdere tegelijk gebruiken, bijvoorbeeld om ogen en gezichten samen te detecteren.
HAAR classifiers uitgelegd:
HAAR Classifiers worden getraind met behulp van veel positieve afbeeldingen (dwz afbeeldingen met het aanwezige object) en
negatieve afbeeldingen (dwz afbeeldingen zonder het aanwezige object).
Zodra we die afbeeldingen hebben, extraheren we kenmerken met schuifvensters van rechthoekige blokken. Deze kenmerken (HAAR-kenmerken) hebben een enkele waarde en worden berekend door de som van pixelintensiteiten onder de witte rechthoeken af te trekken van de zwarte rechthoeken.
Dit is echter een belachelijk aantal berekeningen, zelfs voor een basisvenster van 24 x 24 pixels (180.000 gegenereerde features).
Dus bedachten de onderzoekers een methode genaamd Integral Images die dit berekende met vier array-referenties. Ze hadden echter nog steeds 180.000 functies en de meeste voegden geen echte waarde toe.
Boosting werd vervolgens gebruikt om de meest informatieve functies te bepalen, met Freund & Schapire's AdaBoost en het vond de meest informatieve functies in de afbeelding. Boosting is het proces waarbij we zwakke classificaties gebruiken om sterke classificaties te bouwen, simpelweg door zwaarder gewogen straffen toe te kennen aan onjuiste classificaties. Het terugbrengen van de 180.000 features naar 6000, dat zijn nog best wat features.
In die 6000 functies zullen sommige meer informatief zijn dan andere. Dus als we de meest informatieve functies gebruiken om eerst te controleren of de regio mogelijk een gezicht kan hebben (false positives zijn geen probleem). Hierdoor is het niet meer nodig om alle 6000 kenmerken in één keer te berekenen. Dit concept wordt de Cascade of Classifiers genoemd - voor gezichtsherkenning gebruikte de Viola Jones-methode 38 fasen.
Gezichts- en oogherkenning
Dus na wat theoretische kennis over de HAAR-cascades te hebben opgedaan, gaan we het eindelijk implementeren, om dingen vrij duidelijk te maken zullen we de lessen in delen breken, eerst zouden we het frontale gezicht detecteren, daarna zullen we naar het frontale gezicht gaan met ogen en tot slot zouden we live detectie van gezicht en ogen doen via de webcam.
Dus hiervoor gaan we vooraf getrainde classificaties gebruiken die door OpenCV zijn geleverd als.xml-bestanden, xml staat voor uitbreidbare opmaaktaal, deze taal wordt gebruikt om een enorme hoeveelheid gegevens op te slaan, je zou er zelfs een database op kunnen bouwen.
U kunt via deze link toegang krijgen tot deze classificaties .
Gezichtsherkenning
Laten we proberen voor de frontale gezichtsherkenning, u kunt hier toegang krijgen tot de cascade van frontale gezichtsdetector. Pak het zip-bestand uit om het xml-bestand te krijgen.
import numpy als np import cv2 # We wijzen OpenCV's CascadeClassifier-functie naar waar onze # classifier (XML-bestandsformaat) is opgeslagen, vergeet niet om de code en classifier in dezelfde map te houden face_cascade = cv2.CascadeClassifier ('haarcascade_frontalface_default.xml') # Laden onze afbeelding converteert deze vervolgens naar afbeelding in grijstinten = cv2.imread ('Trump.jpg') grey = cv2.cvtColor (afbeelding, cv2.COLOR_BGR2GRAY) # Onze classificatie geeft de ROI van het gedetecteerde gezicht terug als een tupel # Het slaat linksboven op coördinaat en de coördinaten rechtsonder # het retourneert de lijst met lijsten, die de locatie zijn van verschillende gedetecteerde gezichten. faces = face_cascade.detectMultiScale (grijs, 1.3, 5) # Als er geen gezichten zijn gedetecteerd, geeft face_classifier een leeg tuple als gezichten als gezichten is (): print ("Geen gezichten gevonden") # We doorlopen onze reeks gezichten en tekenen een rechthoek # over elk gezicht in gezichten voor (x, y, w, h) in gezichten: cv2.rectangle (afbeelding, (x, y), (x + w, y + h), (127,0,255), 2) cv2.imshow ('Gezichtsdetectie', afbeelding) cv2.waitKey (0) cv2.destroyAllWindows ()
Laten we nu de gezichts- en oogdetectie combineren, u kunt toegang krijgen tot de cascade van oogdetectoren in hetzelfde zip-bestand.
import numpy als np import cv2 face_classifier = cv2.CascadeClassifier ('haarcascade_frontalface_default.xml') eye_classifier = cv2.CascadeClassifier ('haarcascade_eye.xml') img = cv2.imread ('Trump.jpg') grey = cv2.cvt, cv2.COLOR_BGR2GRAY) faces = face_classifier.detectMultiScale (grijs, 1.3, 5) # Als er geen gezichten worden gedetecteerd, geeft face_classifier een leeg tuple als gezichten is (): print ("Geen gezicht gevonden") voor (x, y, w, h) in gezichten: cv2.rechthoek (img, (x, y), (x + w, y + h), (127,0,255), 2) cv2.imshow ('img', img) roi_gray = grijs roi_color = img eyes = eye_classifier.detectMultiScale (roi_gray) cv2.waitKey (0) voor (ex, ey, ew, eh) in ogen: cv2.rechthoek (roi_color, (ex, ey), (ex + ew, ey + eh), (255,255,0), 2) cv2.imshow ('img', img) cv2.waitKey (0) cv2.destroyAllWindows () cv2.waitKey (0)
Dus deze code is net zo goed als de code voor de gezichtsherkenning, maar hier hebben we oogcascades en een methode toegevoegd om ze te detecteren, zoals je kunt zien hebben we de grijs geschaalde versie van het gezicht gekozen als de parameter voor de detectMultiScale voor de ogen, wat ons bij de vermindering van de berekening brengt, aangezien we alleen ogen alleen in dat gebied zullen detecteren.
Live gezichts- en oogdetectie
Dus tot nu toe hebben we gezichts- en oogdetectie gedaan, laten we nu hetzelfde implementeren met de live videostream van de webcam. Hierin zullen we dezelfde detectie van gezicht en ogen doen, maar deze keer doen we het voor de livestream van de webcam. In de meeste toepassingen zou je je gezicht gemarkeerd vinden met een kader eromheen, maar hier hebben we iets anders gedaan waardoor je je gezicht zou zien uitgesneden en de ogen zouden zich alleen daarin identificeren.
Hierin importeren we dus zowel de gezichts- als de oogclassificatie en hebben we een functie gedefinieerd voor het uitvoeren van alle bewerkingen voor gezichts- en oogdetectie. En daarna startte de webcam-stream en riep de gezichtsdetectorfunctie op om het gezicht en de ogen te detecteren. De parameter die we definiëren binnen de gezichtsherkenningsfunctie zijn de continue beelden van live webcamstreams
import cv2 import numpy als np face_classifier = cv2.CascadeClassifier ('haarcascade_frontalface_default.xml') eye_classifier = cv2.CascadeClassifier ('haarcascade_eye.xml') def face_detector (img, size = 0.5): # Converteer afbeelding naar grijswaarden = cvtCvt (img, cv2.COLOR_BGR2GRAY) gezichten = face_classifier.detectMultiScale (grijs, 1.3, 5) als gezichten () is: geef img terug voor (x, y, w, h) in gezichten: x = x - 50 w = w + 50 y = y - 50 h = h + 50 cv2. rechthoek (img, (x, y), (x + w, y + h), (255,0,0), 2) roi_gray = grijs roi_color = img ogen = eye_classifier.detectMultiScale (roi_gray) voor (ex, ey, ew, eh) in ogen: cv2.rechthoek (roi_color, (ex, ey), (ex + ew, ey + eh), (0,0,255), 2) roi_color = cv2.flip (roi_color, 1) return roi_color cap = cv2.VideoCapture (0) while True: ret, frame = cap.read () cv2.imshow ('Our Face Extractor', face_detector (frame)) als cv2.waitKey (1) == 13: # 13 de Enter-toets is break cap.release () cv2.destroyAllWindows ()
Cascade-classificatoren afstemmen
De parameters die zijn gedefinieerd in detectMultiScale anders dan de invoerafbeelding, hebben de volgende betekenis
onzeClassifier. detectMultiScale (invoerbeeld, schaalfactor, min. buren)
- Schaalfactor Specificeert hoeveel we de afbeeldingsgrootte verkleinen elke keer dat we schalen. Bij gezichtsherkenning gebruiken we bijvoorbeeld meestal 1.3. Dit betekent dat we de afbeelding elke keer dat deze wordt geschaald, met 30% verkleinen. Bij kleinere waarden, zoals 1,05, duurt het langer om te berekenen, maar wordt de detectiesnelheid verhoogd.
- Min buren Specificeert het aantal buren dat elk potentieel raam moet hebben om het als een positieve detectie te beschouwen. Meestal ingesteld tussen 3-6. Het fungeert als gevoeligheidsinstelling, lage waarden detecteren soms meerdere gezichten over één enkel gezicht. Hoge waarden zorgen voor minder valse positieven, maar het kan zijn dat u enkele gezichten mist.
Auto- en voetgangersdetectie in video's
Nu zullen we voetgangers en auto's detecteren in video's met behulp van de HAAR-cascades, maar in het geval dat er geen video wordt geladen en de code zonder fouten compileert, moet u de volgende stappen volgen:
Als er geen video wordt geladen na het uitvoeren van code, moet u mogelijk onze opencv_ffmpeg.dl kopiëren van : opencv \ sources \ 3rdparty \ ffmpeg om het te plakken waar uw python is geïnstalleerd, bijvoorbeeld C: \ Anaconda2
Nadat het is gekopieerd, moet u het bestand hernoemen volgens de versie van OpenCV die u gebruikt. Bv als u OpenCV 2.4.13 gebruikt, hernoem het bestand dan als: opencv_ffmpeg2413_64.dll of opencv_ffmpeg2413.dll (als u met een X86-machine) opencv_ffmpeg310_64.dll of opencv_ffmpeg310.dll (als u een X86-machine gebruikt)
Om erachter te komen waar python.exe is geïnstalleerd, voert u gewoon deze twee regels code uit, het zou de locatie afdrukken waar Python is geïnstalleerd.
import sys print (sys.executable)
Als u deze stappen met succes hebt uitgevoerd, gaan we naar de code voor voetgangersdetectie, U kunt de cascade voor voetgangersdetectie en van het zip-bestand hier bijgevoegd hebben.
import cv2 import numpy als np # Maak onze bodyclassifier body_classifier = cv2.CascadeClassifier ('haarcascade_fullbody.xml') # Start video-opname voor videobestand, hier gebruiken we het videobestand waarin voetgangers zouden worden gedetecteerd cap = cv2.VideoCapture ('walking.avi') # Loop zodra de video met succes is geladen terwijl cap.isOpened (): # Elk frame van de video wordt gelezen ret, frame = cap.read () # hier passen we de grootte van het frame aan tot de helft van de grootte, we doen het om de classificatie te versnellen # aangezien grotere afbeeldingen veel meer vensters hebben om overheen te schuiven, dus over het algemeen verlagen we de resolutie #video met de helft, dat is wat 0,5 aangeeft, en we gebruiken ook een snellere interpolatiemethode, namelijk #interlinear frame = cv2.resize (frame, None, fx = 0,5, fy = 0,5, interpolation = cv2.INTER_LINEAR) grey = cv2. cvtColor (frame, cv2.COLOR_BGR2GRAY) # Geef frame door aan onze body classifier bodies = body_classifier.detectMultiScale (grijs, 1.2, 3) # Extraheer selectiekaders voor alle lichamen geïdentificeerd voor (x, y, w, h) in body's: cv2. rechthoek (frame, (x, y), (x + w, y + h), (0, 255, 255), 2) cv2.imshow ('Pedestrians', frame) if cv2.waitKey (1) == 13: # 13 is de Enter-toets break cap.release () cv2.destroyAllWindows ()
Nadat we voetganger met succes in video hebben gedetecteerd, gaan we naar de code voor autodetectie.U kunt vanaf hier de cascade voor voetgangersdetectie hebben.
import cv2 import tijd import numpy als np # Maak onze bodyclassifier car_classifier = cv2.CascadeClassifier ('haarcascade_car.xml') # Start video-opname voor videobestand cap = cv2.VideoCapture ('cars.avi') # Loop zodra video succesvol is geladen terwijl cap.isOpened (): time.sleep (.05) # Lees eerste frame ret, frame = cap.read () grey = cv2.cvtColor (frame, cv2.COLOR_BGR2GRAY) # Geef frame door aan onze autoclassificator cars = car_classifier.detectMultiScale (grijs, 1.4, 2) # Extraheer selectiekaders voor alle lichamen geïdentificeerd voor (x, y, w, h) in auto's: cv2. rechthoek (frame, (x, y), (x + w, y + h), (0, 255, 255), 2) cv2.imshow ('Cars', frame) if cv2.waitKey (1) == 13: # 13 is de Enter-toets break cap.release () cv2.destroyAllWindows ()
Je hebt gemerkt dat we time.sleep (.05) hebben toegevoegd, het is gewoon een vertraging in de framesnelheid, zodat je kunt bevestigen dat alle auto's correct zijn geïdentificeerd, of je kunt het eenvoudig verwijderen door er een commentaarlabel aan toe te voegen.
Dit artikel is verwezen vanuit de Master Computer Vision ™ OpenCV4 in Python met Deep Learning-cursus op Udemy, gemaakt door Rajeev Ratan, abonneer het voor meer informatie over Computer Vision en Python.