Tanpohp

Einige Makroaufnahmen die ich kürzlich machte

by on Aug.15, 2011, under Photography

Comments Off on Einige Makroaufnahmen die ich kürzlich machte : more...

Feldtag der Landwirtschaftlich Gärtnerischen Fakultät der HU Berlin

by on May.30, 2011, under Photography

Download: Feldtag

Comments Off on Feldtag der Landwirtschaftlich Gärtnerischen Fakultät der HU Berlin :, , more...

LogfileSplitter – a small tool for splitting logfiles

by on May.16, 2011, under ByTheWay, Tools

Kürzlich wurde ich von einem Freund gebeten ein kleines Programm zu schreiben, welches in der Lage ist, große Logdatein eines Programms zu splitten um diese besser auswerten zu können.   Getest habe ich das Programm an einer 7MiB großen Logdatei mit knapp 125000 Zeilen. Das Programm splittet die Datei in 169 Dateien innerhalb von knapp 25 Sekunden, was natürlich start von dem Suchstring abhängt.

Die Logdateien werden in ein vorher gewählten Ordner geschrieben und mit ein Präfix versehen. Die Analyse findet den Suchstring mittels der Methoden: Is, Contains, BeginsWith, EndWith.

logfilesplitter gui screenshot

Scrrenshot of the LogfileSplitter V0.51

Download: LogfileSplitter

Comments Off on LogfileSplitter – a small tool for splitting logfiles :, , , , , more...

A* Algorithmus

by on May.12, 2011, under Snippets

Zur Zeit belege ich ein Fach names “AI for Games” in welchem es darum geht möglichst intelligente Programm zu schreiben. Eine der Aufgaben war einen Agent über ein Feld zu seinem Ziel zu schicken. Als Hilfestellung gab es einen Graphen der für die Navigation genutzt werden sollte, indem für diesen Graphen der A* Algorithmus implementiert werden sollte. Diese Implementation ist weiter unten zu sehen, jedoch verwendet die Wegfindung nicht zwangsweise den Algorithmus. Falls der Weg auch ohne den Graph gefunden werden kann, wird auf dieen verzichtet. Dabei durchläuft der Code folgende Schritte:

  1. Suche im Graph einen Knoten, welchem dem Startpunkt am nächsten ist und direkt einsehbar ist (nicht hinter einer Mauer).
  2. Suche im Graph einen Knoten, welchem dem Zielpunkt am nächsten ist und direkt einsehbar ist (nicht hinter einer Mauer).
  3. Wenn Start- und Zielknoten die selben sind, prüfe ob Ziel direkt einsehbar.
  4. Wenn Ja, laufe zum Zielpunkt.
  5. Wenn Nein
    1. Benutze A* um Weg zu generieren
    2. Laufe zum Startknoten
    3. Laufe Entlang des Graphen zum Zielknoten
    4. Laufen zum Zielpunkt.

Der Algorithmus hat in der Implementation eine kleine Abweichung. Der Agent läuft nicht bis zum jeweils nächsten Knoten, sondern orientiert sich um sobald dieser in der Nähe des Knotens ist. In dem folgenden Video kann man dies daran erkennen, dass der Agent vor dem Knoten abbiegt:

Die Implementation des A* in Java:

public class AStarAlgorithm {

	Graph graph;
	PriorityQueue notYetVisited;

	public AStarAlgorithm (Graph graph){
		this.graph = graph;
	}

	public Queue SearchPath(Node start, Node aim){
		notYetVisited = new PriorityQueue(64, new NodeCostComperator(SortMode.ASCENDING));
		notYetVisited.addAll(graph.GetNodes());

		//set cost to maximum and predecessor to null
		PrepareGraph(notYetVisited);
		//System.out.println();
		//System.out.println(graph.toString());
		Node currentNode = start;
		currentNode.SummedCosts = CalculateDistance(currentNode, aim);
		currentNode.SummedRealCosts = 0;
		//walk through all nodes until aim is reached
		while(currentNode != aim){
			notYetVisited.remove(currentNode);
			ExpandGraph(currentNode, aim);
			currentNode = notYetVisited.peek();
			System.out.println();
			//System.out.println(graph.toString());
		}
		//reconstruct path from aim
		return ReconstructPath(aim);
	}

	/**
	 * The resulted list of nodes is inverted.
	 * @param aim
	 * @return
	 */
	private PriorityQueue ReconstructPath(Node aim) {
		PriorityQueue result = new PriorityQueue(16,new NodeRealCostComperator(SortMode.ASCENDING));
		Node currentNode = aim;
		while(currentNode.Predecessor != null){
			//System.out.println(currentNode.Index);
			result.add(currentNode);
			currentNode = currentNode.Predecessor;
		}
		//finally add start point
		result.add(currentNode);
		return result;
	}

	private void PrepareGraph (Collection nodes){
		for(Node node : nodes){
			node.SummedCosts = Double.MAX_VALUE;
			node.SummedRealCosts = 0;
			node.Predecessor = null;
			node.PresentationColor = Color.GRAY;
		}
	}
	private void ExpandGraph (Node currentNode, Node aim){
		//System.out.println("Node: "+currentNode.Index+" =>");
		Iterator
 outLinks = currentNode.GetOutboundLinks();
		while(outLinks.hasNext()){

			Link link = outLinks.next();
			Node destination = link.GetDestination();
			if(currentNode.Predecessor == destination) continue;

			double cost = currentNode.SummedRealCosts + link.Cost + CalculateDistance(destination, aim);
			//System.out.println("          "+destination.Index+": "+currentNode.SummedRealCosts + " + " +link.Cost+" + "+CalculateDistance(destination, aim)+" = "+cost);
			if(cost < destination.SummedCosts) {
				destination.SummedRealCosts = currentNode.SummedRealCosts + link.Cost;
				destination.SummedCosts = destination.SummedRealCosts + CalculateDistance(destination, aim);
				destination.Predecessor = currentNode;
				//this ensures that queue is sorted correctly
				notYetVisited.remove(destination);
				notYetVisited.add(destination);
			}
		}
	}
	private double CalculateDistance(Node currentNode, Node aim){
		return currentNode.Coordinate.distance(aim.Coordinate);
	}
}
Comments Off on A* Algorithmus :, , , more...

Schlüsselwörter für Suchmaschinen definieren

by on Jan.08, 2011, under ByTheWay, HowTo

Viele Browser bieten die Möglichkeit Schlüsselwörter für diverse Suchmaschienen zu definieren. Während dies bei Firefox sehr einfach zu erstellen ist, indem man einfach das Kontextmenu eines Suchfeldes öffnet, sammlt Chrome diese Adressen automatisch bei deren Benutzung. Leider sammelt es nicht alle. Des Weiteren benutze ich für manche Suchmaschinen mehrere Schlüsselwörter. Hier eine Liste:

Kürzel Url Beispiel Ergebnis
a http://www.amazon.de/s/ref=nb_sb_noss?field-keywords=%s”>a Was macht das Licht wenn es dunkel ist? a Was macht das Licht wenn es dunkel ist? Suche nach “Was macht das Licht wenn es dunkel ist?” in amazon.com
ask http://de.ask.com/web?q=%s a WordPress Suche nach “WordPress” in ask.com
b http://www.bing.com/search?setmkt=de-DE&q=%s b WordPress Suche nach “WordPress” in bing.com
dict http://www.dict.cc/?s=%s dict Tafel Schlägt “Tafel” auf dict.cc nach
dhl http://nolp.dhl.de/nextt-online-public/set_identcodes.do?lang=de&idc=%s dhl 016022541887 Ruft die Sendeverfolgung für Paket 016022541887 bei DHL auf
e http://shop.ebay.de/?_nkw=%s e Laser-Mause Suche nach “Laser-Maus” in der ebay.de
f http://www.facebook.com/search/?src=os&q=%s f David Störmer Suche nach “David Störmer” in Facebook
g http://www.google.de/search?sourceid=chrome&ie=UTF-8&q=%s g WordPress Suche nach “WordPress” in google.de
geiz http://geizhals.at/deutschland/?in=&fs=%s geiz Lenovo W510 Suche nach “Lenovo W510” in dem deutschen teil von geizhals.at
gc http://www.google.com/images?q=%s&um=1&hl=de&uss=1&ie=UTF-8&source=og&sa=N&tab=wi gc WordPress Suche nach “WordPress” in google.com
geoip http://www.geoiptool.com/de/?IP=%s geoip www.htw-berlin.de Zeigt den Standort des Server der HTW Berlin in geoiptool.com auf einer Karte.
gp http://www.google.com/search?sourceid=chrome&ie=UTF-8&q=%s gp WordPress Suche nach “WordPress” in den Bildern von google.com
if http://www.iconfinder.net/search/?q=%s if file Suche nach “file” in den Icons von iconfinder.com
kino http://kino.to/Search.html?q=%s kino Inception Suche nach “Inception” auf kino.to
leo http://dict.leo.org/ende?lp=ende&lang=de&searchLoc=0&search=%s leo Suchmaschine Suche nach der Übersetzung von “Suchmaschine” bei dict.leo.org
lfm http://www.last.fm/search?q=%s lfm Bela b. Suche nach “Bela B.” in last.fm
lmgtfy http://letmegooglethatforyou.com/?q=%s lmgtfy Watchman Suche nach “Watchman” in LetMyGoogleThatForYou
pr http://www.preisroboter.de/search.php?search=%s pr Benq FullHd Suche nach “Benq FullHd” in der Preissuchmaschine preisroboter.de
turl http://tinyurl.com/create.php?source=indexpage&url=%s&submit=Make+TinyURL! turl http://blog.tanpohp.de Erstellt eine kurze Url für http://blog.tanpohp.de
ups http://wwwapps.ups.com/WebTracking/track?HTMLVersion=5.0&loc=de_DE&Requester=UPSHome&
WBPM_lid=homepage/ct1.html_pnl_trk&
trackNums=1Z4V24Y06843238211%0D%0A&track.x=
Status+ermitteln
ups 1Z4V24Y06843238211 Ruft das Tracking zu dem Paket 1Z4V24Y06843238211 auf
vw http://www.videoworld.de/39—-filiale–sortiment–sortiment_liste.html?titel=%s&media=dvd vw Ruft das Tracking zu dem Paket 1Z4V24Y06843238211 auf
yt http://www.youtube.com/results?search_query=%s&page={startPage?}&utm_source=opensearch yt Led Lichtschranke Suche nach “Led Lichtschranke” in youtube
ytp https://youtubeproxy.org/default.aspx?prx=%s ytp http://www.youtube.com/watch?v=5ZMylpizXWY Leitet das Video http://www.youtube.com/watch?v=5ZMylpizXWY um
ytt http://www.youtube.com/results?search_query=%s+trailer ytt Watchmen Leitet das Video http://www.youtube.com/watch?v=5ZMylpizXWY um

Selbstverständlich können die Schlüsselwörter beliebig vergeben werden, wem also “bing.com” lieber ist als “b”, kann diese beliebig ändern. Das Beispiel der Suche nach Trailern bei youtube (ytt) zeigt, das es auch einfach möglich ist eigene Wörter in die Suchabfrage einzubringen.
Grundsätzlich sieht eine solche Url immer wie folgt aus:

     www.server.com/search?KeyDerSuche=%s als search

Der KeyDerSuche ist bei jeder Suchmaschine anders. Wichtig ist hier nur das %s vom Broweser durch den Suchtext ersetzt wird. Bsp:

     search Wikipedia wird im Browser www.server.com/search?KeyDerSuche=Wikipedia

Möchtet man eigene Wörter ergänzen, muss man diese nur vor oder nach %s ergänzen. Leerzeichen werden in Urls durch ein + gekennzeichnet.

     www.server.com/search?KeyDerSuche=%s+News

Comments Off on Schlüsselwörter für Suchmaschinen definieren more...

Kiwi!

by on Nov.06, 2010, under ByTheWay

Großartig gemachtes Video:

Comments Off on Kiwi! :, , more...

Festval of Lights in Berlin

by on Oct.25, 2010, under Holiday&Life, Night Shot

Einige Fotos welche ich beim diesjährigen Festival of Lights gemacht habe:

Comments Off on Festval of Lights in Berlin more...

Optimierung in C# mittels Pointer

by on Oct.23, 2010, under Snippets

Ich habe mich in den letzten Tagen viel mit Farbraumkonvertierung, sowie Pixelextrahierung und dessen Beschleunigungsmöglichkeiten und C# beschäftigt. Mich hat besonders interessiert, ob das Pointerkonzept in C# das Potenzial hat, Anwendungen derart zu beschleunigen, dass es sich lohnt sich damit zu beschäftigen. Dabei habe ich einige sehr interessante Entdeckungen gemacht.

Der folgende Code wandelt ein byte[] im RGB Format in YCbCr um.

public static void Rgb2YCbCr24Bit(ref byte[] rgb)
{
    int y = 0, cr = 0, cb = 0, cg = 0;
    for (int pos = 0; pos < rgb.Length-2; pos += 3)
    {
        r = rgb[pos + 1];
        g = rgb[pos + 2];
        b = rgb[pos + 3];
        lum = ((r + g + b) / 3);
        rgb[pos + 1] = (byte)lum;
        rgb[pos + 2] = (byte)(lum - b);
        rgb[pos + 3] = (byte)(lum - r);
    }
}

Ich habe diesen Code mehrfach mit einem 36MPixel Bild getestet damit eventuelle Störungen durch andere Programme nicht so stark ins Gewicht fallen. Ergebnis: 2023ms.
Darauf hin habe ich das gleich mit Pointern umsetzt:

public static void Rgb2YCbCr24Bit(ref byte[] rgb)
{
    int r = 0, g = 0, b = 0, lum = 0;
    unsafe
    {
        fixed (byte* p1 = rgb)
        {
            byte* p = p1;
            for (int pos = 0; pos < rgb.Length - 2; pos += 3)
            {
                r = *(p);
                g = *(p + 1);
                b = *(p + 2);
                lum = ((r + g + b) / 3);
                *(p) = (byte)lum;
                *(++p) = (byte)(lum - b);
                *(++p) = (byte)(lum - r);
                ++p;
            }
        }
    }
}

Mit den selben Bild: 1572ms. Das heißt eine Beschleunigung um 23%. An dem Code ist zu sehen, das der Grünkanal nur einmal benötigt wird und die Zwischenspeicherung damit redundant ist. Darauf hin änderte ich den Code wie folgt ab.

public static void Rgb2YCbCr24Bit(ref byte[] rgb)
{
    int r = 0, b = 0, lum = 0;
    unsafe
    {
        fixed (byte* p1 = rgb)
        {
            byte* p = p1;
            for (int pos = 0; pos < rgb.Length - 2; pos += 3)
            {
                r = *(p);
                b = *(p + 2);
                lum = ((r + *(p + 1) + b) / 3);
                *(p) = (byte)lum;
                *(++p) = (byte)(lum - b);
                *(++p) = (byte)(lum - r);
                ++p;
            }
        }
    }
}

Interessanter Weise wurde der Code damit nicht schneller, sondern langsamer. Gegenüber der Implementierung mit Arrays betrug die Beschleunigung nur noch 12%. Würde mich sehr stark interessieren, warum das so ist.

An einer anderen Stelle extrahierte ich RGB-Werte aus einer Bitmap. Als erstes ist zu sagen, dass obgleich eines der Formate PixelFormat.Format32bppArgb heißt, entspricht dies nicht der Ordnung der Pixel um Speicher. Diese liegen genau anderes herum im Speicher des Bitmap: Gbra.
Mit folgende Code laß ich die Rgb-Werte aus einer Bitmap aus.

public static byte[] GetPixelsRgb(Bitmap source)
{
    int width = source.Width, height = source.Height;
    byte[] result = new byte[width * height * 3];
    BitmapData bd = source.LockBits(
                            new Rectangle(0, 0, width, height),
                            System.Drawing.Imaging.ImageLockMode.ReadOnly,
                            source.PixelFormat);
    unsafe
    {
        byte* bp = (byte*)bd.Scan0;
        fixed (byte* rPtr = result)
        {
            byte* rp = rPtr;
            int count = result.Length;
            for (int i = 0; i < count; i += 3)
            {
                *rp = *(bp + 2);
                *(rp + 1) = *(bp + 1);
                *(rp + 2) = *(bp);
                bp += 3;
                rp += 3;
            }
        }
    }
    source.UnlockBits(bd);
    return result;
}

Zu beachten ist, das der Code nur wie zu erwarten funktioniert, wenn (source.width*3)%4==0, da ein Stride (siehe MSDN) mit 0 aufgefüllt wird. Mit dem 36MPixel Bild bedarf es 799ms zum Auslesen des Bildes.

Beim betrachten dieses Codes viel mit folgendes auf: für jeden Pixel wird in der for-Schleife eine Addition +=3 ausgeführt und ein Vergleich ausgeführt, ob der Code am Ende des Bitmap angekommen ist. Die meisten Bilder haben eine Breiten die zumindest durch 4 teilbar ist, viele haben Breiten die durch 8 oder 16 teilbar sind. Damit könnten unnötige Überprüfungen unterbunden werden. Daraus resultiert folgender Code:

public static byte[] GetPixelsRgbFast(Bitmap source)
{
    int width = source.Width, height = source.Height;
    byte[] result = new byte[width * height * 3];

    BitmapData bd = source.LockBits(
                            new Rectangle(0, 0, width, height),
                            System.Drawing.Imaging.ImageLockMode.ReadOnly,
                            source.PixelFormat);
    unsafe
    {
        byte* bp = (byte*)bd.Scan0;
        fixed (byte* rPtr = result)
        {
            byte* rp = rPtr;

            for (int i = 0; i < result.Length; i += 24)
            {
                //pixel 0
                *rp = *(bp + 2);
                *(rp + 1) = *(bp + 1);
                *(rp + 2) = *(bp);
                //pixel 1
                *(rp + 3) = *(bp + 5);
                *(rp + 4) = *(bp + 4);
                *(rp + 5) = *(bp + 3);
                //pixel 2
                *(rp + 6) = *(bp + 8);
                *(rp + 7) = *(bp + 7);
                *(rp + 8) = *(bp + 6);
                //pixel 3
                *(rp + 9) = *(bp + 11);
                *(rp + 10) = *(bp + 10);
                *(rp + 11) = *(bp + 9);
                //pixel 4
                *(rp + 12) = *(bp + 14);
                *(rp + 13) = *(bp + 13);
                *(rp + 14) = *(bp + 12);
                //pixel 5
                *(rp + 15) = *(bp + 17);
                *(rp + 16) = *(bp + 16);
                *(rp + 17) = *(bp + 15);
                //pixel 6
                *(rp + 18) = *(bp + 20);
                *(rp + 19) = *(bp + 19);
                *(rp + 20) = *(bp + 18);
                //pixel 7
                *(rp + 21) = *(bp + 23);
                *(rp + 22) = *(bp + 22);
                *(rp + 23) = *(bp + 21);
            }
        }
    }
    source.UnlockBits(bd);
    return result;
}

Der Code behandelt 8 Pixel auf einmal und erspart sich damit 7 Additionen und 7 unnötige Vergleiche. Zeit zum auslesen des 36MPixel Bildes: 410ms. Das ist eine satte Beschleunigung um 49%.

Es zeigte sich, dass das Pointer-Konzept in C# einige Leistungsreserven anzapfen kann und es sich in zeitkritischen Anwendungen lohnt diese Umzusetzten. Viel überraschender fand ich die Ergebnisse des zweiten Experimentes, die relativ unanhängig von Pointern oder C# sind. Hier zeigt sich was mit ein wenig Mehraufwand in der Implementierung geschafft werden kann.

Comments Off on Optimierung in C# mittels Pointer :, more...

Urlaub an der Ostsee

by on Oct.18, 2010, under Holiday&Life, Photography

Vorheriges Wochenende war ich an der Ostsee ein paar Tage ausspannen. Diese Gelegenheit habe ich genutzt um einige Fotos zu machen. Leider ist es mir nicht gelungen, eine langzeitaufnahme von der Brandung zu machen, da es trotz Bewölkung einfach zu hell war. Dennoch sind einige schöne Fotos zustande gekommen.

Comments Off on Urlaub an der Ostsee more...

Lichtschranke aus einem Arduino Board

by on Sep.22, 2010, under Arduino, Experiments, Microcontroler

Ich habe kürzlich einige sehr interessante Fotos gesehen, in denen extrem kurze Belichtungszeiten genutzt wurden um zum Beispiel fallende Wassertropfen aufnehmen zu können. Aus diversen Blogs erfuhr ich, dass dies, wenn man es manuel macht sehr zeitaufwendig ist, da potenziell hunderte Fotos gemacht werden müssen, bevor gute dabei sind. Das Hauptproblem ist das Auslösen im richtigen Moment. Abhilfe verschaftt eine Lichtschranke die die Kamera auslösst. Nach meiner Recherche werden diese nur hier angeboten. Allerdings zu einem Preis von 140€ aufwärts war das für mich nicht tragbar.

Da ich mich ohnehin mit Microcontroler beschäftigen wollte und zudem mit dem Arduino ein sehr günstiges Board gefunden hatte, habe ich das einfach mal selbst probiert.

Dazu habe ich eine LED falsch gepolt um diese als Lichtdetektor zu nutzen. Das empfangene Signal geht wird durch 2 Transistoren verstärkt und in den analogen Eingang des Arduino geleitet.  Diese zeigt auf dem LCD dann ein entsprechendes “Trigger”-Event an. Das ganze habe ich hier in dem Video mal demonstriert.

Im Anschluss an das Video habe ich das noch im eigentlichen “Zielgebiet” getestet und von einem Messer Tropfen durch die Lichtschranke fallen lassen. Ergebnis: Aus einem Meter höhe wurden immernoch das Trigger-Event ausgelöst. Höher war schwer zu testen, da das zielen auf einen 2mm breite Lichtschranke nicht wirklich einfach war. Für die, welche es nachbauen wollen, ist hier die Schaltung:

Für die elektrotechnisch versierten unter euch, bitte verzeiht eventuelle Fehler. Ich bin Informatiker und habe eigentlich keine Ahnung von Elektrotechnik. Ich finde es nur sehr spannend und versuche mich da weiter zu bilden.

Da heute nun die restlichen Teile gekommen sind (2,5mm Klinke-Stecker) werde ich demnächst mal alles an meine Kamera anbauen und testen ob alles geht. Bevor ich es vergesse, die Kostenbelaufen sich momentan bei ~40€. Dies wird allerdings noch etwas steigen, da ich vor habe das ganze fertig zu löten und in eine Box zu bauen, so dass es eine “richtiges Modul wird”. Das LCD ist im übrigen nicht zwangsweise notwendig und könnte vernachlässigt werden(~13€). Ich brauche es aber, da ich vor habe das Signal im Board verzögern zu können. Um diese Verzögerung bequem einstellen zu können, ist eine Visualisierung hilfreich.

Comments Off on Lichtschranke aus einem Arduino Board more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Visit our friends!

A few highly recommended friends...