Geotools und Kantenerkennung

JimK

Bekanntes Mitglied
Hallo liebes Forum.

Ich habe folgende Problematik. Ich habe eine Datei mit Koordinaten die eine räumliche Punktwolke ergibt. Jedoch kann in dieser Punktwolke eine zweite Punktwolke existieren. Um das zu unterscheiden ist in der Koordinaten-Datei ein zusätliches Attribut, dass den Wert 0 oder 10 haben kann. Jetzt möchte ich gerne die Wolken bzw. Koordinaten filtern, die sich in der großen Wolke befinden und weiß nicht wie ich das anstellen kann. Im prinzip ist für mich auch nur die äußere Hülle wichtig. Um das ganze etwas zu verdeutlichen, habe ich eine kleines Bild erstellt. Ihr müsst euch das nur noch in 3D vorstellen. :D Dabei könnten die roten Punkte den Wert 0 haben und die schwarzen Punkte den Wert 10. Jetzt geht es darum den Übergang (blaue Linie) zu erkennen.


Jetzt versuche ich die ganze Zeit mein Problem mit der Bibiothek Geotools zu lösen, weil es irgendwie die Möglichkeit gibt, dass man Nachtbarpunkten untersuchen kann, aber irgendwie ist die Dokumentation nicht besonders. Momentan bin ich soweit, dass ich aus den Punkten Features gebildet habe und in eine Collection speichere. Kennt sich jemand mit Geotools aus, kennt ein Geotools Forum, bessere Dokumentationen oder hat ganz und gar ein bessere Idee die Wolken zu filtern? ^^ Ich bin für jeden Ratschlag dankbar.

LG JimK
 

Logaff

Bekanntes Mitglied
also ich hab mir das so vorgestellt:

eine große Wolke 1, kann Elemente der Wolke 2...x enthalten denn würd ich sagen man bildet ein Polygon aus den äußersten Punkte der ersten Wolke und überprüfung ob sich die Punkte der Wolken 2...x innerhalb des Polygons befinden.
 

JimK

Bekanntes Mitglied
In diese Richtung habe ich auch gedacht. Jedoch existiert ein Problem. Hm... wie erkläre ich es am besten.

Wenn wir uns nochmal das Bild betrachten und uns vorstellen, dass die schwarzen Punkte komplett mit roten Punkten umgeben sind, dann wäre es für die untere Kante kein Problem. Aber bei der oberen Kannte, müssen die letzten roten Punkte noch zu schwarzen Punkten werden. Das hat etwas mit der Messung zu tun. Ein riesiges Schaufelrad Baggert nämlich Abraum weg und an der untersten Kante des Schaufelrades ist der GPS Empfänger. Er Putzt dann den Abraum von der Kohle weg, danach schaltet er um und Baggert mit der ganzen Schaufel die Kohle weg. Somit kann sich die Höhe dann stark unterscheiden. Somit brauche ich die letzten Koordinaten des Abraumes und die letzen Koordinaten der Kohle. Dann bekomme ich eine genaue Punktewolke von der Gebaggerten Kohle.
 
Zuletzt bearbeitet:

turtle

Top Contributor
Ich bin definitiv kein Experte von geotools, aber für einige Funktionen werden meines Wissens durch die JTS Topology Suite bearbeitet. Und diese kann "nur" Euclidean planar linear geometry.
 

JimK

Bekanntes Mitglied
Wenn ich das richtig verstanden habe, dann ist in Geotools die JTS Topology Suite mit integriert. Ich werd mich gleich mal informieren über "Euclidean planar linear geometry" um zu erfahren was das ist. ^^
 

JimK

Bekanntes Mitglied
Ich könnte gerade verzweifel. Es werden die Punkte aus einer Datei gelesen, als Geometry in ein SimpleFeature gepackt und dann in eine Collection gespeichert. Jetzt würde ich mir aber gern die Geometry aus dem Feature holen, aber es funktioniert einfach nicht. Es wir mir als ROT unterstrichen. (Zeile 67)
Laut JAVADOC muss ich mir doch die Geometry wiederholen können. :(
Java:
	public static void main(String[] args) throws Exception{
		

		
		final SimpleFeatureType TYPE = DataUtilities.createType("Location",
                "location:Point:srid=4326," + // <- the geometry attribute: Point type
                        "geologie:Integer," + // <- a number attribute
                        "Datum:String" // a String attribute
        );
		
		File file = JFileDataStoreChooser.showOpenFile("dat", null);
		
        if (file == null) {
            return;
        }


				
		 /*
         * We create a FeatureCollection into which we will put each Feature created from a record
         * in the input csv data file
         */
        SimpleFeatureCollection collection = FeatureCollections.newCollection();
        /*
         * GeometryFactory will be used to create the geometry attribute of each feature (a Point
         * object for the location)
         */
        GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null);

        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);

        BufferedReader reader = new BufferedReader(new FileReader(file));
        try {
            /* First line of the data file is the header */
            String line = reader.readLine();
            System.out.println("Header: " + line);

            for (line = reader.readLine(); line != null; line = reader.readLine()) {
                if (line.trim().length() > 0) { // skip blank lines
                    String tokens[] = line.split("\\;");

                    double latitude = Double.parseDouble(tokens[0]);
                    double longitude = Double.parseDouble(tokens[1]);
                    double altitude = Double.parseDouble(tokens[2]);
                    int geologie = Integer.parseInt(tokens[3].trim());
                    String datum = tokens[4].trim();

                    /* Longitude (= x coord) first ! */
                    Geometry g = geometryFactory.createPoint(new Coordinate(longitude, latitude, altitude));
                    
                    featureBuilder.add(g);
                    featureBuilder.add(geologie);
                    featureBuilder.add(datum);
                    SimpleFeature feature = featureBuilder.buildFeature(null);
                    collection.add(feature);
                  
                }
            }
        } finally {
            reader.close();
        }
		Iterator<SimpleFeature> itr = collection.iterator();
		while(itr.hasNext())
		{
			Object o = 10;
			SimpleFeature test = itr.next();
			Geometry pkt = test.getAttribute("GEOMETRY");		
			
			if(test.getAttribute(1)==o)
				
			System.out.print(pkt+" \n");
		}
		
		}
}

LG JimK
 

jgh

Top Contributor
natürlich nicht....du packst ja die Geometry auch da rein...

Java:
   Geometry g = (Geometry) test.getAttribute("GEOMETRY" );
 

muckelzwerg

Bekanntes Mitglied
Häh? Sorry, ich verstehs noch nicht wirklich. Kannst Du Klartext reden, oder ist das geheim?
Du hast einen Schaufelradbagger, der in zwei verschiedenen Modi arbeitet (1: Abraum, 2: Kohle)?
Du misst die Position des Baggers bei der Arbeit und willst daraus "irgendwas" ermitteln. Die Fläche, wo Kohle gebaggert wurde oder sowas. Was denn eigentlich genau?
Für die Unterscheidung der Modi kann man irgendwie als Trick benutzen, dass der Bagger den GPS Sensor jeweils anders platziert und sich deshalb die Höhe ändert.

Wenn das soweit stimmt, hast Du ein Bild mit Messpunkten, die Du bereits in Kohle und Abraum unterteilen kannst.
Darauf kannst Du jede Menge Methoden für Kantendetektion oder andere Segmentierungen draufwerfen. Da sollte sich recht leicht ein passendes Verfahren finden lassen. (Sobel, Hough ...)
Aber was ist jetzt mit "die roten müssen nochmal schwarz werden, weil Messung ..."?
 

JimK

Bekanntes Mitglied
Es ist schwer für mich mein Problem zu erklären. Darum habe ich mal meine Zeichenkünste eingesetzt. :D





Also es funktioniert so. Der Bagger beseitigt zu erst den Abraum. Dieser Abraum wird auf ein gesondertes Transportband abgeworfen. Dabei bekommen alle Koordinaten zum Beispiel den Wert 1 für Abraum. Hat der Bagger den Abraum von der Kohle geputzt, schaltet er auf ein anderes Transportband um, dass für die Kohle zuständig ist. Dabei erhalten alle Koordinaten den Wert 2 für Kohle. Jetzt ist aber das Problem, dass der Bagger nach dem Putzen voll mit dem Schaufelrad in die Kohle fahren könnte und somit die obere Kante sich um einige Meter nach unter verschiebt. Deshalb benötige ich für die obere Kante die letzten Abraumkoordinaten.
Anhand dieser gefilterten Kohlekoordinaten möchte ich dann später eventuell die Menge der tatsächlich gebaggerten Kohle ermitteln.
Ich danke euch für eure Geduld. ;)
 

JimK

Bekanntes Mitglied
An Hogh habe ich auch schon gedacht bzw. an Kantenerkennung via Bild, aber da hab ich noch keine Ahnung wie ich das bei Daten im Raum anstellen soll. Da müsste ich doch immer einen Querschnitt erstellen und daraus die Kanten ableiten oder? Momentan möchte ich es mit Polygonen versuchen. Was meint ihr? Welche Variante ist besser oder gibt es noch einen anderen Ansatz?
 

muckelzwerg

Bekanntes Mitglied
Ist doch gar nicht so schlecht erklärt. Ein paar mehr Details und jeder versteht es. :)
Es geht irgendwie um die Übergangsphase und darum, dass die Förderbänder bereits auf "Kohle" umgeschaltet sind, der Bagger aber noch etwas anderes macht, als Kohle zu schaufeln?
Kannst Du den Punkt nochmal genauer beschreiben? "er fährt voll in die Kohle" was genau passiert denn?

Du suchst doch irgendwie einen Punkt, ab dem Du sicher weißt "jetzt wirklich wieder Kohle".
Die Menge wird ja wohl letztlich auch gewogen, denk ich mal. ;)
Also gehts Dir vermutlich eher darum die Volumen korrekt zuzuordnen?

Kannst Du in Deine Zeichnung mal ein paar GPS-Messpunkte einfügen? Also dass man mal sieht, wo Rot und wo Schwarz gemessen wird. Da müsste man dann ja den Messfehler direkt sehen können, oder?



Und dann nochmal, was genau sind die Probleme?
Brauchst Du nur die Fehlerkorrektur, oder auch allgemein eine Flächen-/Kantenbestimmung?
Arbeitst Du nur in 2D, weil Du von Kanten schreibst?







Edit: Hough geht auch in 3D für Flächen
Hough transform - Wikipedia, the free encyclopedia
http://plum.eecs.jacobs-university.de/download/3dresearch2011.pdf
aber ob Dir das wirklich was hilft, ist die Frage.
Wozu willst Du die Polygone denn haben?
Bei Punktwolken gibt es Verfahren, um den Hüllkörper zu berechnen. Die findest Du im Bereich von 3D-Scans. Hab ich selbst noch nicht genutzt, deshalb kann ich Dir da grad keinen Namen nennen, aber da gibt es genauso Material zu, wie bei 2D.
Aber Du musst da erstmal entscheiden, was Du am Ende haben willst.
Aus Punktwolken macht man Polygone bzw. Netze, um z.B. Netzalgorithmen anwenden zu können. Ohne Kanten kann man z.B. keine Kantenglättung machen usw.
Aber das willst Du vermutlich alles gar nicht.
Zeichnen kann man Punktwolken auch direkt. Und wenn Du das Volumen berechnen willst, kommst Du mit einem Schichtmodel auch direkter hin.
 
Zuletzt bearbeitet:

JimK

Bekanntes Mitglied
Also die Forderbänder müsst ihr wieder ganz schnell vergessen. :D Ich wollte euch nur damit erklären wie das mit dem Umschalten zusammenhängt. Hab nämlich am Anfang auch Probleme gehabt, dass genaue Problem zu verstehen. :oops:

Also es sieht so aus wie es Muckelzwerg schon richtig erkannt hat. Ziel ist es aus der riesigen räumlichen Koordinatenwolke die Kohlewolken zu ermitteln. Eine weitere Problemstellung ist, dass beim Putzen im Schnitt Abraum nachrutschen kann, weil ja der Bagger die Kohle nicht mit einmal wegnimmt. Durch dieses Nachrutschen können Spitzen in der Wolke entstehen. Diese wollte ich dann anhang der Polygonbildung eliminieren.
Also... primär geht es mir erst einmal darum die Kohlewolke aus der Abraumwolke zu filtern und dabei zu beachten, dass die letzten Abraumkoordinaten der Oberkante zu Kohlekoordinaten werden. ;)



Im Anhang findet ihr eine Datei die ich versuche zu filtern.

EDIT: Datei im Anhang
 

Anhänge

  • sw_s2.zip
    110,7 KB · Aufrufe: 0
Zuletzt bearbeitet:

muckelzwerg

Bekanntes Mitglied
Aber die Trennung der Wolken hast Du doch bereits? Rot und Schwarz.
Die Frage ist, ob Du ein anderes Modell brauchst (z.B. eine Flächenliste) um bestimmte Verfahren darauf anzuwenden.

Wenn Du die Hüllfläche suchst, schau Dir das hier mal an:
Point cloud to mesh
MeshLab
 

JimK

Bekanntes Mitglied
Ja, die Trennung ist im Prinzip da. Aber wenn ich das Problem mit der Oberkante nicht berücksichtige, dann passiert das auf dem Bild. Da der GPS Empfänger an der Unterkante des Schaufelrades ist. :(



Ich danke für deine Hilfe muckelzwerg. Mach mich erstmal auf dem Weg nach Hause und dann hänge ich nochmal die Datei an. ;)
 

JimK

Bekanntes Mitglied
Hallo :D

Ich habe eine neue Idee. ;) Jedoch habe ich da irgendwie einen Denkfehler und ich weiß nicht wo. Ich möchte gerne die Punktwolke in Scheiben schneiden bzw. in einzelne Stäbchen um dann anhand der Stäbchen die Kanten analysieren. So als würde ich zum Beispiel ein Rohr in den Boden stecken, wieder raus hohlen und anhand des im Rohr befindlichen Erdreich die einzelnen Schichten erkennen.
Leider zeigt er mir 0 Ergebnisse und ich weiß nicht warum. Nach meiner Theorie müsste es funktionieren. ;(
Java:
package FloezFilter;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.StringTokenizer;

public class FloezFilter{
	static ArrayList<Messdaten> sort = new ArrayList<Messdaten>();
	static ArrayList<Messdaten> filtereddata = new ArrayList<Messdaten>();
	static ArrayList<Messdaten> geolist = new ArrayList<Messdaten>();
	/**
	 * @param args
	 */
	
	public static void main(String[] args) throws Exception{
		

		String line;
		FileReader fr = new FileReader("f:\\sw_s2.dat");
		BufferedReader br = new BufferedReader(fr);
		
		double xmin = 0,ymin = 0, xmax = 0, ymax = 0;
		
		
		int counter = 0;
		
		while((line = br.readLine()) != null)
		{
			Messdaten a = new Messdaten(0, 0, 0, 0, 0, null);
			
			StringTokenizer tok = new StringTokenizer(line,";");
			String s1 = tok.nextToken();
			a.y = Double.valueOf(s1);
			String s2 = tok.nextToken().trim();
			a.x = Double.valueOf(s2);
			String s3 = tok.nextToken().trim();
			a.z = Double.valueOf(s3);
			String s4 = tok.nextToken().trim();
			a.element = Integer.valueOf(s4);
			a.datum = tok.nextToken().trim();
		
			geolist.add(a);

			if(counter==0)
			{
				xmin=a.x;
				ymin=a.y;
				xmax=a.x;
				ymax=a.y;
			}
			if(a.x<=xmin)
			{
				xmin=a.x;				
			}
			
			if(a.y<ymin)
			{
				ymin=a.y;
			}
			
			if(a.x>xmax)
			{
				xmax=a.x;
			}
			
			if(a.y>ymax)
			{
				ymax=a.y;
			}
			
			counter++;
		}
		br.close();
		System.out.println("++++++++++++++++++++");

		System.out.println("XMin: "+xmin+" YMin: "+ymin);
		System.out.println("XMax: "+xmax+" YMax: "+ymax);
		
		System.out.println("++++++++++++++++++++");
		Collections.sort(geolist);
		
	Reihe(xmin, ymin, xmax, ymax);
	
	System.out.println("++++++++++++++++++++");
	

	listInDatei();
	}
	
	public static void Reihe(double xmin, double ymin, double xmax, double ymax)
	{
		Messdaten b = new Messdaten(0, 0, 0, 0, 0, null); //Vergleichsobjekt
				
		int zahl = 0;
		
		while(ymin<=ymax)	//Arbeitet Y-Reihen ab
		{
			int counter = 0;
			
		while(xmin<=xmax)	//Arbeitet X-Reihen ab
		{
			
		for(Messdaten a : geolist)	//Nimmt sich die Objekte aus einer nach z 
		{							//geordneten ArrayList; ist aufsteigend sortiert
			
			if(a.x==xmin&&a.y==ymin) //Es sollen die Punkte der Reihe nach abgearbeitet werden
			{						//Eine Art Höhen-Stäbchen soll entstehen
				if(counter==0)
				{
					b=a;	//Es wird das erste Objekt zum Vergleich übergeben
				}
				else
				{					
					if(b.element==0 && a.element==10 || b.element==10 && a.element==0)
					{
						filtereddata.add(a);
						//Das Stäbchen wird von unten nach oben nach 0 && 10 untersucht
						zahl++;
					}
						b=a; //Das nächste Objekt wird als Vergleichsparameter übergeben
				}
			
			counter++;
			}
		}
		xmin=xmin+0.5; //Die Koordinatenreihen werden gezählt
		}
		ymin=ymin+0.5;
		}
		

		System.out.println(zahl);
		
	}
	
	 private static void listInDatei() { 
	        try { 
	            PrintWriter printWriter = new PrintWriter(new FileWriter("lala.dat")); 
	            Iterator<Messdaten> iter = filtereddata.iterator(); 
	            while(iter.hasNext() ) { 
	                Messdaten o = iter.next(); 
	                printWriter.println(o.y+";"+o.x+";"+o.z); 
	            } 
	            printWriter.close(); 
	        } catch (IOException e) { 
	            e.printStackTrace(); 
	        } 
	    }
		
}

Java:
package FloezFilter;


public class Messdaten  implements Comparable<Messdaten>{
		
	int element, floetz;
	Double x,y,z;
	String datum;
	
	public Messdaten(double x, double y, double z, int element, int floetz, String datum)
	{	
		this.x = x;
		this.y = y;
		this.z = z;
		this.element = element;
		this.floetz = floetz;
		this.datum = datum;
	}
	
	public void showMessdaten() {
	      System.out.println("x: " + x + ", y: " + y+ ", z: " + z+ ", Element: " + element);
	    }

	
	public int compareTo(Messdaten o) {
	      return ((Double)z).compareTo((Double)o.z);
	}

}

Kann jemand bitte meine Denkblockade lösen??? :(
Ich sag schon mal danke.
 
Zuletzt bearbeitet:

Oben