Volumen aus Bilddateien



  • Also ich habe einen Satz von Bilddaten(bmp) und möchte daraus ein volumen erzeugen, welches man dann mit einem volume rendering programm öffnen kann.
    Ich habe im moment einen volume renderer vorliegen, der nur .raw dateien liest.
    Aber an einem anderen format sollte es nicht scheitern, da der renderer, den ich im moment habe nur die basis bilden soll und weiter ausgebaut werden soll.
    Tipps, wie ich volume rendering direkt mit den bilddateien implementieren kann (bilddateien als slices einlesen) würden mir auch sehr helfen.
    Leider kann ich nichts dazu finden, ich finde immer nur verschiedenen volume renderer, die scheinbar jeder ihr eigenes format für volumendaten haben.

    Ich hoffe das hilft ein wenig mein problem besser zu verstehen.



  • Eine "Raw"-Datei enthaelt (genauso wie Deine Bitmaps) ein 2D-Slice mit einer Praezision zwischen 8 und 16 Bit.
    Du kannst die Bitmaps also leicht konvertieren indem Du einfach die "Grauwerte" sequenziell speicherst.



  • Würde es auch funktionieren, dass meine bitmaps auf diese art schichtweise in eine einzige .raw datei geschrieben werden können?

    Da der volume renderer, den ich habe das volumen aus einer einzigen .raw datei erzeugt.

    Ich habe ein paar beispiele solcher .raw dateien, weiß aber nicht, wie diese genau aufgabaut sind.
    Auf dieser Seite gibt es ein paar beispieldatensätze:
    http://www.gris.uni-tuebingen.de/edu/areas/scivis/volren/datasets/datasets.html



  • Ich habe ein paar beispiele solcher .raw dateien, weiß aber nicht, wie diese genau aufgabaut sind.

    Du siehst ja beispielsweise beim ersten Datensatz (Aneurism), dass es in einer Aufloesung von 256x256x256 bei 8bit pro Voxel vorliegt und die raw Datei gerade 256^3 Bytes gross ist.
    Es gibt also in dem Sinne keinen "Aufbau" sondern einfach nur sequentielle Voxelwerte.
    Haeufig werden die Slices zur einfacheren Handhabung einzelnd gespeichert; hier offenbar nicht.



  • Ich habe vor einiger Zeit mal ein Javaprogramm geschrieben, das genau das macht. Es wird davon ausgegangen, dass die Bilddateien durchnummeriert sind. Dann wird daraus ein Volumen Test.raw generiert. Musst mal gucken, ob das für Dich passend ist. Die raw.info-Datei, die erzeugt wird, ist eine Spezialität von mir. Ich generiere die, um ein paar mehr Informationen zum Einlesen von raw-Dateien zu bekommen. Es gibt übrigens nicht in dem Sinne ein raw-Format, sondern diverse Formate, die sich als .raw bezeichnen. Es ist also nicht klar, dass das generierte raw auch wirklich mit Deinem Volumenrenderer darstellbar ist.

    BTW: Ich sehe gerade, dass ich zur Generierung der Voxel-Werte des .raws den blauen Pixelwert nutze. Keine Ahnung, warum ich das gemacht habe. Musst Du vielleicht anpassen und den Mittelwert aus RGB nehmen.

    import java.util.*;
    import java.io.*;
    import javax.imageio.*;
    import java.awt.*;
    import java.awt.image.*;
    
    public class Images2Raw
    {
       public static void main (String[] args)
       {
          if (args.length == 0)
          {
             System.out.println("Usage: java Images2Raw files");
             System.exit(0);
          }
          BufferedImage[] images = createImages(args);
          System.out.println("Number of valid files: " + images.length);
          if (images.length == 0) System.exit(0);
          int width = images[0].getWidth();
          int height = images[0].getHeight();
          int depth = images.length;
          for (BufferedImage image : images)
          {
             if ((image.getWidth() != width) || (image.getHeight() != height))
             {
                System.out.println("Error: Width or Height differs between images.");
                System.exit(1);
             }
          }
          writeRawFile(images);
          writeRawInfoFile(width,height,depth);
       }
    
       public static void writeRawFile(BufferedImage[] images)
       {
          try
          {
             File file = new File ("Test.raw");
             BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(file));
             for (int z = 0 ; z < images.length ; ++z)
             {
                for (int y = 0 ; y < images[0].getHeight() ; ++y)
                {
                   for (int x = 0 ; x < images[0].getWidth() ; ++x)
                   {
                      // BLUE2GRAY
                      int value = images[z].getRGB(x,y) & 0x000000ff;
                      stream.write(value);
                   }
                }
             }
             stream.close();
          }
          catch (IOException e)
          {
             System.out.println("Error: Could not write raw-file.");
             System.exit(1);
          }
       }
    
       public static void writeRawInfoFile(int width, int height, int depth)
       {
          try
          {
             File file = new File ("Test.raw.info");
             BufferedWriter writer = new BufferedWriter(new FileWriter(file));
             writer.write("Width=" + width + "\n");
             writer.write("Height=" + height + "\n");
             writer.write("Depth=" + depth + "\n");
             writer.write("datatype = UNSIGNED_BYTE\n");
             writer.close();
          }
          catch (IOException e)
          {
             System.out.println("Error: Could not write raw.info-file.");
             System.exit(1);
          }
       }
    
       private static BufferedImage[] createImages(String[] fileNames)
       {
          Arrays.sort(fileNames);
          LinkedList<File> fileList = new LinkedList<File>();
          ImageFileFilter fileFilter = new ImageFileFilter();
          for(int i = 0 ; i < fileNames.length ; ++i)
          {
             final File currentFile = new File(fileNames[i]);
             if (!fileFilter.accept(currentFile))
             {
                System.out.println("Could not load file " + currentFile.getName());
                continue;
             }
             fileList.add(currentFile);
          }
          File[] imageFiles = fileList.toArray(new File[0]);
          BufferedImage[] images = new BufferedImage[imageFiles.length];
          try
          {
             for (int i = 0 ; i < imageFiles.length ; ++i)
             {
                images[i] = ImageIO.read(imageFiles[i]);
             }
          }
          catch (IOException e)
          {
             return null;
          }
          return images;
       }
    
       private static class ImageFileFilter implements java.io.FileFilter
       {
          private final String[] suffixes;   
    
          public ImageFileFilter()
          {
             String[] formatNames = ImageIO.getReaderFormatNames();
             TreeSet<String> suffixTree = new TreeSet<String>();
             for (String format : formatNames)
             {
                suffixTree.add("." + format.toLowerCase());
                suffixTree.add("." + format.toUpperCase());
             }
             suffixes = suffixTree.toArray(new String[0]);
          }
    
          public boolean accept(final File file)
          {
             if (!file.exists()) return false;
             if (file.isDirectory()) return false;
             final String fileName = file.getName();
             for (final String suffix : suffixes)
             {
                if (fileName.endsWith(suffix)) return true;
             }
             return false;
          }
       }
    }
    


  • Vielen Dank für eure Antworten.
    Ich werde das Beispielprogram mal ausprobieren und melde mich dannach nochmal, ob es damit funktioniert.



  • @Gregor:

    Es funktioniert mit deinem Programm 😃
    Ich danke dir wie verrückt...das hilft mir echt weiter



  • @funkycat13: Gern geschehen. Darf man fragen, was Du mit diesen Volumen eigentlich genau machst und an welcher Uni Du studierst? Es interessiert mich generell, wo man etwas in der Art macht.



  • @Gregor: Ich studiere an der Bauhaus Uni Weimar, wir wollen Daten die von Bauingenieuren aufgezeichnet wurden (Volumendaten verschiedener Baumaterialien) mittels volume rendering visualisieren, um sie auf diese Art untersuchen zu können.



  • funkycat13 schrieb:

    @Gregor: Ich studiere an der Bauhaus Uni Weimar, wir wollen Daten die von Bauingenieuren aufgezeichnet wurden (Volumendaten verschiedener Baumaterialien) mittels volume rendering visualisieren, um sie auf diese Art untersuchen zu können.

    Ah, interessant. Die haben bei uns glaube ich mal soetwas ähnliches mit Holzfaserplatten gemacht. Die sind mit der Platte zum DESY gefahren, haben dort mit Synchrotronstrahlung eine CT-Aufnahme davon gemacht und haben diese Aufnahme dann nachher untersucht, um herauszufinden, wie da genau die Fasern liegen. Visualisierung, Segmentierung und so weiter: Bei solchen Aufgaben kann man ne Menge machen. Dein Thema hört sich auf jeden Fall interessant an. Viel Spaß dabei. 😋


Anmelden zum Antworten