2013-09-24 23 views
8

Sto lavorando con immagini tif estremamente grandi che sto componendo in un'unica grande immagine. Ho una libreria creata da un mio collega che genera la piramide dell'immagine e fornisce uno strumento molto utile per visualizzare la piramide dell'immagine. Questo visualizzatore è ideale per dare un picco all'immagine grande e identificare visivamente i punti di interesse, ma i clienti sono più interessati all'analisi delle immagini su queste immagini di grandi dimensioni.Java - Come scrivere un'immagine tif grande (20.000x20.000 px o più grande)

Pertanto, è necessario esportare l'immagine molto grande in un singolo file. Trovo che ciò sia problematico considerando che queste immagini possono essere ovunque da 800 MB a dimensioni multiple di GB. E il solo compito di caricare questa singola immagine in memoria è impegnativo, in particolare quando si esegue l'analisi delle immagini.

Mi stavo chiedendo, se fosse possibile in Java scrivere questa grande immagine tiff in un blocco o riga per riga. Attualmente la mia applicazione sta esaurendo la memoria su macchine piccole (8 GB RAM).

L'attuale metodo per comporre queste immagini è:

  1. Memorizzare i valori dei pixel in una BufferedImage utilizzando un WritableRaster

    short[][]pixels = ... 
    BufferedImage image = new BufferedImage(width, height, type); 
    WritableRaster = image.getRaster(); 
    for (int row = 0; row < height; row++) 
    { 
        for (int col = 0; col < width; col++) 
        { 
         raster.setSample(col, row, 0, pixel[row][col]); 
        } 
    } 
    
  2. e quindi scrivere l'immagine tamponata a disco. Per questa parte sto usando ImageJ per scrivere l'immagine come tif. Se ci sono modi migliori che supportano 16 bit immagini TIF in scala di grigi, allora sarò felice di dare un'occhiata

    // BufferedImage image; from above 
    ... 
    ImagePlus img = new ImagePlus(); 
    img.setImage(image); 
    FileSaver fs = new FileSaver(img); 
    fs.saveAsTiff(file.getAbsolutePath()); 
    

Il problema con questo metodo è che ha troppo grande di un ingombro di memoria per un 8GB della RAM.

Idealmente, quello che mi piacerebbe è avere un solo short[][]pixels. Questo è principalmente dovuto al fatto che ho bisogno di calcolare una funzione di fusione media, quindi un certo ingombro di memoria sarà lì. Anche in futuro aggiungerò una miscela lineare. Lo short[][]pixels dovrebbe occupare solo ~ 765 MB di RAM per i dati di 20k x 20k pixel, cosa che penso sia attualmente inevitabile, quindi per immagini più grandi ad esempio 100k x 100k pixel, mi auguro che i biologi non vogliano esportare questa immagine come richiederebbe 18 GB di RAM.

Successivamente modificheremo il codice per supportare l'esportazione di immagini estremamente grandi come il 100k x 100k. Per ora sto bene assumendo un pezzo di memoria per memorizzare i valori dei pixel iniziali.

Quindi, qual è un buon metodo per scrivere porzioni di un'immagine tif su disco, così posso supportare la scrittura di immagini core come le immagini 100k x 100k.

ho visto questo post: Write tiled output of TIFF, using ImageIO in Java

Ma appena discute il TIFF 6.0 spec. Ma esaminerò lo ImageOutputStreams. Tif è una bestia, quindi potrei semplicemente mordere il proiettile e incoraggiare i biologi a esportare solo le regioni di interesse.

EDIT: trovato una soluzione praticabile:

SCRITTORE: https://github.com/openmicroscopy/bioformats/blob/v4.4.8/components/scifio/src/loci/formats/out/TiffWriter.java

e

LETTORE: https://github.com/openmicroscopy/bioformats/blob/v4.4.8/components/scifio/src/loci/formats/in/TiffReader.java

pagina del gruppo principale: https://github.com/openmicroscopy/bioformats

+0

Puoi lavorare con l'immagine in sezioni, ad esempio quadrati da 10k px e unirli tutti insieme? –

+0

Non ho problemi a lavorare con quadrati di 10k px, il problema è come scriverli in un file tif. – Jameshobbs

+0

Dovresti forse dividere il problema. 1. Scrivi un file di dati di immagine grezza di grandi dimensioni. 2. Leggi quello e salva come tiff. Una volta che funziona, puoi cercare di farlo in 1 passaggio. – hyde

risposta

2

Ok ho trovato una buona soluzione per farlo in Java.

Grazie a @bdares per indicare BigTiff.

Ma confezionato con FIJI, esiste il gruppo di bioformati che ha implementato scifio.

Essi forniscono un certo numero di lettori/scrittori supportati, uno in cui essere un TiffReader/scrittore

https://github.com/openmicroscopy/bioformats/blob/v4.4.8/components/scifio/src/loci/formats/in/TiffReader.java

e

https://github.com/openmicroscopy/bioformats/blob/v4.4.8/components/scifio/src/loci/formats/out/TiffWriter.java

ho modificato il mio post originale. Grazie a tutti per i commenti, mi ha aiutato a guardare nella giusta direzione.

0

Hai una doppia serie di abbreviazioni. Invece di archiviarlo in memoria, è necessario memorizzarlo su disco e manipolarlo su disco. BufferedImage non aiuterà. È necessaria una libreria (o per scrivere una libreria) che consenta la manipolazione di un'immagine sul disco senza la necessità di caricare completamente l'immagine nella memoria.

Non si desidera accedere a ciascun valore singolarmente. Invece, vorrai fare qualcosa del genere:

  1. leggere un blocco (forse 4k, 8k o 40k cosa mai ha senso).
  2. elaborare l'intero blocco.
  3. scrive il blocco su disco.
  4. goto il passaggio 1 fino al completamento.
+0

Il problema principale qui è come scrivere blocco per blocco per un'immagine tif. Sto già cercando di scrivere il mio autore tif, ma tif non è il più semplice dei protocolli per fare uno scrittore. – Jameshobbs

+0

considera la creazione dell'immagine in un formato più semplice, quindi utilizza uno strumento di conversione per renderlo un tiff. – DwB

2

Contrariamente al tuo commento, non è davvero così difficile implementare il tuo autore TIFF.

La specifica è scaricabile here. Nello specifico, le pagine 13-14 sono (quasi) tutte le informazioni necessarie per capire cos'è il TIFF e come scriverlo.

Considerare che, in base alle specifiche 6.0 (aggiornate a settembre 2013), la dimensione massima dell'immagine è 4 GB. Suggerirei di passare a BigTiff. Le differenze nelle specifiche sono elencate sul secondo link.

+0

Questo è davvero molto interessante. Non ero a conoscenza del fatto che l'intestazione è limitata a 32 bit (4 GB) di dimensioni. Sembra che dovrò passare dalla scrittura ImageJ all'utilizzo dello scrittore di Fiji (o semplicemente usare libtiff). – Jameshobbs

3

Con il progetto SCIFIO, stiamo generalizzando il quadro I/O immagine Bio-Formati per indirizzare l'imaging scientifico in generale, oltre la microscopia e le scienze della vita. L'API SCIFIO è ora in beta e includes TIFF, che può ovviamente read e write in tile. Il feedback su API e bug su SCIFIO mailing list è sempre il benvenuto!