2016-07-14 5 views
0

In meinem Java-Programm wird ein Bild in das Programm geladen, dann mit der diskreten Wavelet-Transformation transformiert und die resultierenden Koeffizienten werden als Bilddaten für das Ausgabebild verwendet.Diskrete Wavelet-Transformation in Java erzeugt weiße Flecken im Bild

Das Verfahren funktioniert mit natürlichen Bildern: http://imgur.com/Pk3kUs7

Allerdings, wenn ich zum Beispiel ein cartonish Bild verwandeln, weiße Flecken auf dunkle Ränder erscheinen int er Annäherung Teilband: http://imgur.com/kLXyBvd

Hier ist der Code für die ist forwardDWT:

private int[][] transformPixels(int[][] pixels, int widthHeight) { 
    double[][] temp_bank = new double[widthHeight][widthHeight]; 
    double a1 = -1.586134342; 
    double a2 = -0.05298011854; 
    double a3 = 0.8829110762; 
    double a4 = 0.4435068522; 

    // Scale coeff: 
    double k1 = 0.81289306611596146; // 1/1.230174104914 
    double k2 = 0.61508705245700002;// 1.230174104914/2 
    for (int i = 0; i < 2; i++) { 
     for (int col = 0; col < widthHeight; col++) { 
      // Predict 1 
      for (int row = 1; row < widthHeight - 1; row += 2) { 
       pixels[row][col] += a1 * (pixels[row - 1][col] + pixels[row + 1][col]); 
      } 
      pixels[widthHeight - 1][col] += 2 * a1 * pixels[widthHeight - 2][col]; 

      // Update 1 
      for (int row = 2; row < widthHeight; row += 2) { 
       pixels[row][col] += a2 * (pixels[row - 1][col] + pixels[row + 1][col]); 
      } 
      pixels[0][col] += 2 * a2 * pixels[1][col]; 

      // Predict 2 
      for (int row = 1; row < widthHeight - 1; row += 2) { 
       pixels[row][col] += a3 * (pixels[row - 1][col] + pixels[row + 1][col]); 
      } 
      pixels[widthHeight - 1][col] += 2 * a3 * pixels[widthHeight - 2][col]; 

      // Update 2 
      for (int row = 2; row < widthHeight; row += 2) { 
       pixels[row][col] += a4 * (pixels[row - 1][col] + pixels[row + 1][col]); 
      } 
      pixels[0][col] += 2 * a4 * pixels[1][col]; 
     } 

     for (int row = 0; row < widthHeight; row++) { 
      for (int col = 0; col < widthHeight; col++) { 
       if (row % 2 == 0) 
        temp_bank[col][row/2] = k1 * pixels[row][col]; 
       else 
        temp_bank[col][row/2 + widthHeight/2] = k2 * pixels[row][col]; 

      } 
     } 

     for (int row = 0; row < widthHeight; row++) { 
      for (int col = 0; col < widthHeight; col++) { 
       pixels[row][col] = (int) temp_bank[row][col]; 
      } 
     } 
    } 
    return pixels; 
} 

Dies ist die DWT mit dem CDF9/7 fitlerbanks das Lifting-Schema, ähnlich den DWT in JPEG2000 realisiert.

Der Algorithmus hat zwei Einschränkungen:

  1. Nur Graustufen- Daten
  2. werden, können die Breite und Höhe des Bildes verarbeitet, muss das gleiche, und ein Produkt von 2^n, beispielsweise sein, 256x256, 512x512 usw.

Weil es auch, dass die Grauwerte könnten falsch berechnet sein könnte, hier der andere Code ist das Bild zum Laden, Starten der Transformation, die Umwandlung der RGB-Werte in Graustufen und die Umwandlung zurück rgb:

public BufferedImage openImage() throws InvalidWidthHeightException { 
    try { 
     int returnVal = fc.showOpenDialog(panel); 
     if (returnVal == JFileChooser.APPROVE_OPTION) { 
      File file = fc.getSelectedFile(); 
      BufferedImage temp = ImageIO.read(file); 
      if (temp == null) 
       return null; 
      int checkInt = temp.getWidth(); 
      boolean check = (checkInt & (checkInt - 1)) == 0; 
      if (checkInt != temp.getHeight() & !check) 
       throw new InvalidWidthHeightException(); 
      int widthandHeight = temp.getWidth(); 
      image = new BufferedImage(widthandHeight, widthandHeight, BufferedImage.TYPE_BYTE_GRAY); 
      Graphics g = image.getGraphics(); 
      g.drawImage(temp, 0, 0, null); 
      g.dispose(); 

      return image; 

     } 
    } catch (IOException e) { 
     System.out.println("Failed to load image!"); 
    } 
    return null; 

} 

public void transform(int count) { 
    int[][] pixels = getGrayValues(image); 
    int transformedPixels[][]; 
    int width = pixels.length; 
    transformedPixels = transformPixels(pixels, width); 
    width/=2; 

    for (int i = 1; i < count + 1; i++) { 
     transformedPixels = transformPixels(transformedPixels, width); 
     width/=2; 
    } 
    width = pixels.length; 
    transformedImage = new BufferedImage(width, width, BufferedImage.TYPE_BYTE_GRAY); 
    for (int x = 0; x < width; x++) { 
     for (int y = 0; y < width; y++) { 
      transformedImage.setRGB(x, y, tranformToRGB(transformedPixels[x][y])); 
     } 
    } 

} 

private int tranformToRGB(double d) { 
    int value = (int) d; 
    if (d < 0) 
     d = 0; 
    if (d > 255) 
     d = 255; 
    return 0xffffffff << 24 | value << 16 | value << 8 | value; 
} 

private int[][] getGrayValues(BufferedImage image2) { 
    int[][] res = new int[image.getHeight()][image.getWidth()]; 
    int r, g, b; 
    for (int i = 0; i < image.getWidth(); i++) { 
     for (int j = 0; j < image.getHeight(); j++) { 
      int value = image2.getRGB(i, j); 
      r = (value >> 16) & 0xFF; 
      g = (value >> 8) & 0xFF; 
      b = (value & 0xFF); 
      res[i][j] = (r + g + b)/3; 
     } 
    } 
    return res; 
} 

Hinweis: Da die Breite und die Höhe des Bildes erwartet werden, gleich sein, ich benutze manchmal nur Breite auch für die Höhe.

EDIT: Wie @stuhlo vorgeschlagen, habe ich einen Scheck für Werte für die Annäherung Teilband in der forwardDWT hinzugefügt:

for (int row = 0; row < widthHeight; row++) { 
      for (int col = 0; col < widthHeight; col++) { 
       if (row % 2 == 0) { 
        double value = k1 * pixels[row][col]; 
        if (value > 255) 
         value = 255; 
        if (value < 0) 
         value = 0; 
        temp_bank[col][row/2] = value; 
       } else { 
        temp_bank[col][row/2 + widthHeight/2] = k2 * pixels[row][col]; 
       } 
      } 
     } 

Unfortunatly, jetzt die subabnd für die horizontalen Details wird schwarz.

+0

Haben Sie den Überlauf von 8 Bit während der DWT überprüft? Es kann der Fall sein, dass die Werte des erzeugten LL-Bandes (Approximationsteilband) mehr Bits benötigen, um gespeichert zu werden, und während der Umwandlung in 8-Bit-Grauwerte erhalten Sie 0 - weiße Punkte. – stuhlo

+0

@stuhlo Vielen Dank für Ihren Vorschlag. Ich habe eine Überprüfung für Werte über 255 und unter 0 in dem Deitnerleaving-Teil für das Approximationsteilband hinzugefügt. Die weißen Flecken sind jetzt verschwunden, aber auch das HL-Teilband (horizotal details subband). – darenkster

Antwort

1

Ihr Problem wird durch die Tatsache verursacht, dass Samples von Subbändern mehr Bits benötigen als Original-Image-Samples.

Ich würde vorschlagen, einen größeren Datentyp zu verwenden, um Beispiele von Subbändern zu speichern und sie wieder auf 8-Bit-Werte für die Anzeige zu normalisieren.

Verwandte Themen