Fractal image compression

Fractal image compression è un'applicazione entusiasmante della teoria frattale, in particolare nella compressione dell'immagine.

Descrizione

Con questa applicazione, è possibile:

  • Comprimere le immagini con questo metodo frattale
  • Decomprimere le immagini precedentemente compresse in un formato diverso

Utilizza le librerie della piattaforma, che includono le seguenti funzionalità:

  • Multilingua
  • Zoom multi-risoluzione configurabile
  • Opzione modalità scura
  • Notifica nuova versione


Punti positivi:

  • Se programmato correttamente, funziona indipendentemente dalla risoluzione dell'immagine.
  • È un metodo di compressione distintivo
  • Ti permette di imparare mentre vai


Punti negativi:

  • Il processo di compressione è estremamente lento
  • Non si raggiungono rapporti di compressione molto elevati (almeno con i parametri che ho usato)

Descrizione del codice

Si tratta di un'implementazione di questofractal image compression Algoritmopubblicato in IEEE durante i miei giorni di college

L'applicazione utilizza la libreria di triangolazione incrementale Delaunay, che viene utilizzata anche nelDomanda di Morphing


Algoritmo di alto livello:

  • Compressione:
    • La compressione frattale si concentra sull'archiviazione delle relazioni tra le regioni dell'immagine piuttosto che sui valori reali dei pixel, in particolare tra i triangoli in questo caso.
    • L'immagine è divisa in una griglia triangolare composta da triangoli multipli, formando un dominio triangolare.
    • L'immagine è suddivisa in un nuovo insieme di triangolazioni con triangoli più grandi designati per il libro di codice.
    • Le triangolazioni sono dinamiche e l'algoritmo di divisione e fusione viene applicato in base alla varianza dei pixel del triangolo.
    • Una volta determinata la triangolazione per il codebook, vengono selezionati i triangoli 2n più rappresentativi per formare il codebook. Il valore di n influisce in modo significativo sul tempo di compressione pur avendo un effetto minore sul rapporto di compressione e sulla qualità raggiunta.
    • Per ogni triangolo di dominio, la mappatura ottimale con un triangolo dal codebook viene ricercata utilizzando un criterio minimo di errore quadrato medio (MSE).
    • La mappatura ottimale tra i triangoli si trova creando combinazioni di:
      • Permutazioni dei vertici (6 possibilità)
      • Determinazione di un offset per la media
      • Trovare un fattore di scala tra 0 e 1, che viene applicato alla deviazione dalla media. Questo fattore di scala dovrebbe rimanere tra 0 e 1 per prevenire la divergenza durante il processo di decompressione iterativa
      Inoltre, questi parametri dovrebbero essere quantificati utilizzando un numero limitato di bit per garantire che sia il tempo di compressione che il rapporto siano ragionevoli e in linea con la qualità desiderata.
  • Le informazioni memorizzate nel file compresso per ogni canale:
    • Le informazioni per riprodurre le due triangolazioni:
      • Triangoli che si dividono in ogni iterazione
      • Vertici che sono stati rimossi a seguito della fusione (dopo aver completato le iterazioni di divisione)
    • La selezione dei triangoli 2n del codebook
    • La mappatura ottimale di ogni triangolo di dominio:
      • Quale triangolo di codebook utilizza per mappare (n bit)
      • La permutazione ottimale del vertice (6 combinazioni, 3 bit)
      • Offset (gli autori indicano che l'offset è effettivamente rappresentato con 6 bit)
      • Scala (gli autori indicano che la scala è effettivamente rappresentata con 6 bit)
  • Decompressione (per ogni canale):
    • I triangoli delle due triangolazioni sono ottenuti.
    • I triangoli del codebook sono ottenuti.
    • Questo processo viene ripetuto fino al raggiungimento della convergenza:
      • La mappatura di tutti i triangoli di dominio per le loro corrispondenze ottimali con i triangoli di codebook


Dopo aver conseguito un Master in Intelligenza Artificiale, prevedo di innovare come ricavare i triangoli più significativi per il codebook applicando i K-medoidi.

Non sono sicuro se l’innovazione migliorerà o impedirà l’algoritmo, ma mi impedisce di dover programmarlo da solo, il che inizialmente sembrava complicato.


L'elaborazione delle immagini è divisa in canali, tipicamente RGB.

Utilizza il multiprocessing, con un filo dedicato a ciascun canale.


Con la versione v1.1 è stato aggiunto un lettore compatibile con lo standard ImageIO.

Pertanto, è possibile aprire un'immagine compressa (.dfc) con l'applicazione semplicemente facendo:

BufferedImage image = ImageIO.read("image.dfc");

Finestre

Fractal image compression v1.0 (2022-2024)

Guarda vdeo
Scarica

Fractal image compression v1.1 (2026)

Scarica

Versioni

image

L'applicazione implementa un algoritmo fractal image compression descritto in un documento IEEE dai miei giorni universitari. Si basa sulla triangolazione Delaunay e sulla codifica a blocchi.

Ho collaborato con un compagno di classe universitario per sviluppare la versione iniziale di questo algoritmo durante uno stage per l'ultimo corso di Teleco Television (piano 64 di Barcellona).

Internet era ancora nelle sue fasi iniziali, e qualsiasi progresso si basava quasi interamente sugli sforzi individuali e sui documenti fisici.

Ricordo che abbiamo sviluppato una triangolazione Delaunay abbastanza buona e implementato con successo l'approccio split and merge. Ciò ha comportato il calcolo dei triangoli più rappresentativi e la ricerca delle mappe ottimali durante il processo di codifica. Tuttavia, nonostante tre mesi di sviluppo intensivo, non abbiamo mai completato l'applicazione.

Ora, 25 anni dopo, vi presento questa nuova implementazione dell’algoritmo, completamente sviluppata e completata in un tempo record di due settimane.

Ovviamente, qualcosa sarà migliorato 25 anni dopo. Inoltre, questa volta con il supporto funzione aggiunto per gestire i triangoli, che avevo già programmato per l'applicazione effetto Morphing.

Questa volta utilizzando una libreria di triangolazione Delaunay programmata da professionisti.

È evidente che quando non devi fare i mattoni da solo, più velocemente puoi costruire le pareti...


Video dimostrativo

image

La nuova funzionalità nella versione v1.1 è l'aggiunta di un lettore di immagini compresso frattale all'interno dell'applicazione compatibile con ImageIO.

Pertanto, è possibile leggere un'immagine compressa (.dfc) con l'applicazione come segue:


BufferedImage image = ImageIO.read("image.dfc");


Confrontando l'immagine in formato.jpg e nel formato.dfc dell'applicazione, puoi vedere che la qualità è un po 'peggiore rispetto a.jpg e che occupa un file leggermente più grande (come previsto).

Ma il risultato non è affatto male.

Tuttavia, dato il lungo tempo di elaborazione richiesto per la compressione, questo tipo di compressione e la sua attuazione nell'applicazione sono solo di interesse accademico.


04/05/2026 - 04/12/2026 . Dopo aver recuperato l'evoluzione di questa applicazione, propongo di fare test con immagini reali, e lo provo con uno dei pixel "4000 x 3000".

Incontrerò molti problemi:

  • Il processo dura per sempre nelle iterazioni divise (a causa delle ampie triangolazioni fino a 400.000 triangoli, e che il controllo delle condizioni divise è stato ripetuto per tutti i triangoli in ogni iterazione)
  • La memoria si esaurisce dopo aver raggiunto il limite di 23 GB che avevo sul mio sistema. Perché:
    • Il risultato delle iterazioni split e merge è stato memorizzato in una lista booleana (circa 16 iterazioni x 2 tipi di triangolazione x 3 canali x 400.000 elementi!!!). Ciò rende un totale di circa 40.000.000 di elementi, che è ancora accettabile)
    • Inoltre, la selezione del libro dei triangoli più rappresentativi (impostati a 256) è stata effettuata con un K-medoidi (oltre 400.000 elementi) (penso che la memoria utilizzata da quell'algoritmo sia O(n2). Ora sta sfuggendo di mano...)
    • E, per più INRI, questi calcoli sono stati eseguiti in parallelo per i tre canali (rgb)!!
  • Una volta risolti questi problemi, riesco a comprimere l'immagine (4000 x 3000), ma vedo che ci vogliono tra 6 e 8 ore per completare il lavoro.

E propongo di risolverli:

  • Per l'eternalizzazione delle divisioni. Soluzione:
    • Incremento la dimensione minima dei triangoli da dividere, in modo graduale proporzionale al numero di pixel nell'immagine. Con conseguente riduzione del numero di triangoli nelle triangolazioni. Nell'immagine usata di (4000 x 3000) il numero di triangoli è diviso per più di 4 (siamo passati da circa 400.000 triangoli a circa 100.000 triangoli).
    • Inoltre, creo un Set con i triangoli che non soddisfano il criterio di divisione (relativo alla varianza dei valori dei loro pixel), in modo da non ripeterli in ogni iterazione. Ora vola!!
  • Il sistema sta esaurendo la memoria. Soluzione:
    • Risultato di scissioni e fusioni salvate in elenchi booleani. Soluzione:
      • Man mano che le iterazioni di divisione progrediscono, il numero di triangoli che si dividono è radicalmente più piccolo, la memoria utilizzata viene salvata memorizzando gli indici dei triangoli che si dividono in un insieme.
    • Memoria dei K-medoidi (presumibilmente O(n2)). Soluzione:
      • Poiché abbiamo diviso il numero di triangoli per 4..., la memoria necessaria per quell'algoritmo, questa riduzione dei triangoli comporta la divisione della memoria utilizzata da un fattore di circa 16.
      • Tre K-medoidi in parallelo (uno per ogni canale). Soluzione:
        • Sequenziamo i calcoli delle triangolazioni e la selezione dei triangoli più rappresentativi per il codice-libro (con K-medoidi).
      • Abbiamo diviso la memoria necessaria per i K-medoidi di 48!!
  • Il tempo di elaborazione con immagini "reali" dura per sempre (la compressione dell'immagine di esempio richiede tra 6 e 8 ore) con 3 thread, uno per ogni canale.
    • Rendere configurabile il numero di thread. (Configurandolo a 23 thread (il mio sistema ha 24 core), il tempo di elaborazione è ridotto a tre ore e mezza).
  • Effetti della soluzione:
    • L'effetto di dividere il numero di triangoli per 4 si traduce ovviamente in una notevole perdita della qualità dell'immagine compressa. Ma con così tanta risoluzione, non è così importante.
    • Quando si divide il numero di triangoli per 4, si fa anche la dimensione del file compresso da dividere, presumibilmente anche dell'ordine di 4.

Cerco anche di ridurre al minimo le dimensioni del file compresso, riorganizzando le informazioni da memorizzare.

L’idea è quella di indicare soprattutto nella codifica delle liste degli indici dei triangoli che si dividono in ciascuna delle iterazioni, la cui codifica triviale originale era quella di utilizzare un bit per triangolo, indicando se si divideva o meno.

Ho escogitato un algoritmo per cercare di ridurre al minimo le dimensioni necessarie per memorizzare ciascuno di questi insiemi di indici.

Penso che non sia sprecato... se sei curioso su questo sito vi racconto i punti chiave su cui mi sono basato.

Anche se forse sarebbe stato più utile cercare un compressore generale senza perdita come zip o 7z e applicarlo alla globalità del file compresso... Forse per la prossima volta.


Nell'ultima versione della consegna, è inclusa un'applicazione di interfaccia di comando, che traduce un archivio creato con versioni meno ottimizzate del codificatore, all'ultima versione del codificatore, che presumibilmente occupa meno spazio.

Utilizzando questa piccola nuova applicazione su una coppia di file con la codifica originale (uno di 143x143 e un altro di 4000x3000), è che la dimensione del file compresso è ridotta di circa il 4% in loro.

Video

Scaricamenti