EDI+VA · Esercizio di Programmazione

EP02_11 — 🏆 Correzione della Prospettiva (Omografia) su Immagine Reale

2.12.11 EP02_11 🏆 Correzione della Prospettiva (Omografia) su Immagine Reale

In questa attività, l’obiettivo è applicare la trasformazione prospettica (omografia) per “raddrizzare” un oggetto inclinato in una fotografia reale. Lavorerai con l’immagine di un giornale, dove la griglia di un gioco di Sudoku è distorta a causa dell’angolo con cui è stata scattata la foto.

Il tuo programma deve leggere i parametri di input dal terminale, caricare l’immagine, calcolare la matrice di omografia \(3 \times 3\), applicare la trasformazione geometrica e visualizzare un indicatore globale di validazione.

  • Leggi due interi L e C, che rappresentano le dimensioni di righe e colonne (altezza e larghezza) che l’immagine rettificata di uscita deve avere.
  • Leggi quattro coppie di coordinate \((x, y)\) dal terminale, che rappresentano i quattro angoli del quadrilatero di origine (il Sudoku distorto nell’immagine originale).
  • Calcola automaticamente le quattro coppie di coordinate di destinazione utilizzando le dimensioni \(L\) e \(C\) fornite, mappando gli angoli agli estremi della nuova immagine: \((0,0)\), \((C-1, 0)\), \((0, L-1)\) e \((C-1, L-1)\).
  • Carica l’immagine locale sudoku.png e convertila in scala di grigi (grayscale).
  • Calcola la matrice di omografia e applica la trasformazione spaziale all’immagine.
  • Output: Calcola e stampa la somma di tutti i pixel dell’immagine risultante.

📌 Importante:

  • File di input: L’immagine sudoku.png deve trovarsi nella stessa cartella dello script. Il programma deve leggerla direttamente dal disco (es: usando mm.read("sudoku.png") o cv2.imread).
  • Ordine dei Punti: Assicurati che la lettura dei 4 punti di origine e la generazione dei 4 punti di destinazione seguano rigorosamente lo stesso ordine degli angoli: Superiore-Sinistro (TL), Superiore-Destro (TR), Inferiore-Sinistro (BL) e Inferiore-Destro (BR).
  • Dimensioni in OpenCV: Ricorda che funzioni come cv2.warpPerspective si aspettano la dimensione dell’immagine di uscita nel formato (larghezza, altezza), che equivale a (C, L).
  • Interpolazione: Per garantire la coerenza matematica della somma dei pixel con il correttore automatico, utilizza l’interpolazione bilineare standard (flags=cv2.INTER_LINEAR).
  • Crediti: L’immagine utilizzata è “Sudoku en periódico” di Héctor Rodríguez, sotto licenza CC BY 2.0.

2.12.11.1 🧠 Contesto del Problema

L’omografia ha 8 gradi di libertà, richiedendo almeno 4 corrispondenze di punti per essere calcolata. A differenza delle trasformazioni affini, mappa qualsiasi quadrilatero in un altro quadrilatero, permettendo che le linee che convergono verso punti di fuga tornino ad essere parallele:

Operazione Caratteristica Applicazione Tipica
Omografia Proiezione tra piani Rettifica di documenti, scansione di targhe e codici QR.
Mappatura Inversa Scansione dalla destinazione all’origine Evita “buchi” o pixel vuoti nell’immagine finale rettificata.
Warping Ricampionamento spaziale Correzione della distorsione delle lenti e montaggio di panorami (stitching).

2.12.11.2 📌 Esempi

Input Output Osservazione
500
500
100 120
420 95
80 440
450 460
32982820 I primi due input sono le dimensioni di uscita (\(L\) e \(C\)). Le 4 righe successive sono le coordinate \((x, y)\) degli angoli del Sudoku nell’immagine originale + PAD. L’output è la somma totale dei pixel dell’immagine rettificata.
200 200
100 120
420 95
80 440
450 460
5277150 Stessi punti di origine dell’esempio precedente, ma generando un’immagine di uscita più piccola (\(200 \times 200\)). La somma dei pixel si riduce proporzionalmente a causa della scala.

2.12.11.3 Acquisizione dell’immagine del sudoku e conversione in livelli di grigio

La Figura 2.22 mostra la lettura dell’immagine originale seguita dalla conversione in tonalità di grigio e dal ridimensionamento a una matrice di \(500 \times 500\) pixel, preparando i dati per la fase successiva.

La correzione di prospettiva, applicata nella Figura 2.23 tramite matrice di omografia, elimina le deformazioni causate dall’angolo della telecamera e produce una visione frontale e regolare della griglia del Sudoku.

Figura 2.22: Acquisizione dell’immagine di un Sudoku a sinistra. A destra, conversione in scala di grigi e ridimensionamento. Credito: Héctor Rodríguez de Guardamar, Spagna (CC BY 2.0).
import cv2
import numpy as np

# --- 1. Carica l'immagine salvata (sudoku.png) ---
img = mm.read("sudoku.png")                # BGR, 500×500

# --- 2. Padding per non tagliare i vertici ---
PAD = 60
img_pad = cv2.copyMakeBorder(
    img, PAD, PAD, PAD, PAD,
    cv2.BORDER_CONSTANT, value=[255, 255, 255]
)

# --- 3. Punti di origine (angoli della griglia nell'immagine espansa) ---
pts1 = np.float32([
    [100, 160],    # TL
    [390, 45],    # TR
    [200, 580],   # BL
    [570, 420],   # BR
])
#     W    H

# --- 4. Punti di destinazione (vista frontale 500×500) ---
SIZE = 500
pts2 = np.float32([
    [0,    0],
    [SIZE, 0],
    [0,    SIZE],
    [SIZE, SIZE],
])

# --- 5. Omografia e raddrizzamento ---
img_rect = mm.perspective_transform(img_pad, pts1, pts2, size=(SIZE, SIZE))

# --- 6. Visualizzazione ---
mm.show(
    [img_pad, img_rect],
    titles=["Originale (con padding)", "Vista frontale raddrizzata"],
    cols=2, figsize=(10, 6), axis=True
)
Figura 2.23: Correzione prospettica: originale e vista frontale raddrizzata.
🎮 Simulatore EP02_11: Prospettiva del Sudoku Omografia 3×3 · CC BY 2.0
📷 Originale (Espansa) — Trascina gli Angoli Foto: Héctor Rodríguez · CC BY 2.0
✅ Corretta (400×400) — Vista Frontale
Caricamento immagine del Sudoku...
Figura 2.24: Simulatore EP02_11: Correzione della Prospettiva del Sudoku (Omografia 3×3 con Ricampionamento Bilineare)
%%writefile EP02_11.py
# Codice Python
Overwriting EP02_11.py
TestSuite("EP02_11.py").run()
✔️ EP02_11.cases esiste già in casos/
📋 4 caso/i caricato/i da casos/EP02_11.cases

🔍 Test di Python: EP02_11.py
⚠️ EP02_11.py: file vuoto (meno di 3 righe). Test saltati.