- Kohteen tunnistus SIFT: n avulla
- Kohteen tunnistus ORB: llä
- Suunniteltujen kaltevuuksien histogrammi
- Suuntautuneiden liukuvärien histogrammi, askel askeleelta:
- HAAR-kaskadiluokituslaitteet
- Kasvojen ja silmien tunnistus
- Live kasvojen ja silmien tunnistus
- Cascade-luokittelijoiden viritys
- Autojen ja jalankulkijoiden havaitseminen videoissa
Aloitimme python OpenCV: n asentamisesta ikkunoihin ja tähän mennessä olemme tehneet joitain peruskuvankäsittelyjä, kuvien segmentointia ja kohteiden havaitsemista Pythonilla, jotka on käsitelty alla olevissa opetusohjelmissa:
- Python OpenCV: n käytön aloittaminen: Asennus ja kuvankäsittely
- Kuvankäsittelyt Python OpenCV: ssä (osa 1)
- Kuvankäsittelyt OpenCV: ssä (osa 2)
- Kuvan segmentointi OpenCV: n avulla - Kuvan tiettyjen alueiden purkaminen
Opimme myös erilaisista kohteiden havaitsemisen menetelmistä ja algoritmeista, joissa jokaiselle objektille tunnistettiin jotkut avainkohdat käyttämällä erilaisia algoritmeja. Tässä opetusohjelmassa aiomme käyttää näitä algoritmeja todellisten esineiden havaitsemiseen, tässä käytämme SIFT ja ORB havaitsemiseen.
Kohteen tunnistus SIFT: n avulla
Tässä kohteen tunnistus tehdään live webcam -virralla, joten jos se tunnistaa objektin, se mainitsisi löydetyn objetin. Koodissa pääosan toistaa toiminto, jota kutsutaan SIFT-ilmaisimeksi, suurin osa prosessoinnista tapahtuu tällä toiminnolla.
Ja koodin toisella puoliskolla aloitamme verkkokameravirran avaamisen ja lataamme sitten kuvamallin, ts. Viitekuvan, toisin sanoen ohjelma etsii verkkokameravirtaa.
Seuraavaksi siepataan jatkuvasti kuvia verkkokameravirrasta ääretön silmukka -toiminnon avulla ja siepataan sitten vastaava verkkokamerakehyksen korkeus ja leveys ja määritetään sen jälkeen kiinnostavan alueen (ROI) laatikon parametrit, jossa esineemme mahtuu ottamaan vastaavan korkeuden ja leveyden verkkokameran kehyksestä. Ja sitten piirrämme suorakulmion yllä määritellyistä ROI-parametreista. Rajaa sitten suorakulmio lopuksi ulos ja syötä se SWIFT-ilmaisimen koodiosaan.
Nyt SIFT-ilmaisimessa on pohjimmiltaan kaksi tuloa, yksi on rajattu kuva ja toinen on aiemmin määritelty kuvamalli, ja sitten se antaa meille osumia, joten ottelut ovat periaatteessa rajattuun kuvaan samankaltaisten objektien tai avainkohtien lukumäärä ja kohdekuvan. Määritämme sitten vastaavuuksille kynnysarvon, jos osumien arvo on suurempi kuin kynnysarvo, laitamme ruudullemme löydetyn kuvan ROI-suorakulmion vihreällä värillä.
Siirrytään nyt takaisin koodin pääosaan, toimintoon, jota kutsutaan SIFT-ilmaisimeksi, se ottaa syötteen kahtena kuvana, joista yksi on kuva, josta se etsii objektia ja toinen on kohde, jota yritämme sovittaa kohtaan (kuvamalli). Sitten harmaasävyinen ensimmäinen kuva ja määritä kuvamalli toiseksi kuvaksi. Sitten luomme SIFT-ilmaisinobjektin ja suoritamme OpenCV SIFT -tunnistus- ja laskutoiminnon avainkohtien havaitsemiseksi ja deskriptorien laskemiseksi, kuvaajat ovat pohjimmiltaan vektoreita, jotka tallentavat tiedot avainpisteistä, ja se on todella tärkeää, kun teemme sovituksen kuvien kuvaajien välillä.
Ja määritä sitten FLANN-pohjainen sovitin, emme aio matemaattista teoriaa yhteensopivuudesta sen takana, mutta voit helposti Googlella siitä. Määritä ensin hakemisto kdtree nollaksi ja sitten asetamme hakemisto- ja hakuparametrit sanakirjamuodossa, määritämme vain algoritmin, jota aiomme käyttää, joka on KDTREE, ja käytettävien puiden määrän, sitä enemmän puuta käytämme sitä monimutkaisempaa, mitä se saa ja hitaammin. Ja määritä hakuparametrissa tarkastusten määrä, joka on pohjimmiltaan suoritettavien vastaavuuksien määrä.
Ja luo sitten FLANN-pohjainen matcher-objekti lataamalla aiemmin määrittelemämme parametri, jotka ovat hakemistoparametreja ja hakuparametreja, ja luo tämän perusteella FLANN-pohjainen matcher, joka on KNN-sovitin, jossa KNN on K-lähimmät naapurit, pohjimmiltaan se on tapa, jossa etsimme lähimpiä sovittimia ja kuvaajia ja teemme sovituksen alustusvakion k kanssa. Nyt tämä FLANN-pohjainen ottelija palauttaa saamiemme otteluiden määrän.
FLANN-pohjainen vastaavuus on vain arvio, joten FLANN-pohjaisen ottelijan tarkkuuden lisäämiseksi suoritamme Lowen suhdetestin, ja mitä se tekee, se etsii ottelut knn-flannipohjaisesta sovittimesta ja määrittelee joitain matriisiparametreja, jotka ovat tässä etäisyyttä, jonka etäisyys on numpy-funktio, ja kun se täyttää kriteerit, liitä ottelut hyviin otteluihin ja palauttaa löydetyt hyvät ottelut, joten live-videovirta kertoo näytön kulmasta löydettyjen vastaavuuksien määrän.
Tarkastellaan nyt yllä olevan kuvauksen koodia:
tuo cv2 tuonti numero np def sift_detector (new_image, image_template): # Toiminto, joka vertaa syötettyä kuvaa malliin # Se palauttaa sitten niiden välisten SIFT-vastaavuuksien määrän image1 = cv2.cvtColor (new_image, cv2.COLOR_BGR2GRAY) image2 = image_template # Luo SIFT-ilmaisinobjekti #sift = cv2.SIFT () sift = cv2.xfeatures2d.SIFT_create () # Hanki avainpisteet ja kuvaajat käyttämällä SIFT- avainpisteitä_1, deskriptoreita_1 = sift.detectAndCompute (kuva1, Ei mitään) avainkohtia_2, deskriptorit2 = Siirtää.detailia Ei mitään) # Määritä parametrit Flann Matcherillemme FLANN_INDEX_KDTREE = 0 index_params = dict (algoritmi = FLANN_INDEX_KDTREE, puut = 3) search_params = dict (tarkastukset = 100) # Luo Flann Matcher esine Flann = cv2.FlannBasedMatcher (index_params, search_params) # Hanki ottelunsa käyttäen K-lähimmän naapurin menetelmä # tulos 'matchs' on määrä vastaavia löydetyt molemmissa kuvissa tulitikut = flann.knnMatch (descriptors_1, descriptors_2, k = 2) # Säilytä hyvät ottelut käyttämällä Lowen suhdetestiä good_matches = m: lle, n otteluissa: jos m.distance <0,7 * n.distance: good_matches.append (m) return len (good_matches) cap = cv2.VideoCapture (0) # Lataa kuvamallimme , tämä on viitekuva image_template = cv2.imread ('phone.jpg', 0), kun taas True: # Hanki verkkokamerakuvia ret, frame = cap.read () # Hanki verkkokameran kehyksen korkeus ja leveys, width = frame.shape # Määritä ROI-laatikon mitat top_left_x = int (width / 3) top_left_y = int ((height / 2) + (height / 4)) bottom_right_x = int ((width / 3) * 2) bottom_right_y = int ((height / 2) - (height / 4)) # Piirrä suorakulmainen ikkuna mielenkiintoiselle alueellemme cv2. Suorakulmio (kehys, (top_left_x, top_left_y)), (bottom_right_x, bottom_right_y), 255, 3) # Yllä määritelty havainnoinnin rajausikkuna rajattu = kehys # Käännä kehyksen suunta vaakasuunnassa kehys = cv2.flip (kehys, 1) # Hae SIFT-osumien määrä = sift_detector (rajattu, image_template) # Näytä tilamerkkijono, joka näyttää nykyisen nro. otteluista cv2.putText (kehys, str (ottelut), (450,450), cv2.FONT_HERSHEY_COMPLEX, 2, (0,255,0), 1) # Kynnyksemme osoittaa kohteen havaitseminen # Käytämme 10, koska SIFT-ilmaisin palauttaa vähän vääriä positioita kynnysarvo = 10 # Jos osumat ylittävät kynnyksemme, objekti on havaittu, jos osumat> kynnys: cv2.suorakulmio (kehys, (ylä_vasen_x, ylä_vasen_y), (alempi_oikea_x, alempi_oikea_y), (0,255,0), 3) cv2.putText (kehys), 'Object Found', (50,50), cv2.FONT_HERSHEY_COMPLEX, 2, (0,255,0), 2) cv2.imshow ('SIFT: tä käyttävä objektinilmaisin', kehys) if cv2.waitKey (1) == 13: # 13 on Enter-näppäintä tauko cap.release () cv2.destroyAllWindows ()
Kohteen tunnistus ORB: llä
Kohteen havaitseminen SIFT: n avulla on melko siistiä ja tarkka, koska se tuottaa paljon tarkkoja vastaavuuksia avainkohtien perusteella, vaikka se onkin patentoitu ja mikä vaikeuttaa sen käyttöä kaupallisissa sovelluksissa, toinen ulospääsy tähän on ORB-algoritmi esineiden havaitsemiseen.
Samoin kuin SIFT: n kohteiden havaitsemismenetelmässä, jossa jaoimme ohjelman kahteen osaan, samaa noudatetaan tässä.
Ensinnäkin määritellään funktio ORB_detector, joka vie kaksi tuloa, joista toinen on verkkokamerasta tuleva suora lähetyskuva ja toinen on kuvamalli, jonka perusteella aiomme sovittaa kuvamme. Sitten harmaasävytämme verkkokamerakuvamme ja alustamme sitten ORB-ilmaisimemme ja asetamme sen tähän 1000 avainpisteeseen ja skaalausparametreihin 1,2. voit helposti leikkiä näiden parametrien kanssa, sitten tunnistaa avainkohdat (kp) ja kuvaajat (des) molemmille kuville ja toinen parametri, jonka määrittelemme detektionANDCompute- toiminnossa ei ole, se vaatii kuvan peitteen käyttöä tai ei kiistämme sen täällä.
Siirry sitten ilmaisimeen, jossa olemme aiemmin käyttäneet FLANN-pohjaista sovitinta, mutta tässä käytämme BFMatcheria ja BFMatcherin sisällä määritämme kaksi parametria, joista yksi on NORM_HAMMING ja toinen on crossCheck, jonka arvo on TOSI.
Laske sitten näiden kahden kuvan väliset vastaavuudet käyttämällä yllä määriteltyjä kuvaajia, mikä palauttaa vastaavuuksien määrän, koska nämä ottelut eivät ole likiarvoja, joten Lowen suhdetestiä ei tarvitse tehdä, vaan lajitellaan ottelut etäisyyden perusteella, vähintään etäisyys enemmän ottelu on parempi (tässä etäisyys tarkoittaa etäisyyttä pisteiden välillä), ja lopussa palautamme otteluiden lukumäärän pituusfunktiolla.
Ja päätoiminnossa asetamme kynnyksen paljon korkeammalle arvolle, koska pallodetektori tuottaa paljon melua.
Katsotaan nyt koodia ORB-pohjaiseen havaitsemiseen
tuo cv2 tuontinumero numerona def def ORB_detector (new_image, image_template): # Funktio, joka vertaa syötettyä kuvaa malliin # Se palauttaa sitten ORB-vastaavuuksien määrän niiden välillä image1 = cv2.cvtColor (new_image, cv2.COLOR_BGR2GRAY) # Luo ORB-ilmaisin 1000 avainkohtaa, joiden skaalauspyramidikerroin on 1,2 orb = cv2.ORB_create (1000, 1.2) # Tunnista alkuperäisen kuvan avainkohdat (kp1, des1) = orb.detectAndCompute (image1, None) # Tunnista käännetyn kuvan avainkohdat (kp2, des2) = orb.detectAndCompute (image_template, None) # Luo ottelija # Huomaa, että emme enää käytä Flannbased-vastaavuuksia bf = cv2.BFMatcher (cv2.NORM_HAMMING, crossCheck = True) # Tee vastaavat ottelut = bf.match (des1, des2) # Lajittele ottelut etäisyyden perusteella. Pienin etäisyys # on parempi ottelu = lajiteltu (ottelut, avain = lambda val: val.distance) paluu len (vastaa) cap = cv2.VideoCapture (0) # Lataa kuvamallimme , tämä on viitekuva image_template = cv2.imread ('phone.jpg', 0) # image_template = cv2.imread ('images / kitkat.jpg', 0), kun taas True: # Hanki verkkokamerakuvat uudestaan, frame = cap.read () # Hanki verkkokameran kehyksen korkeus ja leveys , width = frame.shape # Määritä ROI-laatikon mitat (Huomaa, että joidenkin näistä asioista tulisi olla silmukan ulkopuolella) top_left_x = int (width / 3) top_left_y = int ((height / 2) + (height / 4)) bottom_right_x = int ((width / 3) * 2) bottom_right_y = int ((height / 2) - (height / 4)) # Piirrä suorakulmainen ikkuna mielenkiintoinen alue cv2.suorakulmio (kehys, (ylä_vasen_x, ylä_vasen_y), (ala_oikea_x, ala_oikea_y), 255, 3) # Edellä määritelty havainnoinnin rajausikkuna rajattu = kehys # Käännä kehyksen suunta vaakasuunnassa = cv2.flip (kehys, 1) # Hae ORB-osumien lukumäärä = ORB_detector (rajattu, image_template) # Näytä tilamerkkijono, joka näyttää nykyisen nro. otteluista output_string = "Ottelut =" + str (vastaa) cv2.putText (kehys, output_string, (50,450), cv2.FONT_HERSHEY_COMPLEX, 2, (250,0150), 2) # Meidän kynnys ilmoittaa esineen deteciton # Uusien kuvien tai vaalentamiseen olosuhteissa ehkä jonkin verran kokeilemaan # Huom ORB ilmaisin saada alkuun 1000 ottelut, 350 on lähinnä min 35% ottelu kynnys = 250 # Jos ottelut ylittämään kynnys, sitten objekti on havaittu, jos se vastaa> kynnys: cv2.suorakulmio (kehys, (ylä_vasen_x, ylä_vasen_y), (ala_oikea_x, alaosa_oikea_y), (0,255,0), 3) cv2.putText (kehys, 'objekti löydetty', (50, 50), cv2.FONT_HERSHEY_COMPLEX, 2, (0,255,0), 2) cv2.imshow (Object Detector käyttäen ORB, frame) jos cv2.waitKey (1) == 13: # 13 on Enter-näppäintä tauko korkki.release () cv2.destroyAllWindows ()
Suunniteltujen kaltevuuksien histogrammi
Puhutaan nyt toisesta kuvaajasta, joka on suuntautuneiden kaltevuuksien histogrammi (HOG).
HOG: t ovat melko hienoja ja hyödyllisiä kuvaajia, ja niitä käytetään laajasti ja menestyksekkäästi esineiden havaitsemiseen, kuten aiemmin nähtiin kuvakuvaajat, kuten SIFT ja ORB, joissa meidän on laskettava avainkohdat ja sitten laskettava kuvaimet näistä avainkohdista, HOG: t tekevät tämän prosessin eri tavalla. Se edustaa objekteja yhtenä ominaisuusvektorina, toisin kuin joukko ominaisuusvektoreita, joissa kukin edustaa kuvan osaa. Se tarkoittaa, että meillä on yksi vektoriominaisuus koko kuvalle.
Se lasketaan liukuvan ikkunan ilmaisimen avulla kuvan päälle, jossa HOG-kuvaaja lasketaan kullekin sijainnille. Ja sitten kukin sijainti yhdistetään yhdeksi ominaisuusvektoriksi.
Kuten SIFT, kuvan mittakaava säädetään pyramidilla.
Aikaisemmin olemme käyttäneet vastaavuuksia, kuten FLANN ja BFMatcher, mutta HOG: t tekevät sen eri tavalla SVM (support vector machine) -luokittelijoiden avulla, jolloin kukin laskettu HOG-kuvaaja syötetään SVM-luokittelijaan sen selvittämiseksi, löydettiinkö objekti vai ei.
Tässä on linkki Dalal & Triggsin loistavaan artikkeliin HOG: iden käytöstä ihmisen havaitsemiseen:
Suuntautuneiden liukuvärien histogrammi, askel askeleelta:
HOG: n ymmärtäminen voi olla melko monimutkaista, mutta tässä käsittelemme vain HOG: n teoriaa menemättä syvemmälle siihen liittyvään matematiikkaan.
Otetaan siis tämä kuva, joka on hieman pikseloitu, ja yläkulmassa on tässä 8x8 pikselin laatikko, joten tässä laatikossa lasketaan jokaisen pikselin gradienttivektori tai reunan suunta. Joten tämä tarkoittaa, että tässä ruudussa lasketaan laatikon sisällä olevien pikselien kuvan gradienttivektori (ne ovat eräänlainen kuvan intensiteetin suunta tai virtaus), ja tämä tuottaa 64 (8 x 8) gradienttivektoria, jotka esitetään sitten histogrammina. Joten kuvittele histogrammi, joka edustaa kutakin gradienttivektoria. Joten jos kaikki pisteet tai intensiteetit valehtelevat yhteen suuntaan, sen suunnan histogrammin sanotaan 45 astetta, histogrammin huippu olisi 45 astetta.
Joten mitä teemme nyt, jaamme jokaisen solun kulmasäiliöiksi, joissa kukin alusta vastaa kaltevuuden suuntaa (esim. X, y). Dalal- ja Triggs-papereissa he käyttivät 9 astiaa 0-180 ° (20 ° kukin bin). Tämä vähentää tehokkaasti 64 vektoria vain 9 arvoon. Joten mitä olemme tehneet, on pienennetty kokoa, mutta säilyttänyt kaikki tarvittavat avaintiedot.
Seuraava vaihe sian laskemisessa on normalisointi, normalisoimme kaltevuudet varmistaaksemme muuttumattomuuden valaistuksen muutoksiin eli kirkkauteen ja kontrastiin.
Tässä kuvassa intensiteettiarvot näytetään neliössä kulloisenkin suunnan mukaan, ja kaikilla on 50 eroa toistensa välillä
∆ H = 50, ∆ v = 50; │∆│ = √50 2 +50 = 70,72, 70,72 / 100 = 0,707
Jaamme vektorit gradienttisuureilla, jotka saamme kaikille 0,707, tämä on normalisointi.
Samoin, jos muutamme intensiteettiä tai kontrastia, saadaan alla olevat arvot.
∆ 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
Normalisointi ei tapahdu solutasolla, vaan se tapahtuu lohkotasolla, joten tässä lohkot ovat pohjimmiltaan 4 solun ryhmä, tämä ottaa huomioon naapurilohkot, jotka normalisoituvat samalla kun otetaan huomioon kuvan suuremmat segmentit.
Katsotaan nyt koodia
tuo numerotiedosto np: ksi tuonti cv2 tuo matplotlib.pyplot plt-tiedostona # Lataa kuva ja sitten harmaasävy image = cv2.imread ('elephant.jpg') harmaa = cv2.cvtColor (kuva, cv2.COLOR_BGR2GRAY) # Näytä alkuperäinen kuva cv2.imshow (' Syöttökuva ', kuva) cv2.waitKey (0) #parametrien, solun koon ja lohkon koon määrittäminen # hxw pikseleinä cell_size = (8, 8) # hxw soluissa block_size = (2, 2) # suuntaussäiliöiden lukumäärä nbins = 9 # OpenCV: n HOG- kuvaajan käyttö # winSize on kuvan koko, joka on rajattu solun koon monikertaan hog = cv2.HOGDescriptor (_winSize = (harmaa.muoto // solukoko * solukoko, grey.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) # Luomme numerosarjan muodon luoda hog_features n_cells = (harmaa.muoto // solukoko, harmaa.muoto // solukoko) # Indeksoimme lohkot ensin riveittäin. # hog_feats sisältää nyt gradienttiamplitudit kullekin suunnalle, # ryhmän jokaiselle solulle kullekin ryhmälle. Indeksointi tapahtuu riveittäin ja sarakkeittain. hog_feats = hog.compute (harmaa).reshape (n_cells - block_size + 1, n_cells - block_size + 1, block_size, block_size, nbins).transpose ((1, 0, 2, 3, 4)) # Luo gradienttitaulukko, jossa on nbin-mitat, jotta voit tallentaa gradienttisuuntaukset gradientit = np.zeros ((n_cells, n_cells, nbins)) # Luo taulukko dimensiot cell_count = np.full ((n_cells, n_cells, 1), 0, dtype = int) # Lohkon normalisointi off_y-alueella (lohkon koko): off_x-alueella (lohkon koko): kaltevuudet - lohkon koko + pois_y + 1, pois_x: n_kennot - lohkon koko + pois_x + 1] + = \ hog_feats solujen määrä - lohkon koko + pois_y + 1, off_x: n_cells - block_size + off_x + 1] + = 1 # Gradienttien keskimääräiset kaltevuudet / = cell_count # Piirrä Matplotlibiä käyttävät HOGit # kulma on 360 / nbins * suunta color_bins = 5 plt. väri (liukuvärit) plt.gca (). invert_yaxis () plt.gca (). set_aspect ('sama', säädettävä = 'laatikko') plt.colorbar () plt.show () cv2.destroyAllWindows ()
Kuva näyttää kuinka tulokuva näkyy HOG-esityksenä.
HAAR-kaskadiluokituslaitteet
Kuten aiemmin keskusteltiin, voimme poimia ominaisuuksia kuvasta ja käyttää niitä ominaisuuksien luokittelemiseen tai havaitsemiseen.
Mitä ovat HAAR-kaskadiluokittelijat?
Kohteen havaitsemismenetelmä, joka syöttää Haarin ominaisuudet luokittelusarjaan (kaskadi) kuvassa olevien esineiden tunnistamiseksi. Heidät koulutetaan tunnistamaan yhden tyyppinen esine, mutta voimme käyttää useita niistä rinnakkain, esimerkiksi havaita silmät ja kasvot yhdessä.
HAAR-luokittelijat selittävät:
HAAR-luokittelijat koulutetaan käyttämällä paljon positiivisia kuvia (eli kuvia, joissa on esine) ja
negatiivisia kuvia (eli kuvia, joissa ei ole esinettä).
Kun olemme saaneet nuo kuvat, poimimme ominaisuudet käyttämällä suorakaiteen muotoisten lohkojen liukuvia ikkunoita. Nämä ominaisuudet (HAAR-ominaisuudet) ovat yksittäisiä ja ne lasketaan vähentämällä mustien suorakulmioiden valkoisten suorakulmioiden alla olevien pikselien voimakkuuksien summa.
Tämä on kuitenkin naurettava määrä laskelmia, jopa 24 x 24 pikselin perusikkunalle (180 000 ominaisuutta luotu).
Joten tutkijat suunnittelivat menetelmän nimeltä Integral Images, joka laski tämän neljällä matriisiviitteellä. Niillä oli kuitenkin vielä 180 000 ominaisuutta, ja suurin osa niistä ei tuonut mitään todellista arvoa.
Tehostusta käytettiin sitten informatiivisimpien ominaisuuksien määrittämiseen Freund & Schapiren AdaBoostin avulla ja se löysi kuvasta eniten informatiivisia ominaisuuksia. Tehostaminen on prosessi, jossa käytämme heikkoja luokittelijoita vahvojen luokittelijoiden rakentamiseen yksinkertaisesti määrittelemällä ankarampia painotettuja rangaistuksia virheellisistä luokituksista. Pienennetään 180 000 ominaisuutta 6000: een, mikä on silti melko vähän ominaisuuksia.
Niissä 6000 ominaisuudessa jotkut ovat informatiivisempia kuin toiset. Joten jos käytimme kaikkein informatiivisimpia ominaisuuksia tarkistaaksemme ensin, onko alueella mahdollisesti kasvot (väärät positiiviset eivät ole iso juttu). Näin poistetaan tarve laskea kaikki 6000 ominaisuutta kerralla. Tätä konseptia kutsutaan luokittelijoiden kaskadiksi - kasvojen havaitsemiseen Viola Jones -menetelmä käytti 38 vaihetta.
Kasvojen ja silmien tunnistus
Joten saatuamme jonkin verran teoreettista tietoa HAAR-kaskadeista, aiomme toteuttaa sen lopullisesti, jotta asiat olisivat melko selkeät, hajotamme oppitunnit osittain, ensin havaitsemme etupinnan, jonka jälkeen siirrymme havaitsemaan etupuolet silmät ja lopulta tekisimme suoran kasvojen ja silmien havaitsemisen verkkokameran kautta.
Joten aiomme käyttää ennalta koulutettuja luokittelijoita, jotka OpenCV on toimittanut.xml-tiedostoina, xml tarkoittaa laajennettavaa merkintäkieliä, tätä kieltä käytetään valtavan määrän tietojen tallentamiseen, voit jopa rakentaa siihen tietokannan.
Voit käyttää näitä luokittelijoita tällä linkillä .
Kasvojentunnistus
Yritetään etupuolen kasvojentunnistusta, sinulla on pääsy etupään tunnistimen kaskadiin täällä. Pura vain zip-tiedosto saadaksesi xml-tiedoston.
import numpy as np import cv2 # Osoitamme OpenCV: n CascadeClassifier-toiminnon kohtaan, johon # luokittelijamme (XML-tiedostomuoto) on tallennettu, muista pitää koodi ja luokittelija samassa kansiossa face_cascade = cv2.CascadeClassifier ('haarcascade_frontalface_default.xml') # Lataa kuvamme sitten muuntaa sen harmaasävykuvaksi = cv2.imread ('Trump.jpg') harmaa = cv2.cvtColor (kuva, cv2.COLOR_BGR2GRAY) # Luokittelijamme palauttaa havaitun kasvon ROI: n dupleksina # Se tallentaa vasemman yläkulman koordinaatti ja oikean alakulman koordinaatit # se palauttaa luettelon luetteloista, jotka ovat havaittujen eri kasvojen sijainti. kasvot = face_cascade.detectMultiScale (harmaa, 1.3, 5) # Kun kasvoja ei havaittu, face_classifier palaa ja tyhjä sarake, jos kasvot ovat (): print ("Ei kasvoja löytynyt") # Me iteroimme kasvojemme läpi ja piirrämme suorakulmion # jokaisen kasvon yli kasvoille (x, y, w, h) kasvoissa: cv2.suorakulmio (kuva, (x, y), (x + w, y + h), (127,0255), 2) cv2.imshow ('Kasvojentunnistus', kuva) cv2.waitKey (0) cv2.destroyAllWindows ()
Yhdistetään nyt kasvojen ja silmien tunnistus yhdessä. Sinulla on pääsy silmätunnistimen kaskadiin samassa zip-tiedostossa.
tuo numerotiedosto nimellä np tuonti cv2 face_classifier = cv2.CascadeClassifier ('haarcascade_frontalface_default.xml') eye_classifier = cv2.CascadeClassifier ('haarcascade_eye.xml') img = cv2.imread ('Trump.jpgc) im cv2.COLOR_BGR2GRAY) kasvot = face_classifier.detectMultiScale (harmaa, 1.3, 5) # Jos kasvoja ei havaittu, face_classifier palaa ja tyhjä sarake, jos kasvot ovat (): print ("Ei kasvoja löytynyt") (x, y, w, h)) kasvoissa: cv2.suorakulmio (img, (x, y), (x + w, y + h), (127,0255), 2) cv2.imshow ('img', img) roi_gray = harmaa roi_color = img silmät = eye_classifier.detectMultiScale (roi_gray) cv2.waitKey (0 ) silmille (ex, ey, ew, eh) silmissä: cv2. suorakulmio (roi_color, (ex, ey), (ex + ew, ey + eh), (255,255,0), 2) cv2.imshow ('img', img) cv2.waitKey (0) cv2.destroyAllWindows () cv2.waitKey (0)
Joten tämä koodi on sama kuin kasvojentunnistuskoodi, mutta tässä on lisätty silmien kaskadeja ja menetelmä niiden havaitsemiseksi, kuten näette, olemme valinneet kasvojen harmaasävyisen version parametriksi detectMultiScale for silmät, mikä vie meidät laskennan vähenemiseen, koska aiomme havaita silmät vain tällä alueella.
Live kasvojen ja silmien tunnistus
Joten tähän asti olemme tehneet kasvojen ja silmien tunnistuksen, nyt toteutetaan sama web-kameran suoran videovirran kanssa. Tässä teemme saman kasvojen ja silmien havaitsemisen, mutta tällä kertaa teemme sen web-kameran suoratoistoa varten. Suurimmassa osassa sovellusta kasvosi on korostettu laatikolla sen ympärillä, mutta täällä olemme tehneet jotain toisin, että huomaat kasvosi leikatun ja silmät tunnistavat vain siinä.
Joten tässä tuomme sekä kasvojen että silmien luokittelijan ja määritimme toiminnon kaiken prosessoinnin suorittamiseksi kasvojen ja silmien havaitsemiseksi. Ja sen jälkeen alkoi verkkokameravirta ja kutsui kasvojentunnistintoiminnon kasvojen ja silmien havaitsemiseksi. Parametri, jonka määrittelemme kasvojentunnistimen sisällä, ovat jatkuvan kuvan suorasta verkkokameravirrasta
tuo cv2 tuonti numero nimellä np face_classifier = cv2.CascadeClassifier ('haarcascade_frontalface_default.xml') eye_classifier = cv2.CascadeClassifier ('haarcascade_eye.xml') def face_detector (img, size = 0.5 cvv tai muuntaa kuvan muuttamaan (img, cv2.COLOR_BGR2GRAY) kasvot = face_classifier.detectMultiScale (harmaa, 1.3, 5), jos kasvot ovat (): palauta img arvolle (x, y, w, h) kasvoille: x = x - 50 w = w + 50 y = y - 50 h = h + 50 cv2. suorakulmio (img, (x, y), (x + w, y + h), (255,0,0), 2) roi_gray = harmaa roi_color = img silmät = eye_classifier.detectMultiScale (roi_gray) for (ex, ey, ew, eh) silmissä: cv2. suorakulmio (roi_color, (ex, ey), (ex + ew, ey + eh), (0,0,255), 2) roi_color = cv2.flip (roi_color, 1) paluu roi_color cap = cv2.VideoCapture (0) vaikka totta: evp, runko = cap.read () cv2.imshow ('kasvot Linko', face_detector (frame)) jos cv2.waitKey (1) == 13: # 13 on Enter-näppäintä tauko cap.release () cv2.destroyAllWindows ()
Cascade-luokittelijoiden viritys
Muun detectMultiScale-laitteen sisällä määritetyillä parametreilla kuin tulokuvalla on seuraava merkitys
meidän luokittelija. detectMultiScale (syöttökuva, mittakaavan tekijä, vähäiset naapurit)
- Skaalakerroin Määrittää, kuinka paljon pienennämme kuvan kokoa joka kerta kun skaalaamme. Esimerkiksi kasvojentunnistuksessa käytämme tyypillisesti 1.3. Tämä tarkoittaa, että pienennämme kuvaa 30% joka kerta, kun se skaalataan. Pienempien arvojen, kuten 1.05, laskeminen kestää kauemmin, mutta lisää havaitsemisnopeutta.
- Pienet naapurit Määrittää naapureiden määrän, jonka jokaisella mahdollisella ikkunalla pitäisi olla, jotta sitä voidaan pitää positiivisena havaintona. Tyypillisesti asetettu välillä 3-6. Se toimii herkkyysasetuksena, matalat arvot havaitsevat joskus useita kasvoja yhden kasvon yli. Korkeat arvot takaavat vähemmän vääriä positiivisia tuloksia, mutta saatat menettää joitain kasvoja.
Autojen ja jalankulkijoiden havaitseminen videoissa
Nyt havaitsemme videoista jalankulkijat ja autot HAAR-kaskadeilla, mutta jos videota ei ladata ja koodi kääntyy ilman virheitä, sinun on noudatettava seuraavia vaiheita:
Jos video ei kuormia juoksun jälkeen koodia, voit joutua kopioimaan meidän opencv_ffmpeg.dl alkaen : OpenCV \ lähteet \ 3rdparty \ ffmpeg liitä se missä python on sijoitettu esimerkiksi C: \ Anaconda2
Kun se on kopioitu, sinun on nimettävä tiedosto uudelleen käyttämäsi OpenCV-version mukaan. Eg, jos käytät OpenCV 2.4.13, nimeä tiedosto uudelleen nimellä: opencv_ffmpeg2413_64.dll tai opencv_ffmpeg2413.dll (jos olet X86-koneella) opencv_ffmpeg310_64.dll tai opencv_ffmpeg310.dll (jos käytät X86-konetta)
Jos haluat selvittää, missä python.exe on asennettu, suorita vain nämä kaksi koodiriviä, se tulosta pythonin asennuksen sijainnin.
tuo sys- tulostus (sys.exe)
Jos olet nyt suorittanut nämä vaiheet onnistuneesti, siirrymme jalankulkijoiden havaitsemiskoodiin, Voit saada kaskadin jalankulkijoiden havaitsemiseen ja täältä liitettyyn zip-tiedostoon.
import cv2 import numpy as np # Luo kehon luokittelija body_classifier = cv2.CascadeClassifier ('haarcascade_fullbody.xml') # Aloita videotiedoston sieppaus, tässä käytämme videotiedostoa, jossa jalankulkijat havaittaisiin cap = cv2.VideoCapture ('walking.avi') # Silmukka, kun video ladataan onnistuneesti, kun cap.isOpened (): # Luemme videon jokaisen kehyksen ret, frame = cap.read () # tässä muutamme kehyksen kokoa puoleen sen koosta, nopeutamme luokittelua # koska suuremmissa kuvissa on paljon enemmän ikkunoita, joiden yli voi liukua, joten yleisesti ottaen pienennämme tarkkuutta Videon # puolikkaasta 0,5 tarkoittaa, ja käytämme myös nopeampaa interpolointimenetelmää, joka on #interlinear frame = cv2.resize (frame, None, fx = 0.5, fy = 0.5, interpolation = cv2.INTER_LINEAR) harmaa = cv2. cvtColor (kehys, cv2.COLOR_BGR2GRAY) # Siirrä keho vartaloluokittelijamme elimille = body_classifier.detectMultiScale (harmaa, 1.2, 3) # Pura rajoituslaatikot elimille, jotka on tunnistettu (x, y, w, h) rungoissa: cv2. suorakulmio (kehys, (x, y), (x + w, y + h), (0, 255, 255), 2) cv2.imshow ('Jalankulkijat', kehys) if cv2.waitKey (1) == 13: # 13 on Enter Key break cap. Release () cv2.destroyAllWindows ()
Kun olemme onnistuneesti havainneet jalankulkijan videossa, siirrymme auton tunnistuksen koodiin. Voit saada jalankulkijoiden havainnoinnin kaskadin täältä.
tuonti CV2 tuonti aikaan tuonti numpy NP # Luo kehomme luokittelija car_classifier = cv2.CascadeClassifier ('haarcascade_car.xml') # Aloita videokuvaus videotiedoston korkki = cv2.VideoCapture ('cars.avi') # Loop kun video on onnistunut ladattu, kun cap.isOpened (): time.sleep (.05) # Lue ensimmäinen kehys ret, kehys = cap.read () harmaa = cv2.cvtColor (kehys, cv2.COLOR_BGR2GRAY) # Siirrä kehys autoluokituksellemme autot = car_classifier.detectMultiScale (harmaa, 1.4, 2) # Pura rajoituslaatikot kaikille korille, jotka on tunnistettu (x, y, w, h) autoille: cv2.suorakulmio (kehys, (x, y), (x + w, y + h)), (0, 255, 255), 2) cv2.imshow ('Autot', kehys) jos cv2.waitKey (1) == 13: # 13 on Enter-näppäintä tauko cap.release () cv2.destroyAllWindows ()
Olet huomannut, että olemme lisänneet time.sleep (.05) , se on vain viive kehysnopeudessa, jotta voit vahvistaa, että kaikki autot on tunnistettu oikein, tai voit poistaa sen helposti lisäämällä siihen kommenttimerkin.
Tämä artikkeli on tarkoitettu Rajeev Ratanin luomaan Pythonin Master Computer Vision ™ OpenCV4 -kurssilla, jossa syvällistä oppimista käsittelevä Udemy-kurssi. Tilaa se saadaksesi lisätietoja Computer Visionista ja Pythonista.