Oppdage maskinlesbare soner i passbilder

mrz_output_04

Dagens blogginnlegg ville ikke være mulig uten PyImageSearch Gurus medlem, Hans Boone. Hans jobber med et datasynsprosjekt for automatisk å oppdage Maskinlesbare Soner (MRZs) i passbilder-akkurat som regionen som er oppdaget i bildet ovenfor.

MRZ-regionen i pass eller reisekort faller i to klasser: Type 1 Og type 3. Type 1 MRZs er tre linjer, med hver linje som inneholder 30 tegn. Type 3 MRZ har bare to linjer, men hver linje inneholder 44 tegn. I begge tilfeller, MRZ koder identifiserende informasjon om en gitt borger, inkludert type pass, pass ID, utstedende land, navn, nasjonalitet, utløpsdato, etc.

Inne I PyImageSearch Gurus kurset viste Hans meg sin fremgang på prosjektet, og jeg ble umiddelbart interessert. Jeg har alltid ønsket å bruke datasynalgoritmer til passbilder (hovedsakelig bare for moro skyld), men manglet datasettet for å gjøre det. Gitt den personlige identifiserende informasjonen et pass inneholder, kunne jeg åpenbart ikke skrive et blogginnlegg om emnet og dele bildene jeg brukte til å utvikle algoritmen.

Heldigvis gikk Hans Med på å dele noen av prøvepassbildene han har tilgang til — og jeg hoppet på sjansen til å leke med disse bildene.

nå, før vi kommer til langt, er det viktig å merke seg at disse passene ikke er «ekte» i den forstand at de kan knyttes til et faktisk menneske. Men de er ekte pass som ble generert ved hjelp av falske navn, adresser, etc. for utviklere å jobbe med.

Du tror kanskje at for å oppdage MRZ-regionen i et pass at du trenger litt maskinlæring, kanskje ved Hjelp Av Det Lineære SVM + HOG-rammeverket for å konstruere EN «MRZ-detektor» – men det ville være overkill —

I Stedet kan VI utføre MRZ-deteksjon ved hjelp av bare grunnleggende bildebehandlingsteknikker som terskel, morfologiske operasjoner og konturegenskaper. I resten av dette blogginnlegget vil jeg detaljere min egen ta på hvordan du bruker disse metodene for å oppdage MRZ-regionen i et pass.

Leter du etter kildekoden til dette innlegget?

Hopp Rett Til Nedlastingsseksjonen

Oppdage maskinlesbare soner i passbilder

La oss gå videre og få dette prosjektet i gang. Åpne en ny fil, gi den navnet detect_mrz.py, og sett inn følgende kode:

# 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))

Linje 2-6 importerer våre nødvendige pakker. Jeg antar at Du allerede Har OpenCV installert. Du trenger også imutils, min samling av praktiske funksjoner for å gjøre grunnleggende bildebehandlingsoperasjoner Med OpenCV enklere. Du kan installere imutilsved hjelp av pip :

$ pip install --upgrade imutils

Derfra Håndterer Linjer 9-11 parsing vårt kommandolinjeargument. Vi trenger bare en enkelt bryter her, --images , som er banen til katalogen som inneholder passbildene vi skal behandle.

Til Slutt initialiserer Linjene 14 og 15 to kjerner som vi senere bruker når vi bruker morfologiske operasjoner, spesielt lukkeoperasjonen. For tiden er det bare å merke seg at den første kjernen er rektangulær med en bredde omtrent 3x større enn høyden. Den andre kjernen er firkantet. Disse kjernene vil tillate oss å lukke hull mellom MRZ-tegn og åpninger mellom MRZ-linjer.

Nå som våre kommandolinjeargumenter analyseres, kan vi begynne å looping over hvert av bildene i datasettet og behandle dem:

# 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)

Linje 20 og 21 laster vårt originale bilde fra disk og endrer størrelsen på det for å ha en maksimal høyde på 600 piksler. Du kan se et eksempel på et originalt bilde nedenfor:

Figur 1: vårt opprinnelige passbilde som vi prøver å oppdage MRZ i.
Figur 1: vårt opprinnelige passbilde som vi prøver å oppdage MRZ i.

Gaussisk uskarphet brukes På Linje 26 for å redusere høyfrekvent støy. Vi bruker deretter en blackhat morfologisk operasjon til det uskarpe gråtonebildet på Linje 27.

en blackhat-operatør brukes til å avsløre mørke områder (DVS. MRZ-tekst) mot lyse bakgrunner(dvs. bakgrunnen til passet selv). Siden passeteksten alltid er svart på en lys bakgrunn (i hvert fall når det gjelder dette datasettet), er en blackhat-operasjon hensiktsmessig. Nedenfor kan du se resultatet av å bruke blackhat-operatøren:

Figur 2: Bruk av blackhat morfologisk operatør avslører den svarte MRZ-teksten mot lyspassbakgrunnen.
Figur 2: Bruk av blackhat morfologisk operatør avslører den svarte MRZ-teksten mot lyspassbakgrunnen.

det neste trinnet I MRZ-deteksjon er å beregne gradientstørrelsesrepresentasjonen av blackhat-bildet ved Hjelp Av scharr-operatøren:

# 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")

her beregner Vi scharr-gradienten langs x-aksen til blackhat-bildet, og avslører områder av bildet som ikke bare er mørke mot en lys bakgrunn, men også inneholder vertikale endringer i gradienten, for EKSEMPEL MRZ-tekstregionen. Vi tar da dette gradientbildet og skalerer det tilbake i området ved hjelp av min / maks skalering:

Figur 3: Bruk Av scharr-operatør til vårt blackhat-bilde viser regioner som inneholder sterke vertikale endringer i gradient.
Figur 3: Bruk Av scharr-operator på blackhat-bildet viser områder som inneholder sterke vertikale endringer i gradient.

selv om det ikke er helt åpenbart hvorfor vi bruker dette trinnet, vil jeg si at det er ekstremt nyttig for å redusere falske positive MRZ-detekteringer. Uten det kan vi ved et uhell markere pyntet eller utformet regioner i passet SOM MRZ. Jeg vil forlate dette som en øvelse for deg å bekrefte at beregning av gradienten til blackhat-bildet kan forbedre MRZ-deteksjonsnøyaktigheten.

det neste trinnet er å prøve å oppdage DE faktiske linjene I MRZ:

# 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)

Først bruker Vi en avsluttende operasjon ved hjelp av vår rektangulære kjerne. Denne lukkeoperasjonen er ment å lukke hull i MELLOM MRZ-tegn. Vi bruker deretter terskel ved Hjelp Av Otsus metode for automatisk å terskel bildet:

Figur 4: Bruk en lukkeoperasjon ved hjelp av en rektangulær kjerne (som er bredere enn den er høy) for å lukke hull i MELLOM MRZ-tegnene
Figur 4: Bruk en avsluttende operasjon ved hjelp av en rektangulær kjerne (som er bredere enn den er høy) for å lukke hull i MELLOM MRZ-tegnene

som vi kan se fra figuren ovenfor, er HVER AV MRZ-linjene til stede i terskelkartet vårt.

det neste trinnet er å lukke hullene mellom de faktiske linjene, noe som gir oss en stor rektangulær region som tilsvarer 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)

Her utfører vi en annen avsluttende operasjon, denne gangen ved hjelp av vår firkantede kjerne. Denne kjernen brukes til å lukke hull mellom de enkelte linjene I MRZ, noe som gir oss en stor region som tilsvarer MRZ. En rekke erosjoner blir deretter utført for å bryte fra hverandre tilkoblede komponenter som kan ha blitt sluttet under lukkeoperasjonen. Disse erosjoner er også nyttig i å fjerne små blobs som er irrelevant FOR MRZ.

 Figur 5: en andre avsluttende operasjon utføres, denne gangen ved hjelp av en firkantet kjerne for å lukke hullene mellom individuelle MRZ-linjer.
Figur 5: En annen avsluttende operasjon utføres, denne gangen ved hjelp av en firkantet kjerne for å lukke hullene mellom individuelle MRZ-linjer.

for noen passskanninger kan grensen til passet ha blitt festet TIL MRZ-regionen under avsluttende operasjoner. For å rette opp dette setter vi 5% av venstre og høyre kant av bildet til null (dvs. svart):

# 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

du kan se resultatet av vår grensen fjerning nedenfor.

 Figur 6: Sett 5% av venstre og høyre kantpiksler til null, slik at MRZ-regionen ikke er festet til den skannede margen på passet.
Figur 6: Sett 5% av venstre og høyre kantpiksler til null, slik at MRZ-regionen ikke er festet til den skannede margen på passet.

Sammenlignet Med Figur 5 ovenfor, kan du nå se at grensen er fjernet.

det siste trinnet er å finne konturene i vårt terskelbilde og bruke konturegenskaper for å identifisere MRZ:

# 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)

På Linje 56-58 beregner vi konturene (dvs. konturer) av vårt terskelbilde. Vi tar deretter disse konturene og sorterer dem basert på deres størrelse i synkende rekkefølge På Linje 59 (noe som betyr at de største konturene er først i listen).

På Linje 62 starter vi looping over vår sorterte liste over konturer. For hver av disse konturene beregner vi markeringsrammen (Linje 66) og bruker den til å beregne to egenskaper: sideforholdet og dekningsforholdet. Sideforholdet er ganske enkelt bredden på grenseboksen dividert med høyden. Dekningsforholdet er bredden på markeringsrammen dividert med bredden på det faktiske bildet.

Ved hjelp av disse to egenskapene kan vi sjekke På Linje 72 for å se om VI undersøker MRZ-regionen. MRZ er rektangulær, med en bredde som er mye større enn høyden. MRZ bør også strekke seg over minst 75% av inngangsbildet.

Forutsatt at Disse to tilfellene holder, Bruker Linjene 75-84 (x, y)-koordinatene til markeringsrammen for å trekke UT MRZ og tegne markeringsrammen på vårt inngangsbilde.

Til Slutt Viser Linjene 87-89 våre resultater.

Resultater

for å se VÅR MRZ-detektor i aksjon, utfør bare følgende kommando:

$ python detect_mrz.py --images examples

Nedenfor kan du se et eksempel på en vellykket MRZ deteksjon, MED MRZ skissert i grønt:

Figur 7: til venstre har vi vårt inngangsbilde. OG TIL høyre har VI MRZ-regionen som har blitt oppdaget.
Figur 7: til venstre har vi vårt inngangsbilde. OG TIL høyre har VI MRZ-regionen som har blitt oppdaget.

her er et annet eksempel på å oppdage Den Maskinlesbare Sonen i et passbilde ved Hjelp Av Python og OpenCV:

Figur 8: Bruke MRZ-deteksjon til et skannet pass.
Figur 8: Bruk AV MRZ-deteksjon på et skannet pass.

DET spiller ingen rolle OM MRZ-regionen er øverst eller nederst i bildet. Ved å bruke morfologiske operasjoner, trekke ut konturer og beregne konturegenskaper, kan VI trekke UT MRZ uten problem.

det samme gjelder for følgende bilde:

Figur 9: Oppdage maskinlesbare soner i bilder ved hjelp av datasyn.
Figur 9: Oppdage maskinlesbare soner i bilder ved hjelp av datasyn.

La oss gi et annet bilde et forsøk:

 Figur 10: Igjen kan VI oppdage MRZ i passskanningen ved hjelp av grunnleggende bildebehandlingsteknikker.
Figur 10: Igjen kan VI oppdage MRZ i passport-skanningen ved hjelp av grunnleggende bildebehandlingsteknikker.

frem til nå har Vi bare sett Type 1 MRZs som inneholder tre linjer. Men vår metode fungerer like bra Med Type 3 MRZs som bare inneholder to linjer:

Figur 11: Oppdage MRZ i Et type 3 passbilde ved Hjelp Av Python og OpenCV.
Figur 11: Detekterer MRZ i Et type 3 passbilde ved Hjelp Av Python og OpenCV.

her er et annet eksempel på å oppdage En TYPE 3 MRZ:

Figur 12: Bruk av datasyn og bildebehandling for å oppdage maskinlesbare soner i bilder.
Figur 12: Bruk av datasyn og bildebehandling for å oppdage maskinlesbare soner i bilder.

Hva blir det neste? Jeg anbefaler PyImageSearch University.

Kursinformasjon:
30 + totalt antall klasser • 39h 44m video * Sist oppdatert: 12/2021
★★★★★ 4.84 (128 Karakterer • * 3000 + Studenter

jeg tror sterkt på at hvis du hadde den rette læreren, kunne du mestre datasyn og dyp læring.

tror du læring datasyn og dyp læring må være tidkrevende, overveldende og komplisert? Eller må involvere komplekse matematikk og ligninger? Eller krever en grad i informatikk?

Det er ikke tilfelle.

Alt du trenger for å mestre datasyn og dyp læring er at noen skal forklare ting for deg på enkle, intuitive vilkår. Og det er akkurat det jeg gjør. Mitt oppdrag er å endre utdanning og hvordan komplekse Kunstige Intelligensemner blir undervist.

Hvis du er seriøs om å lære datasyn, bør neste stopp Være PyImageSearch University, Den mest omfattende datasyn, dyp læring og OpenCV-kurset online i dag. Her lærer du hvordan du vellykket og trygt bruker datasyn til arbeid, forskning og prosjekter. Bli med meg i computer vision mastery.

Inne PyImageSearch Universitetet finner du:

  • &sjekk; 30 + kurs på essential computer vision, deep learning og OpenCV emner
  • &sjekk; 30+ Sertifikater For Ferdigstillelse
  • &sjekk; 39h 44m on-demand video
  • &sjekk; Helt Nye kurs utgitt hver måned, slik at du kan holde tritt med toppmoderne teknikker
  • &sjekk; forhåndskonfigurert jupyter-Notatbøker i google colab
  • &sjekk; kjør alle kodeeksempler i nettleseren din-fungerer på windows, macos og linux (ingen konfigurasjon av utviklingsmiljø kreves!)
  • &sjekk; Tilgang til sentralisert kode repos for alle 500 + tutorials På PyImageSearch
  • & sjekk; Enkel ett-klikk nedlastinger for kode, datasett, pre-trente modeller, etc.
  • & sjekk; Tilgang på mobil, bærbar pc, skrivebord, etc.

Klikk her for Å bli Med PyImageSearch University

Sammendrag

i dette blogginnlegget lærte vi å oppdage Maskinlesbare Soner (MRZs) i passskanninger ved hjelp av bare grunnleggende bildebehandlingsteknikker, nemlig:

  • Terskel.
  • Graderinger.
  • Morfologiske operasjoner (spesielt lukkinger og erosjoner).
  • Konturegenskaper.

disse operasjonene, mens enkle, tillot oss å oppdage MRZ-regionene i bilder uten å måtte stole på mer avanserte funksjonsutvinning og maskinlæringsmetoder som Lineær SVM + HOG for objektdeteksjon.

Husk at når du står overfor et utfordrende datasynsproblem-vurder alltid problemet og dine forutsetninger! Som dette blogginnlegget demonstrerer, kan du bli overrasket over hva grunnleggende bildebehandlingsfunksjoner som brukes i tandem kan oppnå.

nok en gang, en stor takk Til PyImageSearch Gurus medlem, Hans Boone, som følger oss med disse eksempel passbilder! Takk Hans!

Leave a Reply

Din e-postadresse vil ikke bli publisert.