2011-01-08 2 views
12

Il mio solito metodo di contrasto al 100% e una certa regolazione della luminosità per regolare il punto di taglio di solito funziona abbastanza bene per pulire foto di piccoli sotto-circuiti o equazioni per la pubblicazione su E & R.SE, tuttavia a volte non è proprio così bello, come con questa immagine:Quali passi di elaborazione devo usare per pulire le foto dei disegni di linea?

alt text

Quali altri metodi oltre contrasto (o al posto di) posso usare per darmi un output più consistente?

Mi aspetto una risposta abbastanza generale, ma probabilmente lo implementerò in uno script (su cui posso semplicemente eseguire il dump dei file) usando ImageMagick e/o PIL (Python) quindi se avete qualcosa di specifico per loro sarebbe il benvenuto

Idealmente un'immagine di origine migliore sarebbe piacevole, ma occasionalmente uso questo sulle immagini di altre persone per aggiungere un po 'di lucido.

+1

ne dite di colore? Non ho familiarità con l'elaborazione delle immagini, ma sembra che se rimuovi tutto all'interno di una certa differenza di blu, la griglia verrà rimossa. – Mehrdad

risposta

15

Il primo passaggio consiste nell'equalizzare le differenze di illuminazione nell'immagine tenendo conto dei problemi di bilanciamento del bianco. La teoria qui è che la parte più luminosa dell'immagine all'interno di un'area limitata rappresenta il bianco. Sfocando l'immagine in anticipo eliminiamo l'influenza del rumore nell'immagine.

from PIL import Image 
from PIL import ImageFilter 
im = Image.open(r'c:\temp\temp.png') 
white = im.filter(ImageFilter.BLUR).filter(ImageFilter.MaxFilter(15)) 

alt text Il passo successivo è quello di creare un'immagine in scala di grigi dall'ingresso RGB. Ridimensionando al punto bianco correggiamo i problemi di bilanciamento del bianco. Prendendo il massimo di R, G, B, sottolineiamo qualsiasi colore che non sia un grigio puro come le linee blu della griglia. La prima riga di codice presentata qui è un dummy, per creare un'immagine della dimensione e del formato corretti.

grey = im.convert('L') 
width,height = im.size 
impix = im.load() 
whitepix = white.load() 
greypix = grey.load() 
for y in range(height): 
    for x in range(width): 
     greypix[x,y] = min(255, max(255 * impix[x,y][0]/whitepix[x,y][0], 255 * impix[x,y][2]/whitepix[x,y][3], 255 * impix[x,y][4]/whitepix[x,y][5])) 

Il risultato di queste operazioni è un'immagine che ha valori principalmente consistenti e può essere convertita in bianco e nero mediante una semplice soglia. alt text


Edit: E 'bello vedere un po' di concorrenza. nikie ha proposto un approccio molto simile, utilizzando la sottrazione invece del ridimensionamento per rimuovere le variazioni nel livello del bianco.Il mio metodo aumenta il contrasto nelle regioni con scarsa illuminazione e il metodo di Nikie non lo fa - il metodo che preferisci dipenderà dal fatto che ci siano informazioni nelle aree scarsamente illuminate che desideri conservare.

Il mio tentativo di ricreare questo approccio ha portato a questo:

for y in range(height): 
    for x in range(width): 
     greypix[x,y] = min(255, max(255 + impix[x,y][0] - whitepix[x,y][0], 255 + impix[x,y][7] - whitepix[x,y][8], 255 + impix[x,y][9] - whitepix[x,y][10])) 

alt text

Sto lavorando a una combinazione di tecniche per fornire un risultato ancora migliore, ma non è ancora del tutto pronto.

+0

Solo un commento dalla "competizione": la differenza principale tra il tuo suggerimento e il mio è che il tuo utilizza un filtro sfocatura (gaussiano?) Seguito da un filtro massimo (= dilatazione). Il mio usa un'apertura morfologica, che lascia virtualmente invariati i gradienti su larga scala. Il problema è che il PIL non contiene filtri morfologici (o non li ho trovati). – Niki

3

Che ne dici di detecting edges? Questo dovrebbe raccogliere i disegni al tratto.

Ecco il risultato di rilevamento dei bordi Sobel sulla vostra immagine:

alt text

Se quindi la soglia dell'immagine (utilizzando una soglia empiricamente determinato o la Ohtsu method), è possibile ripulire l'immagine utilizzando morphological operations (es. dilatazione ed erosione). Ciò ti aiuterà a sbarazzarti delle linee spezzate/doppie.

Come ha fatto notare Lambert, è possibile pre-elaborare l'immagine utilizzando il canale blu per sbarazzarsi delle linee della griglia se non le si desidera nel risultato.

Otterrete risultati migliori anche se accendete la pagina in modo uniforme prima di visualizzarla (o utilizzate solo uno scanner), perché non dovete preoccuparvi tanto delle soglie globali o locali.

15

Un modo comune per rimuovere la diversa illuminazione di sfondo è calcolare un'immagine "bianca" dall'immagine, tramite l'immagine opening.

In questo codice ottava esempio, ho usato il canale blu dell'immagine, perché le linee sullo sfondo sono meno prominenti in questo canale (Edited: utilizzando un elemento strutturante circolare produce artefatti meno visive di un semplice box):

src = imread('lines.png'); 
blue = src(:,:,3); 
mask = fspecial("disk",10); 
opened = imerode(imdilate(blue,mask),mask); 

Risultato: opened

quindi sottrarre questo da l'immagine di origine:

background_subtracted = opened-blue; 

background_subtracted (contrasto versione avanzata)

Infine, avevo appena binarizzare l'immagine con una soglia fissa:

binary = background_subtracted < 35; 

binary