koneellisesti luettavien vyöhykkeiden havaitseminen passikuvissa

mrz_output_04

tänään blogikirjoitus ei olisi mahdollista ilman PyImageSearch Gurus jäsen, Hans Boone. Hans työskentelee tietokonenäköprojektissa tunnistaakseen automaattisesti koneellisesti luettavat alueet (Mrzs) passikuvissa-aivan kuten yllä olevassa kuvassa havaittu alue.

passeissa tai matkakorteissa MRZ-alue jakautuu kahteen luokkaan: tyyppiin 1 ja tyyppiin 3. Tyypin 1 MRZ: t ovat kolme riviä, joista jokainen rivi sisältää 30 merkkiä. Tyypin 3 MRZ: ssä on vain kaksi riviä, mutta jokainen rivi sisältää 44 merkkiä. Kummassakin tapauksessa MRZ koodaa tietyn kansalaisen tunnistetiedot, mukaan lukien passin tyyppi, passin tunnus, myöntävä maa, nimi, kansalaisuus, viimeinen voimassaolopäivä jne.

PyImageSearch gurujen kurssilla Hans näytti minulle edistymisensä projektissa ja kiinnostuin heti. Olen aina halunnut soveltaa passikuviin tietokonenäköalgoritmeja (lähinnä huvin vuoksi), mutta siihen ei ollut aineistoa. Passin sisältämien henkilötunnistetietojen vuoksi en tietenkään voinut kirjoittaa aiheesta blogikirjoitusta ja jakaa kuvia, joita käytin algoritmin kehittämiseen.

onneksi Hans suostui jakamaan osan näytteistä/näytekuvista, joihin hänellä on pääsy — ja tartuin tilaisuuteen leikkiä näillä kuvilla.

nyt, ennen kuin päästään pitkälle, on tärkeää huomata, että nämä passit eivät ole ”todellisia” siinä mielessä, että ne voidaan yhdistää todelliseen ihmiseen. Mutta ne ovat aitoja passeja, jotka on luotu väärillä nimillä, osoitteilla jne. kehittäjille, joiden kanssa työskennellä.

voisi ajatella, että passin MRZ — alueen havaitsemiseen tarvitaan hieman koneoppimista, ehkä lineaarisen SVM + HOG-kehyksen avulla ”MRZ-ilmaisimen” rakentaminen-mutta se olisi liioittelua.

sen sijaan MRZ-tunnistus voidaan suorittaa vain kuvankäsittelyn perustekniikoilla, kuten puinnilla, morfologisilla operaatioilla ja ääriviivaominaisuuksilla. Tämän blogikirjoituksen loppuosassa kerron yksityiskohtaisesti oman näkemykseni siitä, miten näitä menetelmiä voidaan soveltaa passin MRZ-alueen havaitsemiseen.

Etsitkö lähdekoodia tähän viestiin?

siirry suoraan lataukset-osioon

koneellisesti luettavien vyöhykkeiden havaitseminen passikuvissa

mennään eteenpäin ja aloitetaan tämä projekti. Avaa uusi tiedosto, nimeä se detect_mrz.py ja lisää seuraava koodi:

# import the necessary packagesfrom imutils import pathsimport numpy as npimport argparseimport imutilsimport cv2# construct the argument parse and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-i", "--images", required=True, help="path to images directory")args = vars(ap.parse_args())# initialize a rectangular and square structuring kernelrectKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (13, 5))sqKernel = cv2.getStructuringElement(cv2.MORPH_RECT, (21, 21))

linjat 2-6 tuo tarvittavat paketit. Oletan, että sinulla on jo OpenCV asennettuna. Tarvitset myös imutils, my collection of convenience-toiminnot, jotta perus kuvankäsittelytoiminnot OpenCV: llä helpottuvat. Voit asentaa imutils käyttämällä pip :

$ pip install --upgrade imutils

sieltä rivit 9-11 käsittelevät komentoriviargumentin jäsentämistä. Tarvitsemme vain yhden kytkimen, --images, joka on polku hakemistoon, joka sisältää passikuvat, joita aiomme käsitellä.

lopuksi rivit 14 ja 15 alustavat kaksi ydintä, joita myöhemmin käytämme morfologisissa operaatioissa, erityisesti sulkuoperaatiossa. Toistaiseksi, yksinkertaisesti huomaa, että ensimmäinen ydin on suorakulmainen leveys noin 3x suurempi kuin korkeus. Toinen ydin on neliö. Näiden ytimien avulla voimme sulkea aukot MRZ-merkkien ja aukkojen välillä MRZ-viivojen välillä.

nyt kun komentoriviargumenttimme on jäsennetty, voimme aloittaa jokaisen datajoukon kuvan silmukoinnin ja käsitellä niitä:

# loop over the input image pathsfor imagePath in paths.list_images(args):# load the image, resize it, and convert it to grayscaleimage = cv2.imread(imagePath)image = imutils.resize(image, height=600)gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# smooth the image using a 3x3 Gaussian, then apply the blackhat# morphological operator to find dark regions on a light backgroundgray = cv2.GaussianBlur(gray, (3, 3), 0)blackhat = cv2.morphologyEx(gray, cv2.MORPH_BLACKHAT, rectKernel)

linjat 20 ja 21 lataavat alkuperäisen kuvan levyltä ja muuttavat sen maksimikorkeudeksi 600 pikseliä. Näet esimerkin alkuperäisestä kuvasta alla:

Kuva 1: alkuperäinen passikuva, jossa yritämme havaita MRZ: n.
Kuva 1: alkuperäinen passikuvamme, josta yritämme havaita MRZ: n.

Gaussin sumennusta käytetään linjalla 26 suurtaajuuskohinan vähentämiseksi. Sen jälkeen tehdään Mustahat-morfologinen operaatio sumeaan, harmaasävyiseen kuvaan rivillä 27.

mustahatunoperaattoria käytetään paljastamaan tummia alueita (eli MRZ-tekstiä) vaaleita taustoja (eli itse passin taustaa) vasten. Koska passiteksti on aina musta vaalealla pohjalla (ainakin tämän aineiston osalta), blackhat-operaatio on paikallaan. Alla näet tuotoksen soveltamalla blackhat operaattori:

kuva 2: Soveltamalla blackhat morfologinen operaattori paljastaa musta MRZ teksti vasten valoa passin Tausta.
kuva 2: Blackhatin morfologisen toimijan soveltaminen paljastaa mustan MRZ-tekstin vaaleaa passitaustaa vasten.

seuraava vaihe MRZ-tunnistuksessa on laskea mustahat-kuvan gradienttimagnitudiesitys Scharr-operaattorilla:

# compute the Scharr gradient of the blackhat image and scale the# result into the range gradX = cv2.Sobel(blackhat, ddepth=cv2.CV_32F, dx=1, dy=0, ksize=-1)gradX = np.absolute(gradX)(minVal, maxVal) = (np.min(gradX), np.max(gradX))gradX = (255 * ((gradX - minVal) / (maxVal - minVal))).astype("uint8")

tässä lasketaan Scharr-gradientti blackhat-kuvan x-akselia pitkin paljastaen kuvan alueet, jotka eivät ole ainoastaan tummia vaaleaa taustaa vasten, vaan sisältävät myös pystysuoria muutoksia gradientissä, kuten MRZ-tekstialue. Otamme tämän gradienttikuvan ja Skaalaamme sen takaisin alueelle käyttäen min / max-skaalausta:

kuva 3: Scharr-operaattorin soveltaminen Blackhat-kuvaan paljastaa alueet, jotka sisältävät voimakkaita pystysuoria muutoksia kaltevuudessa.
kuva 3: Scharr-operaattorin soveltaminen Blackhat-kuvaan paljastaa alueet, jotka sisältävät voimakkaita pystysuoria muutoksia kaltevuudessa.

vaikka ei ole täysin selvää, miksi käytämme tätä vaihetta, sanon, että se on erittäin hyödyllinen väärien positiivisten MRZ-havaintojen vähentämisessä. Ilman sitä voimme vahingossa merkitä passin koristellut tai suunnitellut alueet MRZ: ksi. Jätän tämän tehtäväksenne varmistaaksenne, että Blackhat-kuvan gradientin laskeminen voi parantaa MRZ-tunnistustarkkuutta.

seuraava vaihe on yrittää havaita MRZ: n todelliset viivat:

# apply a closing operation using the rectangular kernel to close# gaps in between letters -- then apply Otsu's thresholding methodgradX = cv2.morphologyEx(gradX, cv2.MORPH_CLOSE, rectKernel)thresh = cv2.threshold(gradX, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)

ensin tehdään sulkuoperaatio suorakulmaisen ytimen avulla. Sulkemisoperaation tarkoituksena on paikata MRZ-merkkien välisiä aukkoja. Sitten sovellamme thresholding Otsun menetelmällä automaattisesti kynnys kuvan:

Kuva 4: sovelletaan sulkuoperaatiota käyttämällä suorakulmaista ydintä (joka on leveämpi kuin korkea) MRZ-merkkien
Kuva 4: Soveltamalla sulkuoperaatiota, jossa käytetään suorakulmaista ydintä (joka on leveämpi kuin korkea) MRZ-merkkien

välisten aukkojen sulkemiseksi, kuten voimme nähdä yllä olevasta kuvasta, jokainen MRZ-viiva on läsnä kynnyskartassamme.

seuraava vaihe on sulkea varsinaisten viivojen väliset raot, jolloin saadaan yksi suuri suorakulmainen alue, joka vastaa MRZ: ää:

# perform another closing operation, this time using the square# kernel to close gaps between lines of the MRZ, then perform a# series of erosions to break apart connected componentsthresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, sqKernel)thresh = cv2.erode(thresh, None, iterations=4)

tässä suoritamme toisen sulkemisoperaation, tällä kertaa käyttäen neliöydintämme. Tätä ydintä käytetään MRZ: n yksittäisten rivien välisten aukkojen sulkemiseen, jolloin saadaan yksi suuri alue, joka vastaa MRZ: ää. Tämän jälkeen suoritetaan sarja eroosioita, jotka hajottavat toisiinsa kytkettyjä osia, jotka ovat saattaneet olla yhdistettyinä sulkemisoperaation aikana. Nämä eroosiot auttavat myös poistamaan pieniä möykkyjä, jotka eivät ole MRZ: n kannalta merkityksellisiä.

kuva 5: suoritetaan toinen sulkuoperaatio, tällä kertaa neliöydin yksittäisten MRZ-viivojen välisten aukkojen sulkemiseksi.
kuva 5: Suoritetaan toinen sulkuoperaatio, tällä kertaa neliöydin yksittäisten MRZ-viivojen välisten aukkojen sulkemiseksi.

joissakin passikuvauksissa passin raja on saattanut kiinnittyä MRZ-alueeseen sulkemisoperaatioiden aikana. Tämän korjaamiseksi asetamme 5% kuvan vasemmasta ja oikeasta reunasta nollaan (eli mustaan):

# during thresholding, it's possible that border pixels were# included in the thresholding, so let's set 5% of the left and# right borders to zerop = int(image.shape * 0.05)thresh = 0thresh - p:] = 0

rajanpoistomme tuotoksen näet alta.

kuva 6: asetetaan 5% vasemman ja oikean rajapinnan pikseleistä nollaan varmistaen, ettei MRZ-alue ole kiinnitettynä passin skannattuun marginaaliin.
kuva 6: asetetaan 5% vasemman ja oikean rajapinnan pikseleistä nollaan varmistaen, ettei MRZ-alue ole kiinnitettynä passin skannattuun marginaaliin.

verrattuna yllä olevaan kuvioon 5, voi nyt nähdä, että raja on poistettu.

viimeinen vaihe on löytää ääriviivat kuvastamme ja käyttää ääriviivaominaisuuksia MRZ: n tunnistamiseen:

# find contours in the thresholded image and sort them by their# sizecnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)cnts = imutils.grab_contours(cnts)cnts = sorted(cnts, key=cv2.contourArea, reverse=True)# loop over the contoursfor c in cnts:# compute the bounding box of the contour and use the contour to# compute the aspect ratio and coverage ratio of the bounding box# width to the width of the image(x, y, w, h) = cv2.boundingRect(c)ar = w / float(h)crWidth = w / float(gray.shape)# check to see if the aspect ratio and coverage width are within# acceptable criteriaif ar > 5 and crWidth > 0.75:# pad the bounding box since we applied erosions and now need# to re-grow itpX = int((x + w) * 0.03)pY = int((y + h) * 0.03)(x, y) = (x - pX, y - pY)(w, h) = (w + (pX * 2), h + (pY * 2))# extract the ROI from the image and draw a bounding box# surrounding the MRZroi = image.copy()cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)break# show the output imagescv2.imshow("Image", image)cv2.imshow("ROI", roi)cv2.waitKey(0)

rivillä 56-58 laskemme kuvamme ääriviivat (eli ääriviivat). Sitten otamme nämä ääriviivat ja lajittelemme ne niiden koon perusteella alenevassa järjestyksessä rivillä 59 (mikä tarkoittaa, että suurimmat ääriviivat ovat ensimmäisenä luettelossa).

linjalla 62 alamme silmukoida lajiteltuja ääriviivojamme. Kullekin ääriviivoille laskemme rajauslaatikon (rivi 66) ja käytämme sitä laskemaan kahta ominaisuutta: kuvasuhdetta ja peittosuhdetta. Kuvasuhde on yksinkertaisesti rajauslaatikon leveys jaettuna korkeudella. Peittävyyssuhde on rajauskentän leveys jaettuna varsinaisen kuvan leveydellä.

näiden kahden ominaisuuden avulla voimme tarkistaa riviltä 72, tutkimmeko MRZ-aluetta. MRZ on suorakulmainen, jonka leveys on paljon suurempi kuin korkeus. MRZ: n pitäisi myös kattaa vähintään 75% syötetystä kuvasta.

jos nämä kaksi tapausta pitävät, rivit 75-84 käyttävät rajauslaatikon (x, y)-koordinaatteja MRZ: n purkamiseen ja rajauslaatikon piirtämiseen syötekuvastamme.

lopulta rivit 87-89 näyttävät tuloksemme.

tulokset

jos haluat nähdä MRZ-ilmaisimen toiminnassa, suorita seuraava komento:

$ python detect_mrz.py --images examples

alla on esimerkki onnistuneesta MRZ-tunnistuksesta, jossa MRZ on hahmoteltu vihreällä:

Kuva 7: vasemmalla on syötekuvamme. Oikealla on MRZ-alue, joka on havaittu onnistuneesti.
Kuva 7: vasemmalla on syötekuvamme. Oikealla on MRZ-alue, joka on havaittu onnistuneesti.

tässä on toinen esimerkki koneellisesti luettavan alueen havaitsemisesta passikuvassa Pythonin ja OpenCV: n avulla:

Kuva 8: MRZ-tunnistuksen soveltaminen skannattuun passiin.
Kuva 8: MRZ-tunnistuksen soveltaminen skannattuun passiin.

sillä ei ole väliä, onko MRZ-alue kuvan ylä-vai alaosassa. Käyttämällä morfologisia operaatioita, poimimalla ääriviivat ja laskemalla ääriviivat ominaisuudet, voimme poimia MRZ ilman ongelmia.

sama pätee myös seuraavaan kuvaan:

Kuva 9: koneellisesti luettavien vyöhykkeiden havaitseminen kuvissa tietokonenäön avulla.
Kuva 9: koneellisesti luettavien alueiden havaitseminen kuvissa tietokonenäön avulla.

kokeillaan toista kuvaa:

Kuva 10: taas passiskannauksessa MRZ: n voi havaita peruskuvankäsittelytekniikoilla.
Kuva 10: PASSISKANNAUKSESSA MRZ: n voi taas havaita peruskuvankäsittelytekniikoilla.

tähän mennessä on tavattu vain tyypin 1 MRZ: iä, joissa on kolme riviä. Menetelmämme toimii kuitenkin yhtä hyvin tyypin 3 MRZ: ien kanssa, jotka sisältävät vain kaksi riviä:

Kuva 11: MRZ: n havaitseminen tyypin 3 passikuvassa Pythonin ja OpenCV: n avulla.
Kuva 11: MRZ: n havaitseminen tyypin 3 passikuvassa Pythonin ja OpenCV: n avulla.

Tässä toinen esimerkki tyypin 3 MRZ: n havaitsemisesta:

Kuva 12: Tietokonenäön ja kuvankäsittelyn käyttö koneellisesti luettavien alueiden havaitsemiseksi kuvissa.
Kuva 12: Tietokonenäön ja kuvankäsittelyn soveltaminen koneellisesti luettavien alueiden havaitsemiseen kuvissa.

mitä seuraavaksi? Suosittelen PyImageSearch University.

kurssitiedot:
30 + yhteensä luokat • 39h 44m video * päivitetty viimeksi: 12/2021
★★★★★ 4.84 (128 arvio) • 3000 + opiskelijaa ilmoittautui

uskon vahvasti, että jos sinulla olisi oikea opettaja, voisit hallita tietokonenäön ja syväoppimisen.

pitääkö tietokonenäön ja syväoppimisen olla mielestäsi aikaa vievää, musertavaa ja monimutkaista? Vai täytyykö siihen liittyä monimutkaista matematiikkaa ja yhtälöitä? Tai vaatii tietojenkäsittelytieteen tutkinnon?

näin ei ole.

tietokonenäön ja syväoppimisen hallitsemiseen tarvitaan vain se, että joku selittää asiat sinulle yksinkertaisilla, intuitiivisilla termeillä. Ja juuri niin minä teen. Tehtäväni on muuttaa koulutusta ja sitä, miten monimutkaisia Tekoälyaiheita opetetaan.

jos olet tosissasi tietokonenäön oppimisesta, seuraava pysäkkisi pitäisi olla PyImageSearch University, kattavin tietokonenäkö, syväoppiminen ja OpenCV-kurssi verkossa tänään. Täällä opit, miten voit menestyksekkäästi ja luottavaisesti soveltaa tietokonenäköä työhösi, tutkimuksiisi ja projekteihisi. Tule kanssani tietokonenäön hallintaan.

PyImageSearch Universityn sisältä löydät:

  • &tarkista; 30+ kurssia, jotka käsittelevät olennaista tietokonenäköä, syväoppimista ja Openenssia
  • ✓ 30+ todistukset suorittamisesta
  • ✓ 39h 44m tilausvideo
  • ✓ upouudet kurssit, jotka julkaistaan joka kuukausi varmistaen, että pysyt ajan tasalla huipputekniikan kanssa
  • &tarkista; valmiiksi konfiguroidut jupyter-muistikirjat Google colabissa
  • &tarkista; suorita kaikki koodiesimerkit selaimessasi-toimii Windowsissa, MacOS: ssa ja Linuxissa (dev-ympäristön määritystä ei tarvita!)
  • &tarkista; Pääsy keskitettyyn koodirepos kaikille 500 + tutorials PyImageSearch
  • &tarkista; Helppo yhdellä napsautuksella lataukset koodi, tietokokonaisuudet, ennalta koulutetut mallit, jne.
  • & check; Access on mobile, laptop, desktop, jne.

Klikkaa tästä liittyäksesi PyImageSearch University

Summary

tässä blogikirjoituksessa opimme tunnistamaan koneellisesti luettavia alueita (Mrzs) passien skannauksissa käyttäen vain peruskuvankäsittelytekniikoita, eli:

  • puinti.
  • kaltevuudet.
  • morfologiset operaatiot (erityisesti sulkemiset ja eroosiot).
  • Ääriviivaominaisuudet.

nämä toiminnot, vaikkakin yksinkertaiset, mahdollistivat MRZ-alueiden havaitsemisen kuvista ilman, että jouduimme turvautumaan kehittyneempiin piirteiden louhinta-ja koneoppimismenetelmiin, kuten lineaariseen SVM + HOG-menetelmään objektien havaitsemisessa.

muista, kun kohtaat haastavan tietokonenäköongelman-ota aina huomioon ongelma ja oletuksesi! Kuten tämä blogikirjoitus osoittaa, saatat olla yllättynyt, mitä perus kuvankäsittely toimintoja käytetään yhdessä voi saavuttaa.

vielä kerran suuret kiitokset PyImageSearch Gurun jäsenelle Hans Boonelle, joka toimitti meille nämä esimerkkipassikuvat! Kiitos Hans!

Leave a Reply

Sähköpostiosoitettasi ei julkaista.