Läsare som du hjälper till att stödja MUO. När du gör ett köp med hjälp av länkar på vår webbplats kan vi tjäna en affiliate-provision. Läs mer.

Du kanske vill digitalisera ett dokument för att spara fysiskt utrymme eller skapa en säkerhetskopia. Hur som helst, att skriva ett program som kan konvertera foton av dina pappersfiler till ett standardformat är en uppgift som Python briljerar med.

Med hjälp av en kombination av lämpliga bibliotek kan du bygga en liten app för att digitalisera dokument. Ditt program tar en bild av ett fysiskt dokument som indata, tillämpar flera bildbehandlingstekniker på det och matar ut en skannad version av inmatningen.

Förbered din miljö

För att följa den här artikeln bör du vara bekant med grunderna i Python. Du måste också ha förståelse för hur man arbetar med NumPy Python-biblioteket.

Öppna valfri Python IDE och skapa två Python-filer. Namnge en main.py och den andra transform.py. Kör sedan följande kommando på terminalen för att installera de nödvändiga biblioteken.

instagram viewer
pip installera OpenCV-Python imutils scikit-image NumPy

Du kommer att använda OpenCV-Python för att ta bildinmatningen och utföra viss bildbehandling. Imutils för att ändra storlek på ingångs- och utdatabilder. scikit-image för att tillämpa en tröskel på bilden. NumPy hjälper dig att arbeta med arrayer.

Vänta tills installationen är klar och tills IDE uppdaterar projektskeletten. När skelettuppdateringen är klar är du redo att börja koda. Den fullständiga källkoden finns tillgänglig i en GitHub-förråd.

Importera de installerade biblioteken

Öppna filen main.py och importera de bibliotek du installerade i miljön. Detta gör att du kan ringa och använda deras funktioner vid behov.

importera cv2
importera imutils
från skimage.filters importera tröskel_lokal
från omvandla importera perspektiv_omvandla

Ignorera felet som kastas på perspective_transform. Den försvinner när du är klar med att arbeta med filen transform.py.

Ta och ändra storlek på indata

Ta en tydlig bild av dokumentet du vill skanna. Se till att de fyra hörnen av dokumentet och dess innehåll är synliga. Kopiera bilden till samma mapp som du lagrar programfilerna.

Skicka ingångsbildens sökväg till OpenCV. Gör en kopia av originalbilden eftersom du kommer att behöva den under perspektivomvandlingen. Dela höjden på originalbilden med höjden du vill ändra storlek på den till. Detta kommer att bibehålla bildförhållandet. Mata slutligen ut den ändrade storleken på bilden.

# Passerar bildbanan
original_img = cv2.imread("sample.jpg")
copy = original_img.copy()

# Den ändrade höjden i hundratals
ratio = original_img.shape[0] / 500.0
img_resize = imutils.resize (original_img, höjd=500)

# Visar utdata
cv2.imshow("Ändra storlek på bild", img_resize)

# Väntar på att användaren ska trycka på valfri tangent
cv2.waitKey(0)

Utdata från ovanstående kod är som följer:

Du har nu ändrat storleken på originalbilden till 500 pixlar.

Konvertera den ändrade storleken på bilden till gråskala

Konvertera den ändrade storleken på RGB-bilden till gråskala. De flesta bildbehandlingsbibliotek fungerar bara med gråskalebilder eftersom de är lättare att bearbeta.

grå_bild = cv2.cvtColor (img_resize, cv2.COLOR_BGR2GRAY)
cv2.imshow("Gråad bild", grå_bild)
cv2.waitKey(0)

Lägg märke till skillnaden mellan originalbilden och den gråa.

Det färgade bordet har blivit svart och vitt.

Applicera en kantdetektor

Använd ett Gaussiskt oskärpafilter på den gråa bilden för att ta bort brus. Anropa sedan OpenCV canny-funktionen för att upptäcka kanterna som finns i bilden.

blurred_image = cv2.GaussianBlur (grå_bild, (5, 5), 0)
edged_img = cv2.Canny (suddig_bild, 75, 200)
cv2.imshow("Bildkanter", edged_img)
cv2.waitKey(0)

Kanterna är synliga på utgången.

Kanterna du kommer att arbeta med är dokumentets kanter.

Hitta den största konturen

Upptäck konturerna i den kantade bilden. Sortera dem i fallande ordning med endast de fem största konturerna. Ungefär den största konturen med fyra sidor genom att loopa genom de sorterade konturerna.

cnts, _ = cv2.findContours (edged_img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
cnts = sorterad (cnts, key=cv2.contourArea, omvänd=Sann)[:5]

för c i cnts:
peri = cv2.arcLength (c, Sann)
ungefär = cv2.approxPolyDP(c, 0.02 *peri, Sann)

om len (ungefär) == 4:
doc = ca
ha sönder

Konturen med fyra sidor innehåller sannolikt dokumentet.

Cirkel de fyra hörnen av dokumentkonturen

Ringa in hörnen på den upptäckta dokumentkonturen. Detta hjälper dig att avgöra om ditt program kunde upptäcka dokumentet i bilden.

p = []

för d i doc:
tuppelpunkt = tuppel (d[0])
cv2.circle (img_resize, tuple_point, 3, (0, 0, 255), 4)
p.append (tuple_point)

cv2.imshow("Ringade hörnpunkter", img_resize)
cv2.waitKey(0)

Implementera cirkling på den ändrade storleken på RGB-bilden.

Efter att ha upptäckt dokumentet måste du nu extrahera dokumentet från bilden.

Använda Warp Perspective för att få den önskade bilden

Warpperspektiv är en datorseendeteknik för att transformera en bild för att korrigera förvrängningar. Den omvandlar en bild till ett annat plan så att du kan se bilden från en annan vinkel.

warped_image = perspektiv_transform (kopia, doc.reshape(4, 2) * förhållande)
warped_image = cv2.cvtColor (warped_image, cv2.COLOR_BGR2GRAY)
cv2.imshow("skev bild", imutils.resize (warped_image, height=650))
cv2.waitKey(0)

För att få en skev bild måste du skapa en enkel modul som kommer att utföra perspektivomvandlingen.

Transformationsmodul

Modulen kommer att ordna punkterna i dokumenthörnen. Det kommer också att omvandla dokumentbilden till ett annat plan och ändra kameravinkeln till en överliggande bild.

Öppna filen transform.py som du skapade tidigare. Importera OpenCV- och NumPy-bibliotek.

importera numpy som np
importera cv2

Denna modul kommer att innehålla två funktioner. Skapa en funktion som kommer att ordna koordinaterna för dokumentets hörnpunkter. Den första koordinaten kommer att vara den för det övre vänstra hörnet, den andra kommer att vara det för det övre högra hörnet, den tredje kommer att vara i det nedre högra hörnet, och den fjärde koordinaten kommer att vara den för det nedre vänstra hörn.

deforder_poäng(poäng):
# initierar listan över koordinater som ska beställas
rect = np.zeros((4, 2), dtype = "float32")

s = pts.sum (axel = 1)

# övre vänstra punkten kommer att ha den minsta summan
räta[0] = pts[np.argmin (s)]

# punkt längst ner till höger kommer att ha den största summan
räta[2] = poäng[np.argmax (s)]

beräkna skillnaden mellan punkterna, den
den övre högra punkten kommer att ha den minsta skillnaden,
medan den nedre vänstra kommer att ha den största skillnaden
diff = np.diff (pkt, axel = 1)
räta[1] = pts[np.argmin (diff)]
räta[3] = pts[np.argmax (diff)]

# returnerar beställda koordinater
lämna tillbaka rect

Skapa en andra funktion som kommer att beräkna hörnkoordinaterna för den nya bilden och få en överheadbild. Den kommer sedan att beräkna perspektivomvandlingsmatrisen och returnera den skeva bilden.

defperspektiv_omvandla(bild, poäng):
# packa upp de beställda koordinaterna individuellt
rect = order_points (poäng)
(tl, tr, br, bl) = rekt

beräkna bredden på den nya bilden, som kommer att vara
maximalt avstånd mellan nedre höger och nedre vänstra
x-koordinater eller uppe till höger och x-koordinater uppe till vänster
breddA = np.sqrt(((br[0] - bl[0]) ** 2) + ((br[1] - bl[1]) ** 2))
breddB = np.sqrt(((tr[0] - tl[0]) ** 2) + ((tr[1] - tl[1]) ** 2))
maxWidth = max (int (widthA), int (widthB))

beräkna höjden på den nya bilden, som kommer att vara
maximalt avstånd mellan det övre vänstra och y-koordinater längst ned till vänster
höjdA = np.sqrt(((tr[0] - br[0]) ** 2) + ((tr[1] - br[1]) ** 2))
höjdB = np.sqrt(((tl[0] - bl[0]) ** 2) + ((tl[1] - bl[1]) ** 2))
maxHeight = max (int (höjdA), int (höjdB))

konstruera uppsättningen destinationspunkter för att få ett överheadskott
dst = np.array([
[0, 0],
[maximal bredd - 1, 0],
[maximal bredd - 1, maximal höjd - 1],
[0, maximal höjd - 1]], dtype = "float32")

# beräkna perspektivomvandlingsmatrisen
transform_matrix = cv2.getPerspectiveTransform (rect, dst)

# Använd transformationsmatrisen
warped = cv2.warpPerspective (image, transform_matrix, (maxWidth, maxHeight))

# returnera den skeva bilden
lämna tillbaka skev

Du har nu skapat transformationsmodulen. Felet på importen perspective_transform kommer nu att försvinna.

Lägg märke till att bilden som visas har en bild ovanför.

Tillämpa adaptiv tröskel och spara den skannade utdata

I main.py-filen, tillämpa den gaussiska tröskeln på den skeva bilden. Detta kommer att ge den skeva bilden ett skannat utseende. Spara den skannade bilden i mappen som innehåller programfilerna.

T = tröskel_lokal (förvrängd_bild, 11, offset=10, metod="gaussisk")
skev = (förvriden_bild > T).astype("uint8") * 255
cv2.imwrite('./'+'skanna'+'.png',skev)

Att spara skanningen i PNG-format bibehåller dokumentkvaliteten.

Visar utdata

Mata ut bilden av det skannade dokumentet:

cv2.imshow("Slutlig skannad bild", imutils.resize (skev, höjd=650))
cv2.waitKey(0)
cv2.destroyAllWindows()

Följande bild visar programmets utdata, en overheadbild av det skannade dokumentet.

Hur man avancerar i datorseende

Att skapa en dokumentskanner täcker några kärnområden inom datorseende, vilket är ett brett och komplext område. För att avancera i datorseende bör du arbeta med intressanta men utmanande projekt.

Du bör också läsa mer om hur du kan använda datorseende med nuvarande teknologier. Detta kommer att hålla dig informerad och ge dig nya idéer för projekt att arbeta med.