Pixel suchen mit VB.NET

08/09/2013 23:23 Requi#1
Ich versuche mich gerade an einer Pixelsuch Funktion, die vom Screen einen angegeben Pixel sucht und die X und Y Koordinaten zurück gibt.

Da ich was schnelles brauche, sind mir 1540 ms zu langsam. Und das in einem 2.Thread.
Ohne 2. Thread sind es bis zu 2100 ms.

Hätte da jemand was relativ schnelles, denn der Bot muss schnell hinterher kommen, bevor er sich verklickt.

Was ich habe:

MfG
08/09/2013 23:31 tolio#2
[Only registered and activated users can see links. Click Here To Register...]
08/09/2013 23:36 snow#3
Du hast hier halt ne Laufzeit von O(height * width), was recht langsam ist.
Was du evtl. versuchen könntest, wäre das aufsplitten des Bildes und dann z.B. erst die linke Hälfte abzusuchen. Wenn da nichts dabei ist, suchst du die obere Hälfte der rechten Hälfte ab, wenn da nichts dabei ist, die linke Hälfte der unteren Hälfte der rechten Seite, wenn da nichts dabei ist die linke Hälfte der rechten Hälfte der unteren Hälfte der rechten Seite usw. :D

Irgendwas in die Richtung müsstest du machen, dass deine Laufzeit eher in Richtung logarithmisch geht.
08/10/2013 02:23 Requi#4
Das ist gerade das Problem.
Ich weiß, dass es so dreckslahm ist, weil es höhe * weite durchläufe macht.
Bei mir wären das:
1600x900=
1.440.000 Durchläufe.

Ich schau mir mal das von tolio an und schau was ich damit anfangen kann.

EDIT: Habs mir jetzt mal angeschaut, aber verstehe es nicht wirklich.
Was zum Beispiel ist der PaintEventArgs. Ich meine es ist das Bild, das übergeben werden soll. Aber das mache ich ja schon während der Beispiel Sub.

Und was genau macht denn die Sub am Ende.
Was genau muss ich machen (Pseudo-Code reicht mir), damit er mir einen Pixel aus der Bitmap sucht. Soweit ich es verstanden habe, speichert LockBits die Bitmap im Speicher und ist festgesetzt dort, bis man sie wieder unlocked, oder einen Restart macht.

Das war es erstmal mit meinen Fragen :o
08/10/2013 14:54 nkkk#5
Quote:
Originally Posted by snow911 View Post
Du hast hier halt ne Laufzeit von O(height * width), was recht langsam ist.
Was du evtl. versuchen könntest, wäre das aufsplitten des Bildes und dann z.B. erst die linke Hälfte abzusuchen. Wenn da nichts dabei ist, suchst du die obere Hälfte der rechten Hälfte ab, wenn da nichts dabei ist, die linke Hälfte der unteren Hälfte der rechten Seite, wenn da nichts dabei ist die linke Hälfte der rechten Hälfte der unteren Hälfte der rechten Seite usw. :D

Irgendwas in die Richtung müsstest du machen, dass deine Laufzeit eher in Richtung logarithmisch geht.
auch mit der methode wird die laufzeit nicht logaritmisch werden.

@te:
naja zum einen rufst du Color.FromArgb(A, R, G, B) innerhelb der schleife auf, besser währe es ausserhalb damit es nur einmal aufgerufen wird.

zum zweiten ist bmp.GetPixel auch nicht wirklich schnell, in C# würde man unsafe benutzen, in VB geht das nicht. ist es wohl das beste das ganze mit Marshall.Copy in ein array zu kopieren. In dem zusammenhalb benutzt du auch die methode von tolio.

naja die erste und letzte iele bruchst du nicht. du bauchst nur
Code:
    ' Create a new bitmap. 
    Dim bmp As New Bitmap("c:\fakePhoto.jpg")

    ' Lock the bitmap's bits.   
    Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
    Dim bmpData As System.Drawing.Imaging.BitmapData = bmp.LockBits(rect, _
        Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)

    ' Get the address of the first line. 
    Dim ptr As IntPtr = bmpData.Scan0

    ' Declare an array to hold the bytes of the bitmap. 
    ' This code is specific to a bitmap with 24 bits per pixels. 
    Dim bytes As Integer = Math.Abs(bmpData.Stride) * bmp.Height
    Dim rgbValues(bytes - 1) As Byte 

    ' Copy the RGB values into the array.
    System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes)

    ' Set every third value to 255. A 24bpp image will look red. 
    For counter As Integer = 2 To rgbValues.Length - 1 Step 3
        rgbValues(counter) = 255
    Next 

    ' Unlock the bits.
    bmp.UnlockBits(bmpData)
rgbValues ist der inhalt des bildes als byte array, dh es hat die grösse 3*höhe*breite (3 da jedes pixel aus 3 bytes (rgb) besteht).

und anstatt jetzt jedes dritte pixel auf 255 zu setzten, überprufst du eben in der schleife ob es die gewünschte farbe ist.
08/10/2013 15:37 dready#6
Das ist eine relativ klassische Frage :)

Wenn du dich mit dem ganzen nähe auseinandersetzen willst sieh dir mal Sortier und Such Algorhytmen an.

Grundlegendes um etwas mehr Perfomance rauszubekommen wurde ja schon genannt.

Deine Problemstellung hier ist das du eine "große" Datenmenge hast und nach etwas bestimmten suchst.

Ansätze für soetwas sind z.b. :

1. Zerleg die Datenmenge in kleinere Mengen, intressante Ergebnisse erreicht man z.b. wenn man die Gesammtmenge in 10 kleinere Ausschnitte zerlegt und diese mit einer zufälligen Reihenfolge abarbeitet. Die Maximal Zeit bleibt die selbe aber die Wahrscheinlichkeit das der Algo früher ein Treffer hat erhöht sich.

2. Benutze Muster bei der Erkennung, es ist recht unwahrscheinlich das es nur einen Pixel mit der gesuchten Farbe gibt, durchsuche also zuerst nur jeden 2. Pixel, erst wenn das nicht zum erfolg führt die restlichen.
(Hier kann man sich austoben, ist auch ein relativ intressantes Projekt, Bsp. Bau ein Programm das Zufällige Muster für die Suche wählt, lass sie jeweils x-Stunden auf dein Ziel los, und gib danach dem Muster einen Score wie gut er abgeschnitten hat, war durchaus beeindruckt was für gute Muster man finden kann, einziger Nachteil man bekommt nicht mit warum genau ein Muster sehr gut ist.)


3. Nutze die heutige Hardware, ist dein Problem erstmal in kleine Teilprobleme zerlegt, gibt es keinen Grund es nicht auszunutzen, heutzutage hat praktisch jeder Dual oder Quadcore Cpus, gut umgesetzt kann es imens Zeit einsparen.
08/10/2013 17:33 'Heaven.#7
LINQ ist dazu noch schneller als For und For Each schleifen + If Abfragen
08/11/2013 02:51 dready#8
schleifen sollten schneller sein als LINQ oder hab ich da was falsch im kopf ?
08/11/2013 03:27 Requi#9
Könnte mir kurz jemand erklären was genau LINQ ist?
08/12/2013 14:13 'Heaven.#10
Quote:
Originally Posted by dready View Post
schleifen sollten schneller sein als LINQ oder hab ich da was falsch im kopf ?
Nachdem LINQ geladen ist ist es wesentlich schneller soweit ich weiß