# (Finger-)Abdruck einscannen



## Kampfzwereg (24. Jan 2012)

Hallo. 

Ich hab hier nen kleines Programm geschrieben. Mit diesem möchte ich gerne ein Bild einlesen und nach einem Fingerabdruckähnlichen gebilde suche.
Es gibt erst ne Methode , die das ganze Quadrat nur danach abscannt ob irgendwo nen Pixel ist, der farblich ist. Ich hatte mir gedacht erstmal klein anzufangen und nen schwarzweibild/schwarzes Bild zu nehmen und da nen roten Klekcs drauf zu machen. Dann wenn ein Pixel gefudnen wurde, check er mit der zweiten Methode ob das auch wirklich estwas Kreisartiges ist.Ist natürlich vorerst ein Ansatz und nach in der "Entwicklungsphase". 
Aber ich würde erstens gerne... 

....eure Meinung dazu hören, und ob der Ansatz an sich richtig ist?Produktive Kritik nehme ich gerne an.

....ob das Laufzeittechnisch sinnvol ist. Ich könntr mir vorstellen, dass das checken eines größeren Bildes irre lange dauert.

....ob jemand ne Idee hat warum ich ne ArrayOutOfBounds bekomme. Hier mal die Fehlermeldung:

```
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: Coordinate out of bounds!
	at sun.awt.image.ByteInterleavedRaster.getDataElements(ByteInterleavedRaster.java:318)
	at java.awt.image.BufferedImage.getRGB(BufferedImage.java:888)
	at QuadratEinlesen.checkQ(QuadratEinlesen.java:128)
	at QuadratEinlesen.checkAll(QuadratEinlesen.java:84)
	at QuadratEinlesen.checkQ(QuadratEinlesen.java:155)
	at QuadratEinlesen.checkAll(QuadratEinlesen.java:84)
	at QuadratEinlesen.jBanalysieren_ActionPerformed(QuadratEinlesen.java:177)
	at QuadratEinlesen$1.actionPerformed(QuadratEinlesen.java:46)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2018)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2341)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
	at javax.swing.DefaultButtonModel.setPressed(DefaultButtonModel.java:259)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(BasicButtonListener.java:252)
	at java.awt.Component.processMouseEvent(Component.java:6504)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
	at java.awt.Component.processEvent(Component.java:6269)
	at java.awt.Container.processEvent(Container.java:2229)
	at java.awt.Component.dispatchEventImpl(Component.java:4860)
	at java.awt.Container.dispatchEventImpl(Container.java:2287)
	at java.awt.Component.dispatchEvent(Component.java:4686)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4492)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
	at java.awt.Container.dispatchEventImpl(Container.java:2273)
	at java.awt.Window.dispatchEventImpl(Window.java:2713)
	at java.awt.Component.dispatchEvent(Component.java:4686)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
	at java.awt.EventQueue.access$000(EventQueue.java:101)
	at java.awt.EventQueue$3.run(EventQueue.java:666)
	at java.awt.EventQueue$3.run(EventQueue.java:664)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
	at java.awt.EventQueue$4.run(EventQueue.java:680)
	at java.awt.EventQueue$4.run(EventQueue.java:678)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:90
```



```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.io.*;
import java.awt.Color;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;

/**
  *
  * Beschreibung
  *
  * @version 1.0 vom 1/10/2012
  * @author
  */

public class QuadratEinlesen extends JFrame {
  // Anfang Attribute
  private JButton jBanalysieren = new JButton();
  private JLabel jLmoeglich = new JLabel();
  private JLabel jLgefunden = new JLabel();
  private JLabel jLcheckPos = new JLabel();
  // Ende Attribute

  public QuadratEinlesen(String title) {
    // Frame-Initialisierung
    super(title);
    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    int frameWidth = 300;
    int frameHeight = 300;
    setSize(frameWidth, frameHeight);
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    int x = (d.width - getSize().width) / 2;
    int y = (d.height - getSize().height) / 2;
    setLocation(x, y);
    Container cp = getContentPane();
    cp.setLayout(null);
    // Anfang Komponenten

    jBanalysieren.setBounds(8, 224, 273, 33);
    jBanalysieren.setText("Analysieren");
    jBanalysieren.setMargin(new Insets(2, 2, 2, 2));
    jBanalysieren.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        jBanalysieren_ActionPerformed(evt);
      }
    });
    cp.add(jBanalysieren);
    jLmoeglich.setBounds(8, 80, 209, 16);
    jLmoeglich.setText("Mögliches Quadrat gefunden");
    jLmoeglich.setFont(new Font("MS Sans Serif", Font.BOLD, 13));
    cp.add(jLmoeglich);
    jLgefunden.setBounds(8, 120, 136, 16);
    jLgefunden.setText("Abdruck gefunden");
    jLgefunden.setFont(new Font("MS Sans Serif", Font.BOLD, 13));
    cp.add(jLgefunden);
    jLcheckPos.setBounds(8, 160, 123, 16);
    jLcheckPos.setText("Checke Position");
    jLcheckPos.setFont(new Font("MS Sans Serif", Font.BOLD, 13));
    cp.add(jLcheckPos);
    // Ende Komponenten

    setResizable(false);
    setVisible(true);
  }

  // Anfang Methoden

   public void checkAll(int pX, int pY)
   {
      try
      {
        BufferedImage image = ImageIO.read(new File("img/abdruck.jpg"));
        for (int x = pX; x < image.getWidth(); x++)
        {
          for (int y = pY; y < image.getHeight(); y++)
          {
             Color color = new Color(image.getRGB(x, y));
             if(color.getBlue()>0 && color.getBlue()<255 &&
                color.getRed()>0 && color.getRed()<255 &&
                color.getGreen()>0 && color.getGreen()<255)
             {
               this.checkQ(x,y);
             }

          }
        }
      }
      catch(IOException e)
      {
         System.out.println("ERROR");
      }

   }

   public Quadrat checkQ(int x, int y)
   {
     try
     {
         int zaehler=0;
         int botY = y;
         BufferedImage image = ImageIO.read(new File("img/abdruck.jpg"));
         Color color;
         Color color2;
         Color color3;
         do
         {
            botY++;
            color= new Color(image.getRGB(x, botY));

         }while(color.getRed()>0 && color.getRed()<255  &&
                color.getGreen()>0 && color.getGreen()<255 &&
                color.getBlue()>0 && color.getBlue()<255 );
         int mid = botY-y;
         int rX = mid;
         int lX = mid;
         do
         {
            rX++;
            color2 = new Color(image.getRGB(rX, mid));
         }while(color2.getRed()>0 && color2.getRed()<255  &&
                color2.getGreen()>0 && color2.getGreen()<255 &&
                color2.getBlue()>0 && color2.getBlue()<255);
         do
         {
            lX--;
            color3 = new Color(image.getRGB(lX, mid));

         }while(color3.getRed()>0 && color3.getRed()<255  &&
                color3.getGreen()>0 && color3.getGreen()<255 &&
                color3.getBlue()>0 && color3.getBlue()<255 );
         for (int a =lX ; a <= rX ; a++)
         {
           for (int b = y ; b <= botY; b++)
           {
              Color color4 = new Color(image.getRGB(a, b));
              if(color4.getRed()>0 && color4.getRed()<255  &&
                 color4.getGreen()>0 && color4.getGreen()<255 &&
                 color4.getBlue()>0 && color4.getBlue()<255 )
               {
                 zaehler++;
               }
           }
         }
         if(zaehler>= (((rX-lX)*(botY-y))*0.8))
         {

           return new Quadrat(new Koordinate(lX,botY), new Koordinate(lX,y), new Koordinate(rX,y), new Koordinate(rX,botY));

         }
         else
         {

           this.checkAll(rX, botY);

           return null;
         }
     }
     catch(IOException e)
     {
        System.out.println("ERROR");

     }
     return null;
   }



   public void ermittlePos()
   {

   }
   
  public void jBanalysieren_ActionPerformed(ActionEvent evt)
  {
    checkAll(0,0);
  }

  // Ende Methoden

  public static void main(String[] args) {
    new QuadratEinlesen("QuadratEinlesen");
  }
}
```


```
public class Quadrat {

  // Anfang Attribute
  private Koordinate punktA;
  private Koordinate punktB;
  private Koordinate punktC;
  private Koordinate punktD;
  // Ende Attribute

  public Quadrat(Koordinate a, Koordinate b, Koordinate c, Koordinate d)
  {
     this.punktA=a;
     this.punktB=b;
     this.punktC=c;
     this.punktD=d;
  }

  // Anfang Methoden
  public Koordinate getPunktA() {
    return punktA;
  }

  public Koordinate getPunktB() {
    return punktB;
  }

  public Koordinate getPunktC() {
    return punktC;
  }

  public Koordinate getPunktD() {
    return punktD;
  }

  // Ende Methoden
}
```


```
public class Koordinate {

  // Anfang Attribute
  private int xWert;
  private int yWert;
  // Ende Attribute

  public Koordinate(int x, int y)
  {
     this.xWert=x;
     this.yWert=y;
  }

  // Anfang Methoden
  public int getXWert() {
    return xWert;
  }

  public int getYWert() {
    return yWert;
  }

  // Ende Methoden
}
```

Hoffe ihr könnt damit was anfangen 
LG Kampfzwereg


----------



## Michael... (24. Jan 2012)

Kampfzwereg hat gesagt.:


> ....eure Meinung dazu hören, und ob der Ansatz an sich richtig ist?Produktive Kritik nehme ich gerne an.


Allgmein: Erst einmal die grundlegenden Fertigkeiten des Programmierens lernen ;-) Sonst kann ich dazu nicht viel sagen, da ich mit Mustererkennung nichts zu tun habe.


Kampfzwereg hat gesagt.:


> ....ob jemand ne Idee hat warum ich ne ArrayOutOfBounds bekomme.


Hab's nur kurz überflogen, vermute weil 
	
	
	
	





```
lX
```
 ins negative läuft. Die Bedingung der while Schleife passt m.M. nicht ganz zu dem was in der Schleife passiert - zumindest wird so ein Fall nicht abgesichert.


----------



## irgendjemand (24. Jan 2012)

hab mal sowas ähnliches gebaut für n freund

problem : er wollte ein bot für das browsergame "pennergame" ... welche jedoch "klick-captchas" verwendet haben *mitlerweile auch nicht mehr das es wohl zu viele bots gibt*
lösung : raste-matrizen der "zahlen" welche aufgetaucht sind anlegen und diese mit dem captcha *vorher greyscaling* vergleichen ...
das ganze dauerte mit 105 matrizen *15 winkel für 7 matrizen* über ein 600x600 bild mit einer durchschnittlichen matrix-größe von 20x30 keine 2sec ... wobei mein code lange nicht optimal war ...
wenn dann ein match auftrat wurde dessen position mit nem http-request an den server gesendet

ist ja auch alles etwas egal .. nur mal so als anmerkung das sowas möglich ist
generell solltest du dich mal mit "Hough Transformation" beschäftigen ... wiki liefert dazu eine gute beschreibung ...

damit kannst du sehr einfach nach bereits vorliegenden mustern *den matrizen* innerhalb des ziel-bildes suchen und deren vorhanden-sein sowie die position ermitteln ...

ob mein code so noch lauffähig wäre wenn PG noch captchas verwenden würde weis ich nicht ... aber ich kann ihn dir trotzdem mal posten ...
das ganze ist dabei lediglich eine unsaubere portierung des damaligen php-bots ..


----------



## HimBromBeere (24. Jan 2012)

Musst du mal nach Matching-Algorithmen suchen, die werden z.B. in photogrammetrischen Auwertungen gebraucht (zum Lesen von Nummernschildern z.B.). Hintergrund ist der folgende:
Du brauchst eine Reihe von Vergleichsbildern, bei denen du für jedes Pixel die Abweichung zwischen deinem Bild und dem Vergleichsbild errechnest. Dann machst du eine statist. Auswertung über die Differenzen und der Gewinner ist das Bild mit den kleinsten Abweichungen zum Vergleichsbild (das größte Problem dabei dürfte sein, einen anständigen "Standard-Fingerabdruck" zu generieren, mit dem du diesen Vergleich dann durchziehen kannst). Wenn ich mich recht entsinne nannte sich das Ganze dann Korrelationskoeefinzientenmatrix oder so ähnlich.


----------



## Kampfzwereg (24. Jan 2012)

@Michael ... inwiefern geh ich da ins negative?


----------



## Michael... (24. Jan 2012)

Kampfzwereg hat gesagt.:


> @Michael ... inwiefern geh ich da ins negative?


Das ist eine reine Vermutung und liese sich mittels Debugger oder System.out.println() überprüfen. Auf jeden Fall tritt hier ja ein Wert ausserhalb der Bounds des Images auf. Und da IX ja nur verkleinert wird und ein paar Codezeilen vorher noch gültig war, kann es m.M. nur daran liegen, dass IX < 0
IX würde ja in folgendem Code negativ werden, wenn das Bild nach unten hin nicht mit einer Farbe "begrenzt" ist, bei der nicht mindestens ein Farbanteil entweder 0 oder 255 ist.

```
do
         {
            lX--;
            color3 = new Color(image.getRGB(lX, mid));
 
         }while(color3.getRed()>0 && color3.getRed()<255  &&
                color3.getGreen()>0 && color3.getGreen()<255 &&
                color3.getBlue()>0 && color3.getBlue()<255 );
```


----------



## Kampfzwereg (24. Jan 2012)

dass kan doch eigentlci hnicht sein ....ich hab nen bild genommen, was komplett schwarz ist, wo in dessen mitte ein roter fleck war. kann es sein, dass das schwarz nicht kompeltt 255,255,255 farbanteile hatte und er somit links aus dem bild gelaufen ist?

frage: welche farbe wäre denn simpel nachzuahmen, kommt selten vor und ist ziemlich genau festzulegen?


----------



## Michael... (24. Jan 2012)

Wie gesagt war das eine erste Vermutung von mir.
Da der Fehler hier auftritt, kann ja nur einer der beiden Werte ungültig sein:
[JAVA=128]color3 = new Color(image.getRGB(lX, mid));[/code]
Daher debuggen oder die Werte per System.out ausgeben lassen. Dann wüsste man schonmal welche Variable einen falschen Wert enthält und könnte weitere Schlussfolgerungen treffen.


----------



## irgendjemand2 (24. Jan 2012)

@Micha
die var heißt LX .. nicht IX xD ...

@TO
farb-bilder sind immer etwas schwieriger ...
wenn möglich würde ich vorher das bild grey-scalen ...
beudet : alle pixel deren farbwert (R+G+B)/3 kleiner als z.b. 125 ist werden 0 ... also schwarz ... und alle die über 125 liegen -1 .. also weis ...

dazu könnte man das hier nehmen


```
public BufferedImage get_captcha_grey(BufferedImage image) throws Exception
	{
		BufferedImage ret=image;
		int w=image.getWidth(), h=image.getHeight();
		for(int x=0; x<w; x++)
		{
			for(int y=0; y<h; y++)
			{
				int rgb=image.getRGB(x, y);
				String hs=Integer.toHexString(rgb);
				int r=Integer.valueOf(hs.substring(2, 4), 16).intValue();
				int g=Integer.valueOf(hs.substring(4, 6), 16).intValue();
				int b=Integer.valueOf(hs.substring(6, 8), 16).intValue();
				if((r+g+b)/3<=110)
					ret.setRGB(x, y, 0);
				else
					ret.setRGB(x, y, -1);
			}
		}
		return ret;
	}
```

dann könntest du einfach auf pixel schwarz testen ...

btw : someone stole / blocked my nick ... LAME


----------



## HoaX (24. Jan 2012)

Da kann wohl jemand keine Bit-Operatoren ... int -> String -> int ist teuer!


```
int a = 0x112233;
int r = (a >> 16) & 0xff;
int g = (a >> 8) & 0xff;
int b = a & 0xff;
```


----------



## irgendjemand2 (25. Jan 2012)

logic AND mit 0xFF kenn ich ... und bit-shift kenne ich auch ... nur bin ich mir bei letzterem einfach zu unsicher xD ...


----------



## Kampfzwereg (25. Jan 2012)

@irgendjemand2 :hm ok ...aber wnen ich einfahc nach nm Fingerabdruckähnlichen gebilde suche, wär das eher unklug, weil ja jetzt alle die gleiche farbe haben oder?

oder such ich dann nach fabrunterschieden. srpich er läuft so lange durch biser 20 pixel nebeneinander hat , die alle die gleiche farbe ham?


----------



## irgendjemand2 (25. Jan 2012)

da hast du n bissl was falsch verstanden .. oder auch ich .. keine ahnung ...

was ich sagen wollte : mit einem entsprechenden wert kannst du aus deinem *möglicherweise* farblichen oder graustufen-bild ein reines schwarz-weis bild erstellen ... also entweder : information da oder eben nicht ...
darauf kannst du dann mit bool weiter arbeiten ... in dem du dann einfach über das grey-scale bild läufst und es von einem komplexen "bild" in ein simples bool-array umträgst *könnte man auch dierekt in dem von mir gepostetem code machen* ...

dann brauchst du eine sog. matrix ... also eine vorlage *ebenfalls schwarz-weis oder gleich als bool-array* welche dir eine "grobe" vorstellung von dem liefert was du eigentlich suchst ... in deinem fall also eine art "standart" fingerabruck *dabei sollte man sich erstmal auf dimension *also höhe und breite* und eventuell winkel , skalierung und seite *so n mensch hat ja ne linke und ne rechte hand*  beschränken ...
damit kannst du dann ziemlich genau erstmal ausmachen wo sich auf deinem bild überhaupt etwas von interesse *also der fingerabdruck* befindet ...

dann nimmst du dir n rekursiven algorithmus der halt das von dir gefundene so lange rechteckig zu allen 4 seiten prüft bis an allen kannten nur noch weise pixel kommen ... du also in deinem bild-ausschnitt dann wirklich nur noch den finger abdruck hast ...

und DANN kannst du dich mit dem verbleibenen sub-image weiter beschäftigen und z.b. den fingerabdruck katalogisieren oder mit bereits katalogisierten vergleichen ... oder was auch immer du damit vorhast ...

es macht dir die arbeit einfacher da du nicht mehr mit so vielen daten rumhandtieren musst sondern nur mit wirklich denen die dich interessieren ...
was du dann mit dem ergebnis machen willst ist mir leider noch nicht ganz klar


----------



## Kampfzwereg (25. Jan 2012)

sagen wir so. ich bin schüler und hab nicht wirklich viel ahnung. desswegen wollte ich klein anfangen. Ich hab mir gedacht, nen ausgestreckter finger(mit nem ovalen goten punkt, oder was auch immer darauf) , den man über ein abbild einer tastzatur bewegt. naja und ich wollte erstmal , einen sich nicht bewegenden finger analysieren und seine position bestimmen. desswegen is dein vorschlag glaub ich auch nicht so sinnvoll, da ich dann zwar weiß, dass ich einen habe , aber nicht mehr wo, da er augeschnitten wurde.

vertsehst du jetztz was ich meine?


----------



## Michael... (25. Jan 2012)

Auch hier kannst Du das Bild "digitalisieren": Alle Pixel die Rot sind (ggf. mit passenden Toleranzen im Farbspektrum) bekommen eine einheitliche Farbe (z.B. Schwarz), die anderen werden weiß und schon hast Du ein "binäres" Abbild, mit dem Du recht einfach die Position des Fingers ermitteln kannst.


----------



## Kampfzwereg (25. Jan 2012)

hm ja dass hört sich logisch an. danke.

dann hab ich noch einzwei fragen zu dem Quelltext,den  irgendwer2 gepoprtset hat.


```
BufferedImage ret=image;
        int w=image.getWidth(), h=image.getHeight();
        for(int x=0; x<w; x++)
        {
            for(int y=0; y<h; y++)
            {
                int rgb=image.getRGB(x, y);
                String hs=Integer.toHexString(rgb);
                int r=Integer.valueOf(hs.substring(2, 4), 16).intValue();
                int g=Integer.valueOf(hs.substring(4, 6), 16).intValue();
                int b=Integer.valueOf(hs.substring(6, 8), 16).intValue();
                if((r+g+b)/3<=110)
                    ret.setRGB(x, y, 0);
                else
                    ret.setRGB(x, y, -1);
            }
        }
        return ret;
    }
```

erstens. wie kann man nem int  w zwei sachen zuweisen?
dann wird ja dem int rgb der RGB-wert an der stelle x,y zugewiesen. RGB = transparentwert oder?
diesen wert machen wa zu nem String. warum verwenden wir da nicht einfach tostring?
und dieser string wird dann in substrings aufgeteilt. wass mit denen dann geschiet ist mir auch unklar. 
und am ende checkt der, ob der farbwert unter oder über der hälfte ist und passt es an.


----------



## Michael... (25. Jan 2012)

Kampfzwereg hat gesagt.:


> erstens. wie kann man nem int  w zwei sachen zuweisen?


Was heißt zwei Sachen zuweisen? Einer Variablen kann man nur einen Wert zuweisen.


Kampfzwereg hat gesagt.:


> RGB = transparentwert oder?


? Im RGB Farbraum gibt es keine Transparenz. Die ist diesem Fall auch nicht notwendig.


Kampfzwereg hat gesagt.:


> diesen wert machen wa zu nem String. warum verwenden wir da nicht einfach tostring?und dieser string wird dann in substrings aufgeteilt.


Die bessere Variante mit Bit Operationen wurde hier ja schon gepostet.


Kampfzwereg hat gesagt.:


> wass mit denen dann geschiet ist mir auch unklar.
> und am ende checkt der, ob der farbwert unter oder über der hälfte ist und passt es an


Es wird geprüft ob die Farbe einen entsprechenden Kriterium entspricht (hier: ob der Mittelwert der Farben >110 ist, in Deinem Fall könnte man prüfen ob der Rotanteil einen bestimmten Wert übersteigt und Blau und Grün möglichst klein sind)
Entsprechend dem Prüfergebnis wird der alte Farb Wert mit der einen oder der anderen Farbe überschrieben, so dass man am Ende ein zweifarbiges Bild erhält.


----------



## Kampfzwereg (25. Jan 2012)

ok das mit dem int hat sich geklärt....hab das komma dazwischen nciht gesehen. 




> Im RGB Farbraum gibt es keine Transparenz. Die ist diesem Fall auch nicht notwendig.


wärste denn auch noch so nett mir dann zu sagen, was das denn ist. Hab bei google geguckt. die methode get RGB gibt irgendeinen Transparentswert zurück .



> Die bessere Variante mit Bit Operationen wurde hier ja schon gepostet.



das beantwortet ja nicht meine frage .... wieso benuzt man den hier toHexString?


----------



## Michael... (25. Jan 2012)

Kampfzwereg hat gesagt.:


> wärste denn auch noch so nett mir dann zu sagen, was das denn ist. Hab bei google geguckt. die methode get RGB gibt irgendeinen Transparentswert zurück .


Was was ist? Der von der Methode zurückgeben Wert enthält zwar einen Transparenzwert. In Deinem Fall vermutlich immer 0xFF da ein JPG ja keine Transparenz haben kann.


Kampfzwereg hat gesagt.:


> das beantwortet ja nicht meine frage .... wieso benuzt man den hier toHexString?


toHexString wandelt einen Zahl in einen hexadezimalen String um. Das wurde hier gemacht, damit man man die einzelnen Farbwerte per substring() heraustrennen kann. Man hätte genausogut die Zahl mit toBinaryString in die Binärdarstellung wandeln können.
Aber es wurde ja bereits erläutert, dass dieses Vorgehen eher ungeschickt ist.


----------



## irgendjemand2 (25. Jan 2012)

wie gesagt : der code entstammt einer portierung des damaligen PHP-Pennergame-Flaschensammel-Bots ... und wurde entsprechend so auch in java implementiert

wie bereits erwähnt : natürlich kann man hier bit-ops nutzen ... der code ist aus dem jar 2009 ... hat also schon sein alter ... und ich hab versucht lediglich alles so umzusetzen wie es meine vorlage vorgab ... und dort wurden halt php-funktionen genutzt welche ebenfalls mit hex-strings gearbeitet haben ...

*vielleicht kennst du das von HTML/CSS ... wenn man dort einen farbwert angeben will macht man dies auch als hex-string in der form RRGGBB*

zu deinen fragen

"wie kann man nem int w zwei sachen zuweisen?"

und das mache ich bitte wo ?


```
int w=image.getWidth(), h=image.getHeight();
```
ist eine verkürzte schreibweise für

```
int w=image.getWidth();
int h=image.getHeight();
```
man sollte laut conventions nur das untere nutzen ...
das obere ist zwar so gültig ... aber nicht gerade sauber und wird beim compilen eh in das untere format umgesetzt ...
da der code nie für publizierung gedacht war habe ich an vielen stellen solche "kurz-formen" verwendet ... aber wie gesagt : gewöhn dir sowas bitte nicht an ! ... sowas kann man machen wenn man mal eben quick&dirty was basteln will ... wenn man aber vorhat seinen source zu publizieren sollte man sowas strikt unterlassen ... *es sieht einfach nicht schön aus , ist gegen die conventions ... und anfänger wie du überlesen häufig da komma*

"dann wird ja dem int rgb der RGB-wert an der stelle x,y zugewiesen. RGB = transparentwert oder?"

FALSCH
RGB ist der reine farb-wert : rot , grün , blau ... nix mit tranzparenz ... das wäre dann ARGB/RGBA bzw BGRA/ABGR ...
da das verwendete format JPG war und JPG nunmal keine transparenz hat war dieser wert immer 0xFF *glaub ich jetzt zumindest ... weis es aber nicht mehr genau ... kann auch 0x00 gewesen sein*
es kommt halt auf das eingangs-format an ...
in der regel ist dieser aber nur bei bildern mit ebenen oder sonstigen spielerein notwendig ... *wobei es auch viele 3D-engines gibt die anstatt den alpha-kanal eine feste farbe wie z.b. vollen blau-wert als transparenz-angabe nutzen *z.b. HL1-engine*

"die methode get RGB gibt irgendeinen Transparentswert zurück"

ist soweit richtig ... getRGB(int, int) gibt einen 32-bit int im format ARGB zurück .. also die ersten 8bit sind der alpha-kanal ... also die transparenz ...
da dies aber von JPG nicht unterstützt wird war es für mich nicht weiter von belang ...
es kommt also auf das daten-format an welches du benutzt ...

"diesen wert machen wa zu nem String. warum verwenden wir da nicht einfach tostring?
und dieser string wird dann in substrings aufgeteilt. wass mit denen dann geschiet ist mir auch unklar"

weil Object.toString() *bzw Integer.toString()* mir den zahlen wert zur basis 10 geliefert hätte .. also einen string mit dem ich so nichts hätte anfangen können da dieser nicht 255255255255 gewesen wäre sondern 0xFFFFFFFF was in java "-1" entspricht ... ich hätte also alles selbst rechnen müssen ...
mit toHexString() erhält man einen hex-string *alternativ auch Integer.toString(int, 16)* mit dem ich dann schon mehr anfangen kann ... weil man dann wirklich im string FFFFFFFF stehen hat ...
dieser wird dann in sub-strings gesplitet ... die ersten 2 FF sind der alpha-kanal .. den brauchte ich nich ... also nur die letzten drei 2er paare ...
diese werden dann mit parseString(String, 16) wieder in einen int umgewandelt ...
allgemein lies sich das damals so am einfachsten machen ...
der einfachere weg sind natürlich bit-ops ... aber da ich damals sowie heute davon nur grundlagen verstehe und ich einfach zu unsicher drin bin habe ich diesen umweg über hex-strings gewählt ... zwar nicht grad so super ... aber hat immerhin seinen zweg getan ...

den zweiten teile des quotes verstehe ich nicht : "was mit denen dann geschiet ist mir auch unklar" ...
du kennst sicher Integer.parseInt(String) mit dem du einen String in einen int parsen kannst ...
Integer.parseInt(String, int) gibt dir die möglichkeit den sog. radix ... also die basis zu bestimmen ...
in meinem fall waren das hexadezimale strings .. also basis 16 ...
wenn du dich mit solch grundlegenden api-methoden nicht auskennst solltest du dies dringen nachholen ...

"und am ende checkt der, ob der farbwert unter oder über der hälfte ist und passt es an"

genau ...
und da es für die muster-erkennung deutlich einfacher ist mit nem bool-array *also nem schwarz/weis bild* zu arbeiten als mit nem farb-bild ... und auch meine matrizen nur als solche daten vorlagen *waren auch schwarz/weis bilder mit einigen zusatz-informationen ... auf welche ich hier aber nicht weiter eingehe* ... und es schneller geht einen bool zu checken anstatt einen 32bit int ... lag einfach näher ...

"aber nicht mehr wo, da er augeschnitten wurde"
gut .. und was hindert dich daran dir einfach diese koordinaten in nem Point zu speichern ?
ist für mich weder sinnvoll noch erschließt sich mir daraus kein problem ...


da dir offenbar einiges an grundlagen fehlt würde ich dir raten noch eine stufe kleiner anzufangen *um mal mit deinen worten zu sprechen : "und hab nicht wirklich viel ahnung. desswegen wollte ich klein anfangen"*
gut ... dann fang noch kleiner an ... weil das was du vorhast ist ohne weitreichende java-grundlagen-kenntnisse und fachwissen in themen wie bild-mustererkennung wirklich schwer umsetzbar ...

wie bereits erwähnt : auch ich habe mir das alles nicht ausgedacht ... sondern lediglich vorhandenen source aus einer anderen sprache portiert ... und habe dadurch die funktions-weise kennen gelernt ...
ich habe mich auch vorher mit Hough-Transform auseinander gesetzt und es anfangs auch nicht wirklich verstanden ... nach dem ich dann aber diesen sehr umständlichen code portiert und dadurch einiges gelernt hatte habe ich auch Hough-Transform verstanden und bin auf dem gebiet der muster-erkennung weiter gekommen ...

aber wie gesagt : mit sowas kannst du dich beschäftigen wenn du die nötigen grundlagen drauf hast ... für den anfang mit so gut wie keinem basis-wissen über die grundlegensten klassen aus dem java.lang - pack ... wirst du es echt schwer haben da weiter zu kommen und auch code-snippets von anderen usern wie mir nur schlecht bis gar nicht verstehen ...

ich will dir dein vorhaben ja nicht ausreden ... aber meiner ansicht nach bist du noch nicht soweit um dich an sowas zu versuchen ... versuch erstmal basis-wissen zu erlangen ... und schau dir dann noch mal muster-erkennung an ...


[OT]nichts anderes macht OCR zum machinellen einlesen von handschriftlichen dokumenten ...
dabei wird auch nur *nach auswahl einer passenden schriftart-datei* über das bild gegangen und alle zeichen gescannt ...
positions-informationen und infos zum zu grunde liegenden "dokument" helfen dann der OCR-software daraus sinnvollen , für einen rechner verwertbare informationen zu generieren ...
leider funktioniert das nicht immer einwand frei so das es zu erkennungs-fehlern führen kann ..
aber OCR ist noch ein ganzes stück komplizierter als bloße muster-erkennung auf bool-basis[/OT]


----------



## HimBromBeere (28. Jan 2012)

@irgendjamand2: 


> Die Zitierfunktion (Sprechblase) kennst du, oder?



EDIT: Um mal auf die Frage mit der Zuweisung zweier Werte zu einer Variablen zurückzukommen: das geht durchaus, kenne ich aus den guten alten Zeiten von QBasic (furchtbare Sprache oder wie man das schimpfen mag...). Dafür muss man nur eine Trennpotenz definieren, z.B. 10^3. Alles, was rechts davon steht, ist Wert1, alles links davon ist Wert2 (auch wenn das bei Kommazahlen etwas deutlicher wäre). 

```
int Rohstoffe = 30001000;
```
heißt soviel wie 3000Holz, 1000Nahrung
Ist aber wie bereits gesagt eine uralte quick&dirty Methode, v.a. für Geräte, bei denen man nur wenig Speicherplatz (32kb...) hat und es auf jeden int ankommt, womit es in Zeiten von nahezu unbegrenzten Speichermethoden seine Relevanz verloren hat...


----------



## Kampfzwereg (20. Mrz 2012)

hallo zusammen. Tut mir wegen der langen pause schrecklich leid, ging aber nicht anders.

Also :
ich hab mir die Tipps mal zu Herzen genommen. Ich bin zu dem Schluss gekommen, das BIld in ein s/w- bild zu ändern und danach dieses dann in einen bool-array zu packen.
Dann könnte man ja laut den Beiträgen nach Mustern und einem Standartfingerabdruck suchen. Wo krieg ich denn so einen her?
Hat da einer einen Tipp wie man sowas rel. einfach hinkriegt? Ich hab mal bei google geguckt. Da bin ich nur zu foren gekommen, wo ich aber soeine Vorlage nicht finden konnte.

LG Kampfzwereg


----------



## Gossi (20. Mrz 2012)

Evtl. Hilfreich:
Insel
FH Regensburg (Quelltext der evtl. hilft)


----------



## Kampfzwereg (20. Mrz 2012)

ok danke. der zweite link ist evtl etwas. Ich glaub das wäre ein Link der mir generell bei meinem Projekt helfen könnte. Ich meinte eher zb nen Tutorial wie man sowas (einfach) selber machen könnte oder Vorlagen die man direkt kopieren kann. 

lg


----------



## Gossi (20. Mrz 2012)

Hmm, dazu habe ich leider nichts gefunden ^^


----------



## Kampfzwereg (20. Mrz 2012)

ja ok. der zweite Link schein mir ja auch schon sehr hilfreich. trotzdem hoffe ich noch auf einen Tipp der anderen : ]  ...


----------



## Kampfzwereg (22. Mrz 2012)

Also.... ich hab das Programm nochmal überarbeitet. Es hat jetzt mehrere Buttons , die alle eigentlich was können. 
Guckt es euch einfach mal an. Es ist noch nicht fertig und ich hab auch noch ein paar Problemchen:

1.Wenn ich erst ein Bild importiere, und dann auf übersetzten drücke, das heißt diese dann schwar/weiß anzeigen lassen will, dann soll er eigentlich das farbliche Bild oben zeichnen und das s/w-Bild darunter. Doch er zeichnet einfach nur 2 s/w-Bilder -.- .
2.Dann würd ich gernen die ProgressBars einfach der Schönheit halber nach dem button klick einmal bis hundert prozent laufne lassen( 2 sec. ca.) , hab ich schonmal probiert mit ner for-schleife bei nem ander Programm, aber die ging einfach direkt auf hundert.´Weiß einer genau wie sowas geht?
3.Weiß einer wie man dem Programm sagen soll, wenn das Bild zu groß ist, für den vorhandenen Platz, dann mach das ganze nen stück größer und wenn kleiner is, dann mach es nen bissel kleiner?


Hoffe da kann mir einer helfen... 
LG Kampfzwereg


```
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import java.io.*;
import java.awt.Color;
import java.awt.image.BufferedImage;
import javax.imageio.ImageIO;

/**
  *
  * Beschreibung
  *
  * @version 1.0 vom 1/10/2012
  * @author
  */

public class QuadratEinlesen extends JFrame {
  // Anfang Attribute
  private JButton jBanalysieren = new JButton();
  private JLabel jLmoeglich = new JLabel();
  private JLabel jLAbdruck = new JLabel();
  private JLabel jLcheckPos = new JLabel();
  private JProgressBar jProgressBar1 = new JProgressBar();
  private JProgressBar jProgressBar2 = new JProgressBar();
  private JProgressBar jProgressBar3 = new JProgressBar();
  private JLabel jLschrift = new JLabel();
  private JRadioButton jRBrichtig1 = new JRadioButton();
  private JRadioButton jRBfalsch1 = new JRadioButton();
  private JRadioButton jRBrichtig2 = new JRadioButton();
  private JRadioButton jRBfalsch2 = new JRadioButton();
  private JRadioButton jRBrichtig3 = new JRadioButton();
  private JRadioButton jRBfalsch3 = new JRadioButton();
  private JButton jBKoordinaten = new JButton();
  private int botY;
  private int topY;
  private int mid;
  private int lX;
  private int rX;
  private JButton jBsuche = new JButton();
  private JButton jBuebersetzten = new JButton();
  private JButton jBimport = new JButton();
  private BufferedImage hintergrund=null;
  private JFileChooser jfc1 = new JFileChooser();
  private int anzahlSpalten;
  private JButton jBArrayAusgeben = new JButton();
  private BufferedImage uebersetztesBild=null;
  private boolean gibtUebersetztesBild= false;


  // Ende Attribute

  public QuadratEinlesen(String title) {
    // Frame-Initialisierung
    super(title);
    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    int frameWidth = 737; 
    int frameHeight = 635;
    setSize(frameWidth, frameHeight);
    Dimension d = Toolkit.getDefaultToolkit().getScreenSize();
    int x = (d.width - getSize().width) / 2;
    int y = (d.height - getSize().height) / 2;
    setLocation(x, y);
    Container cp = getContentPane();
    cp.setLayout(null);
    // Anfang Komponenten

    jBanalysieren.setBounds(8, 104, 137, 81);
    jBanalysieren.setText("analysieren");
    jBanalysieren.setMargin(new Insets(2, 2, 2, 2));
    jBanalysieren.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        jBanalysieren_ActionPerformed(evt);
      }
    });
    jBanalysieren.setFont(new Font("Dialog", Font.PLAIN, 13));
    cp.add(jBanalysieren);
    jLmoeglich.setBounds(8, 525, 141, 20);
    jLmoeglich.setText("Analysiere Bilddatei");
    jLmoeglich.setFont(new Font("Dialog", Font.BOLD, 13));
    cp.add(jLmoeglich);
    jLAbdruck.setBounds(8, 549, 120, 20);
    jLAbdruck.setText("Abdruck checken");
    jLAbdruck.setFont(new Font("Dialog", Font.BOLD, 13));
    cp.add(jLAbdruck);
    jLcheckPos.setBounds(8, 571, 113, 20);
    jLcheckPos.setText("Checke Position");
    jLcheckPos.setFont(new Font("Dialog", Font.BOLD, 13));
    cp.add(jLcheckPos);
    jProgressBar1.setBounds(152, 520, 537, 25);
    cp.add(jProgressBar1);
    jProgressBar2.setBounds(152, 544, 537, 25);
    cp.add(jProgressBar2);
    jProgressBar3.setBounds(152, 568, 537, 25);
    cp.add(jProgressBar3);
    jLschrift.setBounds(304, 8, 201, 29);
    jLschrift.setText("Abdruck-Scanner");
    jLschrift.setFont(new Font("Dialog", Font.BOLD, 21));
    cp.add(jLschrift);
    jRBrichtig1.setBounds(696, 525, 25, 17);
    jRBrichtig1.setText("");
    jRBrichtig1.setFont(new Font("Dialog", Font.PLAIN, 13));
    cp.add(jRBrichtig1);
    jRBfalsch1.setBounds(712, 525, 25, 17);
    jRBfalsch1.setText("");
    jRBfalsch1.setFont(new Font("Dialog", Font.PLAIN, 13));
    cp.add(jRBfalsch1);
    jRBrichtig2.setBounds(696, 549, 25, 17);
    jRBrichtig2.setText("");
    jRBrichtig2.setFont(new Font("Dialog", Font.PLAIN, 13));
    cp.add(jRBrichtig2);
    jRBfalsch2.setBounds(712, 549, 25, 17);
    jRBfalsch2.setText("");
    jRBfalsch2.setFont(new Font("Dialog", Font.PLAIN, 13));
    cp.add(jRBfalsch2);
    jRBrichtig3.setBounds(696, 573, 25, 17);
    jRBrichtig3.setText("");
    jRBrichtig3.setFont(new Font("Dialog", Font.PLAIN, 13));
    cp.add(jRBrichtig3);
    jRBfalsch3.setBounds(712, 573, 25, 17);
    jRBfalsch3.setText("");
    jRBfalsch3.setFont(new Font("Dialog", Font.PLAIN, 13));
    cp.add(jRBfalsch3);
    jBKoordinaten.setBounds(8, 424, 137, 81);
    jBKoordinaten.setText("Koordinaten");
    jBKoordinaten.setMargin(new Insets(2, 2, 2, 2));
    jBKoordinaten.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        jBKoordinaten_ActionPerformed(evt);
      }
    });
    jBKoordinaten.setFont(new Font("Dialog", Font.PLAIN, 13));
    cp.add(jBKoordinaten);
    jBsuche.setBounds(8, 344, 137, 81);
    jBsuche.setText("scannen");
    jBsuche.setMargin(new Insets(2, 2, 2, 2));
    jBsuche.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        jBsuche_ActionPerformed(evt);
      }
    });
    jBsuche.setFont(new Font("Dialog", Font.PLAIN, 13));
    cp.add(jBsuche);
    jBuebersetzten.setBounds(8, 264, 137, 81);
    jBuebersetzten.setText("übersetzten");
    jBuebersetzten.setMargin(new Insets(2, 2, 2, 2));
    jBuebersetzten.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        jBuebersetzten_ActionPerformed(evt);
      }
    });
    jBuebersetzten.setFont(new Font("Dialog", Font.PLAIN, 13));
    cp.add(jBuebersetzten);
    jBimport.setBounds(8, 24, 137, 81);
    jBimport.setText("importieren");
    jBimport.setMargin(new Insets(2, 2, 2, 2));
    jBimport.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        jBimport_ActionPerformed(evt);
      }
    });
    jBimport.setFont(new Font("Dialog", Font.PLAIN, 13));
    cp.add(jBimport);
    jBArrayAusgeben.setBounds(8, 184, 137, 81);
    jBArrayAusgeben.setText("BildArray ausgeben");
    jBArrayAusgeben.setMargin(new Insets(2, 2, 2, 2));
    jBArrayAusgeben.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent evt) {
        jBArrayAusgeben_ActionPerformed(evt);
      }
    });
    jBArrayAusgeben.setFont(new Font("Dialog", Font.PLAIN, 13));
    cp.add(jBArrayAusgeben);
    // Ende Komponenten

    setResizable(false);
    setVisible(true);
  }

  // Anfang Methoden
   public void gibAusFarbanteil()
   {
        BufferedImage image = hintergrund;
        for (int x = 0; x < image.getWidth(); x++)
        {
          for (int y = 0; y < image.getHeight(); y++)
          {
             Color color = new Color(image.getRGB(x, y));
             System.out.println("pixel (" + x + "," + y + ")");
             System.out.println("red:   " + color.getRed());
             System.out.println("green: " + color.getGreen());
             System.out.println("blue:  " + color.getBlue());
          }
        }
   }


   public void checkAll(int pX, int pY)
   {

        BufferedImage image = hintergrund;
        for (int x = pX; x < image.getWidth(); x++)
        {
          for (int y = pY; y < image.getHeight(); y++)
          {
             Color color = new Color(image.getRGB(x, y));
             if(color.getBlue()>0 && color.getBlue()<255 &&
                color.getRed()>0 && color.getRed()<255 &&
                color.getGreen()>0 && color.getGreen()<255)
             {
               this.checkPixel(x,y);
             }

          }
        }


   }

   public Quadrat checkPixel(int x, int y)
   {

         int zaehler=0;
         topY = y;
         botY = y;
         BufferedImage image = hintergrund;
         Color color;
         Color color2;
         Color color3;
         do
         {
            botY++;
            color= new Color(image.getRGB(x, botY));

         }while(color.getRed()>0 && color.getRed()<255  &&
                color.getGreen()>0 && color.getGreen()<255 &&
                color.getBlue()>0 && color.getBlue()<255 );
         int mid = botY-y;
         int rX = mid;
         int lX = mid;
         do
         {
            System.out.println(rX+" ");
            rX++;
            color2 = new Color(image.getRGB(rX, mid));
         }while(color2.getRed()>0 && color2.getRed()<255  &&
                color2.getGreen()>0 && color2.getGreen()<255 &&
                color2.getBlue()>0 && color2.getBlue()<255);
         do
         {
            lX--;
            color3 = new Color(image.getRGB(lX, mid));

         }while(color3.getRed()>0 && color3.getRed()<255  &&
                color3.getGreen()>0 && color3.getGreen()<255 &&
                color3.getBlue()>0 && color3.getBlue()<255 );
         for (int a =lX ; a <= rX ; a++)
         {
           for (int b = y ; b <= botY; b++)
           {
              Color color4 = new Color(image.getRGB(a, b));
              if(color4.getRed()>0 && color4.getRed()<255  &&
                 color4.getGreen()>0 && color4.getGreen()<255 &&
                 color4.getBlue()>0 && color4.getBlue()<255 )
               {
                 zaehler++;
               }
           }
         }
         if(zaehler>= (((rX-lX)*(botY-y))*0.8))
         {

           return new Quadrat(new Koordinate(lX,botY), new Koordinate(lX,y), new Koordinate(rX,y), new Koordinate(rX,botY));

         }
         else
         {

           this.checkAll(rX, botY);

           return null;
         }

   }
   public void ermittlePos()
   {

   }
   public BufferedImage uebersetzten(BufferedImage pBild)
   {

          BufferedImage image = pBild;
          BufferedImage ret=image;
          int w=image.getWidth();
          int h=image.getHeight();
          for(int x=0; x<w; x++)
          {
             for(int y=0; y<h; y++)
             {
                int rgb=image.getRGB(x, y);
                String hs=Integer.toHexString(rgb);
                int r=Integer.valueOf(hs.substring(2, 4), 16).intValue();
                int g=Integer.valueOf(hs.substring(4, 6), 16).intValue();
                int b=Integer.valueOf(hs.substring(6, 8), 16).intValue();
                if((r+g+b)/3<=110)
                    ret.setRGB(x, y, 0);
                else
                    ret.setRGB(x, y, -1);
             }
          }
          
          return ret;

    }
    
    
   public boolean[][] uebertrage(BufferedImage pZuUebertragen)
   {
     boolean[][] uebertragen = new boolean[pZuUebertragen.getHeight()][pZuUebertragen.getWidth()];
     anzahlSpalten = pZuUebertragen.getHeight();
     for (int i = 0; i < pZuUebertragen.getHeight(); i++)
     {
        for (int j = 0; j < pZuUebertragen.getWidth(); j++)
        {
           if(pZuUebertragen.getRGB(i,j) == -1)
           {
              uebertragen[i][j] = true;
           }
           else if(pZuUebertragen.getRGB(i,j) == 0)
           {
              uebertragen[i][j]= false;
           }
        }
     }
     return uebertragen;
   }

   public void bildArrayaAusgeben(boolean[][] pX)
   {
      for (int i = 0; i < anzahlSpalten; i++)
      {
        for (int j = 0; j < pX.length; j++)
        {
           System.out.println(pX[i][j]);
        }
      }
   }
    
    
  public void malen()
  {
    int x = 200;
    int y=105;
    Graphics g = getGraphics();


    if(gibtUebersetztesBild)
    {
      g.drawImage(hintergrund,200,50,this);
      g.drawImage(uebersetztesBild,200,280,this);

    }
    else
    {
       g.drawImage(hintergrund,200,50,this);
    }

  }
  




//--------------------------------!!!Ab hier kommen Buttons!!!-----------------------------------


  public void jBArrayAusgeben_ActionPerformed(ActionEvent evt)
  {
    if(hintergrund == null)
    {
      keinHintergrShowMessageDialog();
    }
    else
    {
      boolean[][] tempArray = uebertrage(uebersetzten(hintergrund));
      bildArrayaAusgeben(tempArray);
    }
  }


  public void jBanalysieren_ActionPerformed(ActionEvent evt)
  {
    if(hintergrund == null)
    {
      keinHintergrShowMessageDialog();
    }
    else
    {
      gibAusFarbanteil();
    }

  }


  public void jBKoordinaten_ActionPerformed(ActionEvent evt)
  {
      if(botY<topY && lX<rX)
      {
         AnzeigeKOShowMessageDialog();
      }
      else
      {
         AnzeigeKOErrorShowMessageDialog();
      }
  }


  public void jBsuche_ActionPerformed(ActionEvent evt)
  {

  }

  public void jBuebersetzten_ActionPerformed(ActionEvent evt)
  {
       if(hintergrund == null)
       {
         keinHintergrShowMessageDialog();
       }

       else
       {
         uebersetztesBild = uebersetzten(hintergrund);
         gibtUebersetztesBild = true;
         malen();
       }
  }

  public void jBimport_ActionPerformed(ActionEvent evt)
  {
     try
     {

      hintergrund = ImageIO.read(new File(jfc1SaveFilename()));
      malen();

     }
     catch(IOException e)
     {
       System.out.println("ERROR");
     }


  }
  

  
  
  
//----------------------------------!!!Ab hier kommen Tools!!!-----------------------------------
  
  
  

  public String jfc1SaveFilename() {
    jfc1.setDialogTitle("Speichere Datei");
    if (jfc1.showSaveDialog(this) == JFileChooser.APPROVE_OPTION) {
      return jfc1.getSelectedFile().getPath();
    } else {
      return null;
    }
  }

  public void keinHintergrShowMessageDialog() {
    JOptionPane.showMessageDialog(this, "Es wurde keine Bilddatei ausgewählt, mit der das Programm arbeiten könnte", "Keine Bilddatei vorhanden", JOptionPane.ERROR_MESSAGE);
  }

  public int keinHintergr2ShowConfirmDialog() {
    return JOptionPane.showConfirmDialog(this, "", "", JOptionPane.DEFAULT_OPTION, JOptionPane.INFORMATION_MESSAGE);
  }
  
   public void AnzeigeKOShowMessageDialog() {
    JOptionPane.showMessageDialog(this, "Die Koordinaten des Abdrucks:\n oberer Rand: "+topY+"\n unterer Rand: "+botY+"\n linker Rand: "+lX+"\n rechter Rand: "+rX+"\n Zentrum: "+mid, "Koordinaten", JOptionPane.INFORMATION_MESSAGE);
  }

  public void AnzeigeKOErrorShowMessageDialog() {
    JOptionPane.showMessageDialog(this, "Es gibt keine Koordinaten.\nGrund: Es wurde kein Abdruck gefunden.", "Koordinaten", JOptionPane.ERROR_MESSAGE);
  }



  // Ende Methoden

  public static void main(String[] args) {
    new QuadratEinlesen("QuadratEinlesen");
  }
}
```


P.S.: Die klasse Quadrat und Koordinate ist nicht mehr nötig


----------

