Tekoälyagentit · Oppitunti

Skannattujen asiakirjojen OCR

Tesseract pytesseractin kautta, kuvien esikäsittely ja tarkkuuden parantaminen

Oppitunti 2/413 vaihetta

Skannattujen asiakirjojen OCR on ilmainen Tekoälyagentit-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Tekoälyagentit-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Tekoälyagentit-kurssilla on yhteensä 4 oppituntia.

Milloin OCR:ää tarvitaan

Kaikki dokumentit eivät ole digitaalisessa muodossa syntyneitä PDF-tiedostoja. Skannatut dokumentit, tekstivalokuvat, käsinkirjoitetut muistiinpanot ja kuvapohjaiset PDF-tiedostot edellyttävät optista tekstintunnistusta (OCR) tekstin poimimiseksi.

OCR muuntaa tekstin pikselikuvat koneellisesti luettaviksi merkeiksi. Kaksi johtavaa Python-kirjastoa ovat pytesseract (Google Tesseract) ja EasyOCR (syväoppiminen, monikielisyys).

pytesseractin perusteet

pytesseract on Python-kääre Googlen Tesseract OCR -moottorille. Tesseract asennetaan ensin käyttöjärjestelmätasolla, minkä jälkeen suoritetaan pip install pytesseract Pillow.

import pytesseract
from PIL import Image

# Simple text extraction
image = Image.open('scanned_document.png')
text = pytesseract.image_to_string(image)
print(text)

# Specify language (default: English)
text_fr = pytesseract.image_to_string(
    Image.open('french_doc.png'),
    lang='fra'
)

# Get detailed output with bounding boxes
data = pytesseract.image_to_data(
    image,
    output_type=pytesseract.Output.DICT
)
for i, word in enumerate(data['text']):
    if word.strip():
        conf = data['conf'][i]
        print(f'Word: {word!r:20} Confidence: {conf}')

Kuvan esikäsittely: harmaasävytys

OCR:n tarkkuus riippuu suuresti kuvan laadusta. Ensimmäinen esikäsittelyvaihe on muuntaminen harmaasävyiseksi — värit lisäävät kohinaa auttamatta merkkien tunnistamista.

Esikäsittelyyn voidaan käyttää Pillowia tai OpenCV:tä. Harmaasävytys vähentää kohinaa ja parantaa Tesseractin merkkien rajojen tunnistamista.

from PIL import Image, ImageOps
import numpy as np

def preprocess_grayscale(image_path):
    img = Image.open(image_path)

    # Convert to grayscale
    img = img.convert('L')  # 'L' = 8-bit grayscale

    # Optionally resize for better OCR (Tesseract works best at ~300 DPI)
    # Scale up small images
    width, height = img.size
    if width < 800:
        scale = 800 / width
        new_size = (int(width * scale), int(height * scale))
        img = img.resize(new_size, Image.LANCZOS)

    return img

img = preprocess_grayscale('scan.jpg')
text = pytesseract.image_to_string(img)
print(text[:300])

Kuvan esikäsittely: kynnystys

Kynnystys muuntaa harmaasävykuvan puhtaaksi mustavalkokuvaksi. Se poistaa harmaat varjot, epätasaisen valaistuksen ja taustakohinan, jolloin teksti erottuu terävästi OCR:ää varten.

from PIL import Image, ImageFilter
import numpy as np

def apply_threshold(img):
    # Method 1: Simple fixed threshold
    img_array = np.array(img)
    threshold = 128
    binary = np.where(img_array > threshold, 255, 0).astype(np.uint8)
    return Image.fromarray(binary)

def adaptive_threshold(img):
    # Method 2: Otsu's method via OpenCV (better for uneven lighting)
    try:
        import cv2
        img_array = np.array(img)
        _, binary = cv2.threshold(
            img_array, 0, 255,
            cv2.THRESH_BINARY + cv2.THRESH_OTSU
        )
        return Image.fromarray(binary)
    except ImportError:
        return apply_threshold(img)

img = preprocess_grayscale('uneven_scan.png')
img_clean = adaptive_threshold(img)
text = pytesseract.image_to_string(img_clean)
print(text[:300])

Kuvan esikäsittely: vinouman korjaus

Skannatut dokumentit ovat usein hieman kääntyneitä. Jo kahden asteen kallistuma heikentää OCR:n tarkkuutta huomattavasti. Vinouman korjauksessa kiertokulma tunnistetaan ja korjataan ennen kuvan välittämistä OCR-moottorille.

import numpy as np
from PIL import Image

def deskew(img):
    try:
        import cv2
        img_array = np.array(img)

        # Find rotation angle using Hough line transform
        edges = cv2.Canny(img_array, 50, 150, apertureSize=3)
        lines = cv2.HoughLines(edges, 1, np.pi/180, threshold=100)

        if lines is None:
            return img  # no lines detected, return unchanged

        angles = []
        for line in lines:
            rho, theta = line[0]
            angle = np.degrees(theta) - 90
            if -45 < angle < 45:
                angles.append(angle)

        if not angles:
            return img

        median_angle = np.median(angles)
        if abs(median_angle) > 0.5:  # only deskew if significant tilt
            print(f'Deskewing by {median_angle:.2f} degrees')
            return img.rotate(-median_angle, expand=True, fillcolor=255)
        return img
    except ImportError:
        return img  # OpenCV not available — skip deskew

Tesseractin kieliasetukset

Tesseract tukee yli sataa kieltä. Kielipaketit voi ladata käyttöjärjestelmän paketinhallinnalla. Monikielisissä dokumenteissa useat kielet määritetään +-erottimella.

import pytesseract
from PIL import Image

# List available languages
import subprocess
result = subprocess.run(['tesseract', '--list-langs'], capture_output=True, text=True)
print('Available languages:')
print(result.stdout)

# Single language
text_en = pytesseract.image_to_string(Image.open('doc.png'), lang='eng')

# Multiple languages (auto-detect best match)
text_multi = pytesseract.image_to_string(
    Image.open('doc.png'),
    lang='eng+fra+deu'  # English + French + German
)

# Tesseract config options for better accuracy
custom_config = r'--oem 3 --psm 6'  # OEM 3=LSTM, PSM 6=assume uniform block of text
text_tuned = pytesseract.image_to_string(
    Image.open('doc.png'),
    config=custom_config
)

EasyOCR: syväoppimiseen perustuva tunnistus

EasyOCR käyttää syväoppimismalleja ja suoriutuu Tesseractia paremmin heikkolaatuisista kuvista, kaarevasta tekstistä ja ei-latinalaisista kirjoitusjärjestelmistä. Se ei edellytä asennusta käyttöjärjestelmätasolla.

Asennus tehdään komennolla pip install easyocr. Ensimmäisellä käyttökerralla mallipainot ladataan (noin 200 Mt).

import easyocr

# Initialize reader (downloads model on first run)
reader = easyocr.Reader(
    ['en', 'tr'],  # list of languages
    gpu=False       # set True if CUDA available
)

# Read text from image
results = reader.readtext('scanned_page.png')

for (bbox, text, confidence) in results:
    print(f'Text: {text!r:30} Confidence: {confidence:.2f}')
    # bbox = [[x1,y1],[x2,y2],[x3,y3],[x4,y4]] (four corners)

# Get plain text only
text_only = ' '.join(result[1] for result in results)
print('Full text:', text_only[:300])

EasyOCR monikielisille dokumenteille

EasyOCR käsittelee monikielisiä dokumentteja hyvin. Se sopii esimerkiksi kansainvälisiin sopimuksiin, tutkimusartikkeleihin, joiden kuvatekstit ovat useilla kielillä, sekä dokumentteihin, joissa tekniset termit on kirjoitettu eri kirjoitusjärjestelmällä.

import easyocr

# For Arabic-English mixed document
reader_ar = easyocr.Reader(['ar', 'en'], gpu=False)
results = reader_ar.readtext('arabic_contract.png')

# For CJK languages
reader_cjk = easyocr.Reader(['ch_sim', 'en'], gpu=False)  # Simplified Chinese + English
results_cjk = reader_cjk.readtext('chinese_report.png')

# Filter by confidence threshold
HIGH_CONFIDENCE = 0.7
def filter_confident_results(results, threshold=HIGH_CONFIDENCE):
    return [
        (bbox, text, conf)
        for bbox, text, conf in results
        if conf >= threshold
    ]

Täydellinen esikäsittelyputki

Kaikki esikäsittelyvaiheet — harmaasävytys, kynnystys ja vinouman korjaus — voidaan ketjuttaa yhdeksi putkifunktioksi. OCR suoritetaan puhdistetulle kuvalle, ja tuloksena palautetaan sekä teksti että luottamusmittarit.

import pytesseract
from PIL import Image

def ocr_pipeline(image_path, lang='eng', engine='tesseract'):
    print(f'Processing: {image_path}')

    # 1. Load
    img = Image.open(image_path)

    # 2. Preprocess
    img = img.convert('L')         # grayscale
    img = adaptive_threshold(img)  # binarize
    img = deskew(img)              # correct rotation

    # 3. OCR
    if engine == 'easyocr':
        reader = easyocr.Reader([lang], gpu=False)
        results = reader.readtext(image_path)
        text = ' '.join(r[1] for r in results if r[2] > 0.5)
    else:
        config = f'--oem 3 --psm 6 -l {lang}'
        text = pytesseract.image_to_string(img, config=config)

    # 4. Clean
    text = '\n'.join(
        line.strip() for line in text.splitlines()
        if line.strip()
    )
    return text

text = ocr_pipeline('invoice_scan.jpg')
print(text[:500])

Kuvapohjaisten PDF-tiedostojen käsittely

Jotkin PDF-tiedostot sisältävät PDF-säilöön tallennettuja skannattuja sivuja kuvina. Tällaiset ”kuva-PDF:t” tunnistetaan, minkä jälkeen sivuille tehdään OCR yksitellen käyttämällä PyMuPDF:ää kuvien poimimiseen ensin.

import fitz
from PIL import Image
import io
import pytesseract

def is_image_pdf(doc):
    # Check if first page has very little extractable text
    text = doc[0].get_text().strip()
    return len(text) < 50

def ocr_pdf(filepath):
    doc = fitz.open(filepath)
    if not is_image_pdf(doc):
        # Native text — no OCR needed
        return '\n'.join(doc[i].get_text() for i in range(len(doc)))

    print('Image PDF detected — running OCR')
    all_text = []

    for page_num in range(len(doc)):
        page = doc[page_num]
        # Render page as image at 300 DPI
        mat = fitz.Matrix(300/72, 300/72)  # scale to 300 DPI
        pix = page.get_pixmap(matrix=mat)
        img = Image.open(io.BytesIO(pix.tobytes('png')))
        text = pytesseract.image_to_string(img)
        all_text.append(f'--- Page {page_num+1} ---\n{text}')

    doc.close()
    return '\n'.join(all_text)

Luottamukseen perustuva suodatus ja jälkikäsittely

OCR-tuloksissa on virheitä erityisesti heikkolaatuisten kuvien kohdalla. Tekstiä voidaan jälkikäsitellä suodattamalla vähän luottamusta saaneet sanat, korjaamalla yleisiä OCR-virheitä (0 vs O, 1 vs l) ja yhdenmukaistamalla välilyönnit.

import re

COMMON_OCR_ERRORS = {
    r'\b0([a-z])\b': r'O\1',
    r'\bl([0-9])\b': r'1\1',
    r'\|': 'I',
    r'  +': ' ',
}

def post_process_ocr(text):
    for pattern, replacement in COMMON_OCR_ERRORS.items():
        text = re.sub(pattern, replacement, text)
    lines = [line.strip() for line in text.splitlines()]
    return '\n'.join(line for line in lines if line)

def high_confidence_ocr(words_with_conf, min_confidence=60):
    words = [w for w, conf in words_with_conf if w.strip() and conf >= min_confidence]
    return post_process_ocr(' '.join(words))

fake_ocr_output = [('0range', 90), ('|s', 40), ('l5', 85), ('good', 95)]
print(high_confidence_ocr(fake_ocr_output))

Tietotesti

Mikä on kuvalle ennen OCR:ää tehtävän kynnystyksen (binarisoinnin) tarkoitus?

Kertaus: skannattujen dokumenttien OCR

OCR muuntaa skannatut kuvat koneellisesti luettavaksi tekstiksi. pytesseract on Google Tesseractin kääre — se on nopea ja kypsä ratkaisu, joka tukee yli sataa kielipakettia. EasyOCR käyttää syväoppimista ja käsittelee heikkolaatuisia kuvia ja monikielistä tekstiä paremmin.

Esikäsitelkää kuvat aina: muuntakaa ne harmaasävyisiksi, käyttäkää Otsun kynnystystä binarisointiin ja korjatkaa vinouma kiertymän oikaisemiseksi. Kuvapohjaisissa PDF-tiedostoissa sivut kannattaa muuntaa suuren DPI-arvon kuviksi PyMuPDF:llä ja suorittaa OCR sen jälkeen. Tulokset suodatetaan luottamuskynnyksen perusteella kohinan poistamiseksi.

Aloita maksutta

Opi Tekoälyagentit tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
60
Oppitunnit
239

Usein kysytyt kysymykset

Onko oppitunti ”Skannattujen asiakirjojen OCR” ilmainen?

Kyllä – oppitunnin ”Skannattujen asiakirjojen OCR” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Tekoälyagentit-kurssin, päivitä CoddyKit PROhon. Tekoälyagentit-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Skannattujen asiakirjojen OCR”?

Tesseract pytesseractin kautta, kuvien esikäsittely ja tarkkuuden parantaminen Harjoittelet Tekoälyagentit-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Tekoälyagentit-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Tekoälyagentit-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”Skannattujen asiakirjojen OCR”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Tekoälyagentit-oppitunnilla?

Kyllä. Jokainen Tekoälyagentit-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. PDF-tiedostojen jäsentäminen PyMuPDFilla ja pdfplumberilla
  2. Skannattujen asiakirjojen OCR
  3. Monen asiakirjan kysymys–vastaus-agentit
  4. Asiakirjojen luokittelu ja reititys
← Takaisin: Tekoälyagentit