AWT Absolut verzweifelt: Faltung 2D Bearbeitung

brokkoli

Mitglied
Hallo zusammen,
Ich bin neu hier und hoffe ich breche hier keine Forenregeln, bin aber grad absolut verzweifelt..
Ich bin z.Z. im Kurs Grundlagen der Programmierung und habe morgen die Abgabe der letzten Übung leider fehlen mir immer noch Punkte zur Prüfungszulassung und ich komme bei der letzten Aufgabe einfach 0 draus, obwohl ich nun schon seit Stunden davor sitze... jetzt wollte ich mal hier nach Hilfe fragen was überhaupt zu tun ist? Ich bin grad echt verzweifelt, da ich die Aufgabe unbedingt lösen muss und leider keine Ahnung habe wie ich vorgehen soll..


Java:
import ch.unibas.informatik.cs101.ImageWindow;
import java.awt.image.BufferedImage;
import java.awt.Color;
import java.io.File;
import java.io.IOException;

public class FaltungsKern {

    float[][] kern;
    float norm;
    float gain;

    public FaltungsKern() {
        //TODO erstelle einen Faltungskern mit standart Werten
    }

    public FaltungsKern(String filename) {
        //TODO erstelle Faltungskern aus dem File
    }

    public void falten(ImageWindow iw) {
        //TODO wende den Faltungskern auf das Bild an
    }

    public void falten_grau(ImageWindow iw) {
        //OPTIONAL
        // berechne den Grauwert als (Rot+Grün+Blau)/3
        // Falte das Bild nur einmal pro (x/y) Stelle
        // schreibe in jeden Farbkanal diesen Wert
    }

    public void median(ImageWindow iw) {
        //OPTIONAL
        // lies alle Werte aus dem Bild im Bereich des Faltungskerns
        // speichere die Werte in einer Liste
        // setze das Zielbild auf den Wert welcher in der Liste in der Mitte steht
    }

    public void lade_kern(String filename) {
        //TODO lies die Daten aus dem File
    }
}


Aufgabe 3 von:
http://informatik.unibas.ch/fileadm...grammierung/Uebungen/cs101_uebungsblatt11.pdf
 
Zuletzt bearbeitet von einem Moderator:

brokkoli

Mitglied
Ich habe es mit dem BufferedReader versucht, habe es geschafft irgendwie in ein String array die jeweiligen Zeilen eines Kerns zu speichern, aber ich verstehe nicht, was ich mit diesen Werten machen soll, geschweige denn, wie ich es dazu bringe, dass nur die zahlen aus diesem Array gelesen werden sollen. Um jegliche Tipps, wie ich einen Schritt weiter komme wäre ich sehr dankbar!

Grüsse
 

stg

Top Contributor
Teilaufgabe 1: Lies das Textfile ein und speichere die Daten in deinem 2D-float Array. Vergiss zunächst mal den ganzen Kladeradatsch bezüglich Faltung usw sondern kümmere dich nur um diese eine Aufgabe. Hilfreich dabei sind zum Beispiel Klasse java.util.Scanner und/oder die Methode Float.parseFloat()
Wenn du dabei Probleme hast, dann komm mit konkreten Fragen hierzu wieder zurück.
Ansonsten, wenn du dieses Teilproblem gelöst hast, dann können wir einen Schritt weiterschauen.
 

brokkoli

Mitglied
Code:
String c=null;
FileReader f = new FileReader("kern1.txt");
                 BufferedReader bf = new BufferedReader(f);
               int i=0;
               while((c = bf.readLine()) != null) { 
                  array[i++]=c;
     
               }

Erstmal, vielen Dank für deine Antwort stg!

Obenstehend den Code, den ich bisher habe... Macht das Überhaupt Sinn, den Inhalt in einem Stringarray zu speichern? Ich dachte an eine .split Methode, aber das geht dann irgendwie bei data nicht auf...

Ich habe 5 verschiedene Kerne, 1 File Sieht z.b. so aus:

size 5 5
norm 1 13
gain 0
data 0 0 1 0 0 0 1 1 1 0 1 1 1 1 1 0 1 1 1 0 0 0 1 0 0

  • Ich glaube ich habe ein grundsätzliches Verständnisproblem: ich soll die Zahlen von data durch die norm konstante teilen (1/13). und wieso benötige ich dann genau ein 2 Dimensionales Array?

  • Den Scanner kannte ich bisher nur als Benutzereingabe, muss der für diesen Zweck gleich deklariert werden also: Scanner scan=new Scanner(System.in) ?
Vielen Dank
 

JStein52

Top Contributor
Hallo,

du könntest die Datei zeilenweise einlesen so wie du es oben stehen hast. Dann splittest du jede Zeile
an den whitespaces und behandelst jeweils den Fall "size", "norm", "gain" und "data" getrennt weiter. z.B. so:

Code:
String[] pieces = currentLine.split("\\s+");

if pieces[0].equals("size") {
    numberOfRows = Integer.parseInt(pieces[1]);
    numberOfColumns = Integer.parseInt(pieces[2]);
    kern = new double[numberOfRows][numberOfColumns];
}
else if pieces[0].equals("gain") {
   .... irgendwas
}

// usw.
// und aus numberOfRows und numberOfColumns weisst
// du ja auch wie viele data-Werte du parsen musst
// Und  beim abspeichern in kern kannst du sie auch gleich normieren.
 

JStein52

Top Contributor
Und um deine Frage nach dem 2D-Array zu beantworten: Das brauchst du deshalb weil ein Faltungskern nun mal ein 2D-Gitter ist, siehe Aufgabenstellung. Und sollst du eigentlich durch 1/13 (als Beispiel) teilen oder damit multiplizieren ??
 

brokkoli

Mitglied
Erstmal Danke für die Antwort JStein52!

Ich bin nun inzwischen einige Schritte weitergekommen, hier mal meinen Code:
Für den FaltungsKern:
Java:
//package ch.unibas.informatik.cs101;

import java.awt.image.BufferedImage;
import java.awt.Color;
import java.awt.Point;
import java.io.*;
import java.io.IOException;
import java.util.Arrays;

public class FaltungsKern {
    int size = 0;
    float[][] kern;
    float norm;
    float gain;

    public FaltungsKern() {
        lade_kern(
                "kern1.txt");
    }

    public FaltungsKern(String filename) {
        lade_kern(filename);
    }

    public void falten(ImageWindow iw) {

        Point point = iw.getMousePos();
        System.out.println("Aktueller Punkt: " + point);
        int ls = point.x - size / 2; // linksstart
        int os = point.y + size / 2; // obenstart
        float red = 0;
        float blue = 0;
        float green = 0;
        for (int i = 0; i < kern.length; i++) { // Koordinaten in der Maske
            for (int j = 0; j < kern[i].length; j++) {
                float kernelvalue = kern[i][j];

                Color c = iw.getPixel(ls + i, os + j); // über das Bild wird Kernmaske gelegt, Start obenlinks
                                                    
                red += c.getRed() * kernelvalue;
                blue += c.getBlue() * kernelvalue;
                green += c.getGreen() * kernelvalue;

            }
        }
        red += gain;
        blue += gain;
        green += gain;

        iw.setPixel(point.x, point.y, Math.round(red), Math.round(green), Math.round(blue));
    }


    public void lade_kern(String filename) {
        try {
            File kern1 = new File(filename);
            FileReader f = new FileReader(kern1);
            BufferedReader bf = new BufferedReader(f);

            String c = null;
            int i = 0;

            while ((c = bf.readLine()) != null) {
                String[] sarray = c.split("\\s+");
                if (i == 0) { // Damit initialisiert
                    size = Integer.parseInt(sarray[1]); // Immer quadratisch

                }
                if (i == 1) {
                    int zaehler = Integer.parseInt(sarray[1]);
                    int nenner = Integer.parseInt(sarray[2]);
                    norm = (float) zaehler / (float) nenner; // casten um
                                                                // Verlust zu
                                                                // vermeiden
                }
                if (i == 2) {
                    gain = Float.parseFloat(sarray[1]);
                }

                if (i == 3) {
                    kern = new float[size][size];
                    int stringposition = 1;
                    for (int j = 0; j < size; j++) {
                        for (int l = 0; l < size; l++) {
                           
                            kern[j][l] = ((Float.parseFloat(sarray[stringposition])) * norm); // Array auffüllen
                                                                               
                            stringposition++;
                        }
                    }
                }
                i++;
            }

            f.close();
        } catch (IOException e) {
            System.out.println("Fehler: " + e.toString());
        }
    }

    @Override
    public String toString() {
        return "FaltungsKern [kern=" + Arrays.deepToString(kern) + ", norm=" + norm + ", gain=" + gain + "]"; // um
                                                                                                                // aus
                                                                                                                // jedem
                                                                                                                // array
                                                                                                                // einen
                                                                                                                // String
                                                                                                                // zu
                                                                                                                // machen
    }

}

Die Main-Methode:
Java:
//package ch.unibas.informatik.cs101;

import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class BasicImageProcessing {
    static final int defaultimagewidth=640;
    static final int defaultimageheight=640;
   
    public static void main(String[] args) throws IOException {
        if (args.length != 2) {
            System.out.println("Falsche Anzahl Argumente!");
            System.exit(-1);
        }
        String kernelpath=args[0];
        String picturepath=args[1];
        if(!(new File(kernelpath)).isFile()){
            System.out.println("Kernpfad nicht gefunden");
            System.exit(-1);
        }
        if(!(new File(picturepath)).isFile()){
            System.out.println("Bildpfad nicht gefunden");
            System.exit(-1);
        }
        System.out.println("Kernpfad: "+kernelpath);
        System.out.println("Bildpfad: "+ picturepath);
        FaltungsKern faltungsKern = new FaltungsKern(kernelpath); //Übergabe Kernpfad an Konstruktor
        BufferedImage img = ImageIO.read(new File(picturepath));
        ImageWindow image=new ImageWindow(defaultimagewidth, defaultimageheight);
        image.setImage(img);       
        image.openWindow();
        while(true){
           
           
            if(image.mousePressed()){
                faltungsKern.falten(image);
               
               
            }
           
            if(image.isKeyDown(KeyEvent.VK_ESCAPE)){
                System.out.println("Quit");
               
                break;
            }
           
            image.pause(100);
            image.redraw();
           
            if(!image.isWindowOpen()){ //überprüft ob Fenster noch offen
                break;
            }
        }
        image.closeWindow();
       
    }

   

}

Nun, ich habe es geschafft, dass der Mauszeiger erkannt wird, jedoch weiss ich nicht, wie ich das Bild dazu bringe, dass es sich Update, sprich wenn ich klicke sehe ich keinen Effekt... Ich denke ich mache da etwas bei der redraw(); Methode komplett falsch?
 

Oben