Misschien wilt u een document digitaliseren om fysieke ruimte te besparen of een veilige back-up maken. Hoe dan ook, het schrijven van een programma dat foto's van je papieren bestanden naar een standaardformaat kan converteren, is een taak waar Python in uitblinkt.
Door een combinatie van geschikte bibliotheken te gebruiken, kunt u een kleine app bouwen om documenten te digitaliseren. Uw programma neemt een afbeelding van een fysiek document als invoer, past er verschillende beeldverwerkingstechnieken op toe en voert een gescande versie van de invoer uit.
Uw omgeving voorbereiden
Om dit artikel te volgen, moet u bekend zijn met de basisprincipes van Python. Je moet er ook verstand van hebben hoe te werken met de NumPy Python-bibliotheek.
Open een Python IDE en maak twee Python-bestanden. Noem de ene main.py en de andere transform.py. Voer vervolgens de volgende opdracht uit op de terminal om de vereiste bibliotheken te installeren.
pip install OpenCV-Python imutils scikit-image NumPy
U zult OpenCV-Python gebruiken om de beeldinvoer te nemen en enige beeldverwerking uit te voeren. Imutils om het formaat van de invoer- en uitvoerafbeeldingen te wijzigen. scikit-image om een drempel op de afbeelding toe te passen. NumPy helpt u bij het werken met arrays.
Wacht tot de installatie is voltooid en tot de IDE de skeletten van het project heeft bijgewerkt. Nadat de skeletupdate is voltooid, bent u klaar om te beginnen met coderen. De volledige broncode is beschikbaar in een GitHub-opslagplaats.
De geïnstalleerde bibliotheken importeren
Open het bestand main.py en importeer de bibliotheken die u in de omgeving hebt geïnstalleerd. Hierdoor kunt u hun functies oproepen en gebruiken waar nodig.
importeren cv2
importeren imutilaties
van skiimage.filters importeren drempel_lokaal
van transformeren importeren perspectief_transform
Negeer de fout gegenereerd op perspective_transform. Het zal verdwijnen wanneer u klaar bent met werken aan het transform.py-bestand.
De invoer nemen en vergroten/verkleinen
Maak een duidelijke afbeelding van het document dat u wilt scannen. Zorg ervoor dat de vier hoeken van het document en de inhoud ervan zichtbaar zijn. Kopieer de afbeelding naar dezelfde map waarin u de programmabestanden opslaat.
Geef het invoerbeeldpad door aan OpenCV. Maak een kopie van de originele afbeelding, want u hebt deze nodig tijdens de perspectieftransformatie. Deel de hoogte van de originele afbeelding door de hoogte waarnaar u het formaat wilt wijzigen. Hierdoor blijft de beeldverhouding behouden. Voer ten slotte de verkleinde afbeelding uit.
# Het afbeeldingspad passeren
origineel_img = cv2.imread('voorbeeld.jpg')
kopiëren = origineel_img.copy()# De gewijzigde hoogte in honderden
verhouding = origineel_img.vorm[0] / 500.0
img_resize = imutils.resize (origineel_img, hoogte=500)# Uitvoer weergeven
cv2.imshow('Verkleinde afbeelding', img_resize)
# Wachten tot de gebruiker op een willekeurige toets drukt
cv2.waitKey(0)
De uitvoer van de bovenstaande code is als volgt:
Je hebt nu de hoogte van de originele afbeelding aangepast naar 500 pixels.
De verkleinde afbeelding converteren naar grijswaarden
Converteer de verkleinde RGB-afbeelding naar grijstinten. De meeste bibliotheken voor beeldverwerking werken alleen met afbeeldingen in grijstinten, omdat deze gemakkelijker te verwerken zijn.
grijze_afbeelding = cv2.cvtColor (img_resize, cv2.COLOR_BGR2GRAY)
cv2.imshow('Grijze afbeelding', grijze_afbeelding)
cv2.waitKey(0)
Let op het verschil tussen de originele afbeelding en de grijze.
De gekleurde tafel is veranderd in zwart en wit.
Een randdetector toepassen
Pas een Gaussiaans vervagingsfilter toe op de grijze afbeelding om ruis te verwijderen. Roep vervolgens de OpenCV canny-functie aan om de randen in de afbeelding te detecteren.
vage_afbeelding = cv2.Gaussiaanse vervaging (grijze_afbeelding, (5, 5), 0)
edged_img = cv2.Canny (wazig_beeld, 75, 200)
cv2.imshow('Beeldranden', edged_img)
cv2.waitKey(0)
De randen zijn zichtbaar op de uitvoer.
De randen waarmee u gaat werken, zijn die van het document.
De grootste contour vinden
Detecteer de contouren die aanwezig zijn in het beeld met randen. Sorteer ze in aflopende volgorde en behoud alleen de vijf grootste contouren. Benader de grootste contour met vier zijden door de gesorteerde contouren te doorlopen.
cnts, _ = cv2.findContours (edged_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = gesorteerd (cnts, key=cv2.contourArea, reverse=WAAR)[:5]voor C in cts:
peri = cv2.arcLengte (c, WAAR)
ca. = cv2.ca.PolyDP(c, 0.02 * peri, WAAR)
als len (ongeveer) == 4:
doc = ca
pauze
De contour met vier zijden bevat waarschijnlijk het document.
De vier hoeken van de documentcontour omcirkelen
Omcirkel de hoeken van de gedetecteerde documentcontour. Dit zal u helpen bepalen of uw programma het document in de afbeelding heeft kunnen detecteren.
p = []
voor D in document:
tuple_point = tuple (d[0])
cv2.circle (img_resize, tuple_point, 3, (0, 0, 255), 4)
p.toevoegen (tuple_point)
cv2.imshow('Omcirkelde hoekpunten', img_resize)
cv2.waitKey(0)
Implementeer cirkels op de verkleinde RGB-afbeelding.
Nadat u het document heeft gedetecteerd, moet u het document nu uit de afbeelding extraheren.
Warp Perspective gebruiken om de gewenste afbeelding te krijgen
Warp-perspectief is een computervisietechniek voor het transformeren van een afbeelding om vervormingen te corrigeren. Het transformeert een afbeelding in een ander vlak, zodat u de afbeelding vanuit een andere hoek kunt bekijken.
warped_image = perspective_transform (kopiëren, doc.reshape(4, 2) * verhouding)
warped_image = cv2.cvtColor (warped_image, cv2.COLOR_BGR2GRAY)
cv2.imshow("Vervormd beeld", imutils.resize (warped_image, height=650))
cv2.waitKey(0)
Om een vervormd beeld te krijgen, moet u dit doen maak een eenvoudige module die de perspectieftransformatie zal uitvoeren.
Transformatiemodule
De module zal de punten van de documenthoeken ordenen. Het zal ook het documentbeeld in een ander vlak transformeren en de camerahoek veranderen in een opname van bovenaf.
Open het bestand transform.py dat u eerder hebt gemaakt. Importeer OpenCV- en NumPy-bibliotheken.
importeren onnozel als np
importeren cv2
Deze module bevat twee functies. Maak een functie die de coördinaten van de hoekpunten van het document rangschikt. De eerste coördinaat is die van de linkerbovenhoek, de tweede is die van de rechterbovenhoek, de derde is van de rechter benedenhoek en de vierde coördinaat is die van de linker benedenhoek hoek.
deforder_punten(ptn):
# initialiseren van de lijst met te bestellen coördinaten
rect = np.nullen((4, 2), dtype = "zweven32")s = pts.som (as = 1)
# linksboven punt heeft de kleinste som
rectificeren[0] = punten[np.argmin (s)]# punt rechtsonder heeft de grootste som
rectificeren[2] = punten[np.argmax (s)]berekenen van het verschil tussen de punten, de
punt rechtsboven heeft het kleinste verschil,
terwijl linksonder het grootste verschil zal hebben
diff = np.diff (pts, as = 1)
rectificeren[1] = punten[np.argmin (diff)]
rectificeren[3] = punten[np.argmax (diff)]
# retourneert geordende coördinaten
opbrengst rect
Maak een tweede functie die de hoekcoördinaten van de nieuwe afbeelding berekent en een overheadopname maakt. Vervolgens wordt de perspectieftransformatiematrix berekend en wordt het kromgetrokken beeld geretourneerd.
defperspectief_transform(afbeelding, punten):
# Pak de bestelde coördinaten afzonderlijk uit
rect = order_points (ptn)
(tl, tr, br, bl) = rectbereken de breedte van de nieuwe afbeelding, die de
maximale afstand tussen rechtsonder En linksonder
x-coördinaten of rechtsboven En x-coördinaten linksboven
breedteA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
breedteB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
maxBreedte = max (int (breedteA), int (breedteB))bereken de hoogte van de nieuwe afbeelding, die de
maximale afstand tussen linksboven En y-coördinaten linksonder
hoogteA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
hoogteB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
maxHeight = max (int (hoogteA), int (hoogteB))construeer de set bestemmingspunten om een overhead shot te verkrijgen
dst = np.array([
[0, 0],
[Maximale wijdte - 1, 0],
[Maximale wijdte - 1, maximale hoogte - 1],
[0, maximale hoogte - 1]], dtype = "zweven32")# bereken de perspectieftransformatiematrix
transform_matrix = cv2.getPerspectiveTransform (rect, dst)# Pas de transformatiematrix toe
kromgetrokken = cv2.warpPerspective (afbeelding, transform_matrix, (maxWidth, maxHeight))
# geef de vervormde afbeelding terug
opbrengst kromgetrokken
U hebt nu de transformatiemodule gemaakt. De fout bij het importeren van perspective_transform zal nu verdwijnen.
Merk op dat de weergegeven afbeelding een overheadopname heeft.
Adaptieve drempel toepassen en de gescande uitvoer opslaan
Pas in het main.py-bestand de Gaussiaanse drempel toe op de kromgetrokken afbeelding. Hierdoor krijgt de kromgetrokken afbeelding een gescand uiterlijk. Sla de uitvoer van de gescande afbeelding op in de map met de programmabestanden.
T = drempel_lokaal (warped_image, 11, offset=10, methode="gaussiaans")
kromgetrokken = (warped_image > T).astype("uint8") * 255
cv2.imwrite('./'+'scannen'+'.png', kromgetrokken)
Door de scan op te slaan in PNG-indeling blijft de documentkwaliteit behouden.
De uitvoer weergeven
Voer de afbeelding van het gescande document uit:
cv2.imshow("Uiteindelijk gescande afbeelding", imutils.resize (vervormd, height=650))
cv2.waitKey(0)
cv2.destroyAllWindows()
De volgende afbeelding toont de uitvoer van het programma, een overheadopname van het gescande document.
Hoe verder te gaan in computervisie
Het maken van een documentscanner omvat enkele kerngebieden van computervisie, wat een breed en complex veld is. Om vooruitgang te boeken in computervisie, moet u aan interessante maar uitdagende projecten werken.
U moet ook meer lezen over hoe u computervisie kunt gebruiken met de huidige technologieën. Zo blijf je op de hoogte en krijg je nieuwe ideeën voor projecten om aan te werken.