Quale filtro di immagine può essere applicato per rimuovere il pattern grigliato dai jpeg corrotti?


8

Ho circa 1.400 jpeg che sono stati corrotti in qualche modo e hanno perso le immagini di backup. Sembrano tutti avere lo stesso modello di linee grigliate su ciascuna (cioè la griglia non si sposta da un'immagine all'altra.

Ecco come appare una di queste immagini:

inserisci qui la descrizione dell'immagine

Esistono tecniche di filtraggio delle immagini in particolare in Matlab o in altro modo che rimuoveranno o smusseranno questo schema di griglia?


2
puoi darci maggiori informazioni su come queste immagini sono state danneggiate? Questo è uno strano schema, dal momento che è molto pixel-locale, che richiede un'alta risoluzione nel dominio della frequenza, il che implicherebbe un codificatore JPEG orribilmente rotto, forse?
Marcus Müller,

Non sono del tutto sicuro, scusa. Le immagini fanno parte di un database che ha cambiato le mani un paio di volte e le persone non sono state così attente come avrebbero dovuto (... studenti). Per quanto riguarda il problema dei pixel locali, sono d'accordo. In alcune foto che includono superfici d'acqua più scure, il motivo a griglia è molto chiaro.
Stephen E,

@ MarcusMüller: un decoder JPEG orribilmente rotto mi sembra più probabile, anche se suppongo che sia possibile in entrambi i modi. Ad ogni modo, in base alla spaziatura irregolare e non-power-of-2 delle linee, mi sembra che le immagini siano state probabilmente ridimensionate e ricodificate dopo che si è verificata la corruzione, quindi purtroppo, cercando di risolverle nel Il dominio DCT è probabilmente inutile. La soluzione di inpainting di Maximilian Matthé di seguito è probabilmente la migliore scommessa dell'OP.
Ilmari Karonen il

1
Oh, e l'OP dovrebbe sicuramente salvare un backup delle immagini prima di tentare di ripararle in alcun modo, nel caso in cui qualcuno voglia mai rianalizzarle. La verniciatura, per quanto ben eseguita, è sempre un'operazione con perdita di dati e ha il potenziale di introdurre una distorsione (dal momento che sostanzialmente equivale a recuperare dati falsi per sostituire i pixel danneggiati). E lo stesso vale per il filtro mediano o la rimozione della frequenza, o qualsiasi altra cosa che possa nascondere questo tipo di danno.
Ilmari Karonen il

@IlmariKaronen Grazie per la punta. Proverò sicuramente a stare più attento con queste immagini.
Stephen E

Risposte:


16

È possibile utilizzare un algoritmo di pittura standard. Questi algoritmi sostituiscono i pixel contrassegnati in un'immagine con i valori dei pixel che circondano questi pixel contrassegnati. La sfida qui è quella di rilevare la griglia (i miei test sembrano dimostrare che non è una griglia completamente regolare). Quindi, ho trovato questa soluzione:

from PIL import Image
import requests
from io import BytesIO
import cv2

url = "http://i.stack.imgur.com/Ahrnl.jpg"
response = requests.get(url)
img = Image.open(BytesIO(response.content))

plt.imshow(img)
A = np.array(img)
A2 = A.copy()
A_gray = cv2.cvtColor(A, cv2.COLOR_RGB2GRAY)


# Do some rough edge detection to find the grid
sX = cv2.Sobel(A_gray, cv2.CV_64F, 1, 0, ksize=3)
sY = cv2.Sobel(A_gray, cv2.CV_64F, 0, 1, ksize=3)
sX[sX<0] = 0
sY[sY<0] = 0

plt.subplot(221)
plt.imshow(sX)

plt.subplot(222)
plt.imshow(sY)

plt.subplot(223)
# the sum operation projects the edges to the X or Y-axis. 
# The 0.2 damps the high peaks a little
eX = (sX**.2).sum(axis=0)  
eX = np.roll(eX, -1) # correct for the 1-pixel offset due to Sobel filtering
plt.plot(eX)

plt.subplot(224)
eY = (sY**.2).sum(axis=1)
eY = np.roll(eY, -1)
plt.plot(eY)

mask = np.zeros(A2.shape[:2], dtype=np.uint8)
mask[eY>480,:] = 1
mask[:, eX>390] = 1


A2[mask.astype(bool),:] = 255
plt.figure()
plt.subplot(221)
plt.imshow(A)

plt.subplot(222)
plt.imshow((A2))

restored = cv2.inpaint(A, mask, 1, cv2.INPAINT_NS)
plt.subplot(223)
plt.imshow(restored)

L'output del programma è il seguente:

inserisci qui la descrizione dell'immagine

inserisci qui la descrizione dell'immagine

Per rilevare la griglia ho fatto una soluzione rapida e sporca. Può essere migliorato molto, ma mostra l'idea iniziale. Il flusso generale è:

  1. rilevare la griglia
  2. creare una maschera che descriva quali pixel sono danneggiati dalla griglia
  3. dipingere i pixel corrotti.

Per la pittura ho usato l' operazione di pittura di OpenCV . Per rilevare la griglia, ho eseguito il rilevamento dei bordi in direzione X e Y utilizzando un filtro Sobel. Quindi aggiungo tutti i valori dei bordi nella direzione X e Y per trovare i picchi, dove si trovano le linee della griglia. Quindi, scelgo i picchi più alti come coordinate in cui sono stimate le linee della griglia. Non funziona perfettamente (ad es. I bordi forti nell'immagine vengono rilevati erroneamente come linee della griglia), ma mostra l'idea. Può essere migliorato, ad esempio, dalla trasformazione di Hough per trovare linee, eliminare bordi molto forti ecc.

In alternativa, se la griglia è davvero la stessa per tutte le immagini, è possibile eseguire il rilevamento della griglia congiuntamente per tutte le immagini, il che produrrebbe una precisione molto migliore (basta fare la tecnica sopra, ma prima di scegliere i picchi, riassumere i risultati da tutte le foto). Più in dettaglio, calcoleresti eX per tutte le immagini e sommeresti tutti questi eX in un unico vettore. Questo vettore avrà una struttura di picco molto più chiara e la soglia può essere eseguita più facilmente.


Grazie per il tuo contributo! Il tuo risultato qui è davvero bello! Ci proverò. Disclaimer: sono un principiante nell'elaborazione delle immagini, quindi mi ci vorrà un po 'di tempo per lavorare da solo, ma lo segnerò risolto poiché funziona così bene da parte tua. In quale ambiente stai eseguendo questo algoritmo? Penso che il rilevamento indesiderato dei bordi su strumentazione e infrastruttura nell'immagine non costituirà un grosso problema in quanto la maggior parte delle immagini non include nulla di tutto ciò e sono solo tundra e / o acqua. Come fai a sommare i picchi da tutte le immagini?
Stephen E,

Grazie! L'ambiente è Python e ho appena aggiunto una nota su cosa intendo con la sintesi dei picchi per tutte le immagini.
Maximilian Matthé,

3

Ho provato un algoritmo davvero semplice di eseguire un filtro mediano 3x3 sui canali R e G di quell'immagine e funziona abbastanza bene. inserisci qui la descrizione dell'immagine Il codice Python è davvero semplice:

import scipy.signal as sp
from scipy import ndimage

image = ndimage.imread('Ahrnl.jpg', flatten=False)
image_filtered = np.array(image)
for i in range(2) :
  image_filtered[:,:,i] = sp.medfilt2d(image[:,:,i])

In alternativa puoi utilizzare il filtro del dominio delle frequenze come discusso in questa domanda: /programming/34027840/removing-periodic-noise-from-an-image-using-the-fourier-transform

La trasformata di Fourier della tua immagine mostra chiaramente alcuni "punti" ripetuti nello spettro corrispondente a questo rumore periodico. inserisci qui la descrizione dell'immagine

Come ha sottolineato Maximilian, quest'ultimo metodo funziona bene solo se il rumore è perfettamente periodico, il che non sembra essere il caso qui.

Ho provato a eseguire un filtro davvero stupido che azzera 5x5 quadrati di bin di frequenza centrati attorno a multipli di 9 in entrambe le direzioni xey e che (in qualche modo) sopprime il rumore ma introduce artefatti in posizioni che non contengono rumore (ad es. cielo).

Si può forse fare di meglio con un'attenta progettazione del filtro a intaglio invece di azzerare direttamente i contenitori FFT ( non farlo mai in pratica! ) E applicare il filtro solo nelle regioni dell'immagine in cui è presente il rumore (cioè non filtrare il cielo).

inserisci qui la descrizione dell'immagine


nell'ultima riga, credo che sia sufficiente filtrare due volte il canale rosso (l'ultimo indice dovrebbe essere io, non 0)
Maximilian Matthé,

@ MaximilianMatthé buona cattura! (Fortunatamente il mio vero codice che ho eseguito era ok: P)
Atul Ingle

Per quanto riguarda il metodo di trasformata di Fourier: funziona in modo affidabile solo se la griglia è veramente regolare (ovvero la stessa distanza tra tutte le linee). Non sono riuscito (almeno non rapidamente) a trovare parametri tali da poter tracciare una griglia regolare sopra le linee danneggiate. Quindi, anche il metodo di Fourier non sarebbe in grado di rimuovere questo rumore non esattamente periodico.
Maximilian Matthé,

@ MaximilianMatthé hai ragione - il metodo FFT è complicato in quanto il rumore non è perfettamente periodico. Ma potrebbe funzionare con un'attenta progettazione del filtro notch. Può essere.
Atul Ingle,

Grazie per il tuo contributo! Ho provato un filtro mediano 3x3 in Matlab e mentre rimuoveva la griglia (principalmente) non mi piaceva la riduzione dei dettagli dell'immagine (devono apparire in un pop-up su un'applicazione di web mapping.
Stephen E
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.