2010-03-11 12 views
10

Sto riscontrando un problema utilizzando l'interpolazione bilineare per dati a 16 bit. Ho due immagini, origImage e displayImage. Voglio usare AffineTransformOp per filtrare origImage attraverso un AffineTransform in displayImage che è la dimensione dell'area di visualizzazione. origImage è di tipo BufferedImage.TYPE_USHORT_GRAY e ha un raster di tipo sun.awt.image.ShortInterleavedRaster. Ecco il codice che ho adessoErrore Java nell'interpolazione bilineare di dati a 16 bit

displayImage = new BufferedImage(getWidth(), getHeight(), origImage.getType()); 
try { 
    op = new AffineTransformOp(atx, AffineTransformOp.TYPE_BILINEAR); 
    op.filter(origImage, displayImage); 
} 
catch (Exception e) { 
    e.printStackTrace(); 
} 

Per mostrare l'errore, ho creato 2 immagini con gradiente. Uno ha valori nell'intervallo di 15 bit (massimo di 32767) e uno nell'intervallo di 16 bit (massimo di 65535). Qui di seguito sono le due immagini

15 immagine po alt text

16 immagine po alt text

Queste due immagini sono state create nella moda identici e dovrebbe apparire identiche, a meno di notare la linea attraverso il centro del 16 bit image. All'inizio ho pensato che si trattasse di un problema di overflow, tuttavia è strano che si manifesti al centro del gradiente anziché alla fine dove i valori dei pixel sono più alti. Inoltre, se si trattasse di un problema di overflow, avrei il sospetto che anche l'immagine a 15 bit sarebbe stata interessata.

Qualsiasi aiuto su questo sarebbe molto apprezzato.

Mi stavo chiedendo perché nessuno risponde, ho fornito abbastanza informazioni? Sono necessarie più informazioni?

Di seguito è riportato il codice che utilizzo per generare AffineTransform. Tutte le variabili di riferimento sono calcolate sulla base dell'input dell'utente (movimento del mouse) e dovrebbero essere corrette (sono state testate da molte persone, incluso me stesso). Speriamo che questo possa aiutare con l'errore.

AffineTransform panTranslate = new AffineTransform(); 
panTranslate.translate(imagePanOffset.x, imagePanOffset.y); 

AffineTransform rotateCenterTranslate = new AffineTransform(); 
rotateCenterTranslate.translate(imageRotateCTR.x, imageRotateCTR.y); 
AffineTransform rotateTransform = new AffineTransform(); 
rotateTransform.rotate(Math.toRadians(rotateValue)); 
AffineTransform rotateAntiCenterTranslate = new AffineTransform(); 
rotateAntiCenterTranslate.translate(-imageRotateCTR.x, -imageRotateCTR.y); 

AffineTransform translateTransform = new AffineTransform(); 
translateTransform.translate(imageMagOffset.x, imageMagOffset.y); 

AffineTransform flipMatrixTransform = new AffineTransform(); 

switch (flipState) { 
    case ENV.FLIP_NORMAL: // NORMAL 
     break; 

    case ENV.FLIP_TOP_BOTTOM: // FLIP 
     flipMatrixTransform.scale(1.0, -1.0); 
     flipMatrixTransform.translate(0.0, -h); 
     break; 

    case ENV.FLIP_LEFT_RIGHT: // MIRROR 
     flipMatrixTransform.scale(-1.0, 1.0); 
     flipMatrixTransform.translate(-w, 0.0); 
     break; 

    case ENV.FLIP_TOP_BOTTOM_LEFT_RIGHT: // FLIP+MIRROR 
     flipMatrixTransform.scale(-1.0, -1.0); 
     flipMatrixTransform.translate(-w, -h); 
     break; 
} 

scaleTransform = new AffineTransform(); 
scaleTransform.scale(magFactor, magFactor); 

AffineTransform atx = new AffineTransform(); 
atx.concatenate(panTranslate); 
atx.concatenate(rotateCenterTranslate); 
atx.concatenate(rotateTransform); 
atx.concatenate(rotateAntiCenterTranslate); 
atx.concatenate(translateTransform); 
atx.concatenate(flipMatrixTransform); 
atx.concatenate(scaleTransform); 

Non ho ancora idea di cosa sta succedendo qui. Apprezzerei molto ogni aiuto che può essere fornito. Ho anche allegato un esempio del bug che si verifica in una immagine reale che incontro per maggiore riferimento.

Ecco il bug accadendo in una radiografia della mano alt text

Ecco una versione ingrandita fino concentrata sulla zona tra il pollice e l'indice. alt text

Nota ancora come il bug non si verifica nelle aree estremamente bianche, ma sui valori nel mezzo dell'intervallo dinamico, proprio come nell'immagine a gradiente.

Ho scoperto più informazioni. Stavo modificando alcune delle trasformazioni e ho scoperto che il bug non si verificava se filtravo attraverso una matrice di identità. Inoltre non si verifica se traduco da un importo intero. Si verifica se traduco da un importo non intero. Si verifica anche se eseguo lo zoom di qualsiasi valore diverso da 1 (intero o non). Speriamo che questo aiuti.

Dopo ulteriori esperimenti, l'errore si manifesta definitivamente ai pixel limite tra la metà dell'intensità massima (65535/2 = 32767,5). Si verifica anche SOLO a questo valore. Spero che questo possa aiutare la diagnosi !!

Su richiesta di AlBlue, ecco un codice completamente indipendente dalla mia applicazione che può generare il bug.Nota che nel post originale ho incluso un gradiente di immagine generato con il codice sottostante, tuttavia ho ingrandito uno di questi gradienti per mostrare meglio l'effetto. Dovresti vedere l'effetto quattro volte sull'immagine 0.5 tradotta e non su nessuna delle altre due immagini. Si noti inoltre che questo bug viene visualizzato durante il ridimensionamento di qualsiasi valore diverso da 1. Basta sostituire AffineTransform.getTranslateInstance() con AffineTransform.getScaleInstance (0.9, 0.9) per vedere anche il bug.

private static class MyJPanel extends JPanel { 
    BufferedImage displayImage = null; 
    public MyJPanel(double translateValue) { 
     super(); 
     BufferedImage bi = new BufferedImage(1024, 1024, BufferedImage.TYPE_USHORT_GRAY); 

     int dataRange = (int)Math.pow(2, 16); 
     double step = dataRange/(bi.getRaster().getDataBuffer().getSize()/4.0); 
     double value = 0; 
     for (int i=0; i<bi.getRaster().getDataBuffer().getSize(); i++) { 
      bi.getRaster().getDataBuffer().setElem(i, (int)value); 
      if (value >= dataRange) 
       value = 0; 
      else 
       value += step; 
     } 
     displayImage = new BufferedImage(bi.getWidth(), bi.getHeight(), bi.getType()); 
     AffineTransform tx = AffineTransform.getTranslateInstance(translateValue, translateValue); 
     AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR); 
     op.filter(bi, displayImage); 
    } 

    public void paint(Graphics g) { 
     super.paint(g); 
     g.drawImage(displayImage, 0, 0, this); 
    } 
} 

private static void showDisplayError() { 
    JDialog dialog1 = new JDialog(); 
    dialog1.setTitle("No Translation"); 
    MyJPanel panel1 = new MyJPanel(0); 
    dialog1.getContentPane().add(panel1); 
    dialog1.setSize(1024, 1024); 
    dialog1.setVisible(true); 

    JDialog dialog2 = new JDialog(); 
    dialog2.setTitle("Translation of 0.5"); 
    MyJPanel panel2 = new MyJPanel(0.5); 
    dialog2.getContentPane().add(panel2); 
    dialog2.setSize(1024, 1024); 
    dialog2.setVisible(true); 

    JDialog dialog3 = new JDialog(); 
    dialog3.setTitle("Translation of 1.0"); 
    MyJPanel panel3 = new MyJPanel(1.0); 
    dialog3.getContentPane().add(panel3); 
    dialog3.setSize(1024, 1024); 
    dialog3.setVisible(true); 
} 

Come un altro aggiornamento, ho appena provato questo su Fedora 10 e ho visto il bug è ancora presente.

+2

Sembra un problema di overflow, poiché sono proprio le tre righe di pixel che devono avere il colore RGB 128-128-128 che sono state modificate. (Sono sostituiti da una riga di 57-57-57, una riga di 232-232-232 e una riga di 151-151-151). Ma non ho idea del perché. –

+0

Grazie per la risposta. Queste immagini dovrebbero essere in scala di grigi, quindi dovrebbe esserci un solo canale, perché suggerisci i valori particolari che hai postato? – Jon

+0

Ho aperto le immagini png in Gimp e ho guardato i valori dei colori. Entrambi hanno un gradiente verticale uniforme da 0 a 255 (da 0x00 a 0xff), tranne le bande bianche e nere in alto e in basso e le tre righe di pixel problematiche nel mezzo della seconda immagine. Ma ancora, non ho idea da dove vengano. –

risposta

0

Hai risolto questo? È probabile che si tratti di un problema non utilizzando AffineTransformOp correttamente. Come hai creato AffineTransform atx? Se l'ho dovrei essere in grado di replicare per aiutare il debug.

Si potrebbe anche dare un'occhiata a questo site. Contiene molte informazioni utili su AffineTransformOp

+1

Ho pubblicato il codice per generare AffineTransform, fammi sapere se questo aiuta. – Jon

+0

E no non ho ancora trovato una soluzione a questo. – Jon

+0

Sei riuscito a trovare qualcosa guardando la fonte per AffineTransform? – Jon

2

Quale versione di java (java -version) e del sistema operativo stai utilizzando? Potrebbe trattarsi di un bug nella trasformazione (che è stato risolto) o potrebbe essere un errore nel rendering in PNG.

Hai provato a utilizzare un filtro NEAREST_NEIGHBOR invece di quello BILINEAR?

+0

Sì, sì, non appare mentre si usa il vicino più vicino. Tuttavia, dal momento che sto lavorando con dati medici, l'utente avrà dati a 16 bit visualizzati su monitor ad altissima risoluzione in cui l'interpolazione vicina più vicina non sarà sufficiente. – Jon

+0

Utilizzo Windows XP SP3 a 32 bit e Java 1.6.0_18 – Jon

+0

Non è un bug di rendering in PNG. Carico il file come file Dicom usando dcm4che (www.dcm4che.org) e creo un BufferedImage.Quindi dipingo questo BufferedImage sullo schermo e vedo l'errore. Ho scelto di salvarlo come PNG per mostrare il bug qui. – Jon

2

si può lavorare intorno ad esso applicando la trasformazione in un Graphics2D invece di un AffineTransformOp:

if (useG2D) { 
    Graphics2D g = displayImage.createGraphics(); 
    g.transform(tx); 
    g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
         RenderingHints.VALUE_INTERPOLATION_BILINEAR); 
    g.drawImage(bi, null, 0, 0); 
} else { 
    AffineTransformOp op = new AffineTransformOp(tx, AffineTransformOp.TYPE_BILINEAR); 
    op.filter(bi, displayImage); 
} 

Non so perché questo darebbe output diverso, ma lo fa.

Nota: useG2D potrebbe essere una costante o potrebbe essere impostata in base al risultato di tx.getType(). Il bug non si verifica con le trasformazioni TYPE_QUADRANT_ROTATION, TYPE_FLIP o TYPE_IDENTITY.

Problemi correlati