VB NET ImageSearch – Bilder in Spielen, Desktop und Co. suchen

VB.NET ImageSearch – Bilder in Spielen, Desktop und Co. suchen

Eine VB NET ImageSearch, also eine Bildersuche wollte vermutlich jeder Entwickler im NET Umfeld einmal realisieren.

Ach Gott wie präsent mir diese Momente noch im Gedächtnis sind, kleines Beispiel gefällig? Kein Problem!

Egal ob beim Ingame-Angeln, wo man praktisch immer wieder die exakt gleichen Aktionen durchführt, oder beim „craften“ von Gegenständen..

Auch wenn diese Beispiele eher mit dem Gaming-Sektor zu tun haben, gibt es mit Sicherheit genug Einsatzmöglichkeiten im Büro.

So oder so hat man sicherlich nicht immer Lust und vor allem die Zeit, diese Art von „Monkey-Work“, also praktisch die Arbeit für „Blöde“ zu erledigen.

Auf YouTube ansehen – VB NET ImageSearch

Falls Du die visuelle Darstellung, bzw. Erklärung des Beitrages bevorzugst, kannst Du natürlich auch das dementsprechende Video anschauen.

Ich habe allerdings in diesem Beitrag einige Neben-Themen eingebracht und kann mir auch hier die Zeit nehmen, ein wenig drum rum zu erklären.

Dieser Beitrag hier ist daher etwas länger und ausführlicher als das Video – just sayin‘.

Ursprung und Idee zum Beitrag – VB NET ImageSearch

VB NET ImageSearch – Die Idee zum Beitrag
VB NET ImageSearch – Die Idee zum Beitrag

In solchen häufig wiederkehrenden Momenten hat man sicherlich das Bedürfnis nach Hilfe.

Man möchte seinem Hausroboter einfach sagen können: „Hey, mach Du das bitte mal, ich habe keine Lust“.

Schnell wird man allerdings feststellen, dass das zu oft einfach nicht geht, bis auf in bestimmten Fällen.

Als Entwickler haben wir natürlich glücklicherweise die Möglichkeit uns verschiedene Hilfsmittel zu bauen.

Ob privat, beruflich, oder für’s Spielen diverser Spiele, können wir uns viele Hilfsmittel programmieren.

Vom einfachen Angel-Bot, Welcher eine bestimmte Abfolge immer wieder abarbeitet, bis hin zu komplexeren Bereichen.

Darunter könnte ich mir z. B. einen „Crafter-Bot“ vorstellen, Welcher nach gewissen Commands wie „Strg+Alt+<XY>“ komplexe Gegenstände erstellen kann.

Hilfsmittel zur Hand

VB.NET ImageSearch mit Hilfe von AutoIt
VB.NET ImageSearch mit Hilfe von AutoIt

Wir arbeiten in diesem Beitrag nicht ohne weitere Hilfsmittel, warum sollte man auch darauf verzichten.

Viele nützliche Funktionalitäten wurden bereits erfunden und erfolgreich über lange Zeit getestet.

Für viele Entwickler spielt natürlich die Größe der jeweiligen Hilfsmittel eine Rolle, man möchte natürlich keine 2GB großen Tools installieren.

Viele sehen allerdings schon rot, wenn die einzelnen Helfer bereits an eine Größe von 1-2 Megabyte rangehen.

In einer Zeit wo man X Terrabyte große Festplatten schon zum Preis von den damaligen 80GB-Kloppern bekommt, sehe ich es allerdings halb so schlimm.

Ich denke man muss letztendlich immer den Mehrwert gegenüber der Eigenarbeit in Relation sehen und der Mehrwert lohnt sich hier definitiv.

Wenn man sein Programm intelligent entwickelt, hält einen nachher auch nichts davon ab, gewisse Parts isoliert auszutauschen.

Letztendlich verwenden wir dieses Mal einige Funktionalitäten der AutoIt3 Scriptsprache zu Nutze.

Vorbereitungen des Visual Studio Projekts

Neues Visual Studio Projekt anlegen
Neues Visual Studio Projekt anlegen

Lade Dir nun am besten die von mir bereitgestellten Bibliotheken herunter, oder suche Diese alternativ im Netz.

Erstelle im nächsten Schritt nun wie gewohnt ein neues Windows Forms-, oder z. B. ein neues WPF-Projekt.

Füge die heruntergeladene „AutoItX3.Assembly.dll“-Datei nun als Verweis in dein Projekt ein – die anderen Dateien werden nicht funktionieren.

Einen Verweis kannst Du über den ProjektmappenExplorer rechts außen im Visual Studio hinzufügen.

Klicke dazu einfach mit der rechten Maustaste auf Verweise“ und suche nach der Datei, wähle alternativ einen anderen Weg.

Du musst danach auch sämtliche anderen Dateien in das DebugVerzeichnis deines Projekts legen.

Die oben Genannte ist bereits durch den vorhin geschehenen Import vorhanden.

Ran an den Code – VB NET ImageSearch

Die Funktion um die sich hier so gut wie alles drehen wird ist die „ImageSearch“-Funktion aus der „ImageSearchDLL.dll“.

Man beachte hier die komische Schreibweise, Welche trotz „doppelt-gemoppelt“ tatsächlich richtig ist..

Diese Funktion muss erst einmal wie folgt aus der passenden Library importiert werden:

    <DllImport("ImageSearchDLL.dll")>
    Private Shared Function ImageSearch(
                                 x As Integer,
                                 y As Integer,
                                 right As Integer,
                                 bottom As Integer,
                                 imagePath As String) As IntPtr
    End Function

Vergiss hier auch nicht den Import des „DllImport“-Attributs:

Imports System.Runtime.InteropServices

Ich denke, dass die Parameter der Funktion zwar relativ einleuchtend sind, gehe aber dennoch gerne darauf ein.

Dabei wird Dir denke ich das folgende Bild noch ein wenig unter die Arme greifen:

VB.NET ImageSearch Searching Area
VB.NET ImageSearch Searching Area

Je kleiner der durchsuchte Bereich ist und je weniger Bildfläche somit durchsucht werden muss, desto schneller ist die Bildsuche natürlich.

Parameter

x As Integer

Der X-Parameter gibt an, auf welcher Position der X-Achse die Funktion anfangen soll zu suchen.

y As Integer

Als nächstes wird der Y-Parameter übergeben, um zu definieren, ab welcher Position auf der vertikalen Achse des Bildschirms gesucht werden soll. Achtung: Von oben nach unten gesehen = je größer der Wert, desto weiter unten auf dem Bildschirm.

right As Integer

Gibt an, bis zu welchem Punkt auf der X-Achse gesucht werden soll.

bottom As Integer

Legt fest, bis zu welchem vertikalen Punkt auf der Y-Achse gesucht wird.

imagePath As String

Hier kannst Du den Pfad zum Bild angeben (z. B. „my_button.png“). Achtung: Wenn Du eine gewisse Toleranz für die Suche angeben möchtest, kannst Du dies mit einem voranstehenden Leerzeichen und dem einem Wert von 0-255 machen. Das sieht dann wie folgt aus: „50 my_button.png“. Wenn Du meine Wrapper-Klasse verwendest, macht Diese das für Dich.

Ein einfacher Aufruf – VB NET ImageSearch

Schaue Dir hier einen einfachen, beispielhaften Aufruf der rohen „ImageSearch“-Funktion an:

' dont forget the import..
' Imports AutoIt

Dim x = 0
Dim y = 0
Dim right = 1920 ' full screen width, adjust..
Dim bottom = 1080 ' full screen height, adjust..
Dim tolerance = 50 ' a tolerance value between 0 and 255
Dim imagePath = "my_button.png"
Dim finalImagePath = $"{tolerance} {imagePath}"

Dim result = ImageSearch(x, y, right, bottom, finalImagePath)
Dim res = Marshal.PtrToStringAnsi(result)

Dim imageFound = res(0) = "1"
If Not imageFound Then
    MessageBox.Show("Image not found")
    Return
End If

Dim data = res.Split("|")

x = Integer.Parse(data(1))
y = Integer.Parse(data(2))

' optional, getting image dimensions
' Dim width = Integer.Parse(data(3))
' Dim height = Integer.Parse(data(4))

' do something with the coordinates, like moving to it
AutoItX.MouseMove(x, y)

Meine kleinen Hilfsklassen

Hier zeige ich Dir beiden (wirklich) kleinen Hilfsklassen, Welche die Arbeit mit der „ImageSearch“-Funktion ein wenig vereinfachen soll.

ImageSearchResult-Klasse

Die einfachere Klasse von beiden kommt dabei zuerst, einfach nur ein Zwischenspeicher für die Werte (alternativ könnte man eine Structure verwenden).

Public Class ImageSearchResult

    Public Property Found As Boolean

    Public Property X As Integer

    Public Property Y As Integer

    Public Property Width As Integer

    Public Property Height As Integer

    Sub New(found As Boolean)
        Me.Found = found
    End Sub

End Class

ImageSearch-Klasse

Hier wäre die Klasse, Welche Dir die Aufrufe der „ImageSearch“-Funktion ein wenig vereinfachen könnte:

Imports System.Runtime.InteropServices

Public NotInheritable Class ImageSearch

    <DllImport("ImageSearchDLL.dll")>
    Private Shared Function ImageSearch(
                                 x As Integer,
                                 y As Integer,
                                 right As Integer,
                                 bottom As Integer,
                                 imagePath As String) As IntPtr
    End Function

    Public Shared Function Execute(imagePath As String, Optional tolerance As Integer = 0) As ImageSearchResult
        Dim workingArea = Screen.PrimaryScreen.WorkingArea
        Dim result = DoSearch(0, 0, workingArea.Width, workingArea.Height, imagePath, tolerance)
        Return result
    End Function

    Public Shared Function Execute(x As Integer, y As Integer, right As Integer, bottom As Integer, imagePath As String, Optional tolerance As Integer = 0) As ImageSearchResult
        Dim result = DoSearch(x, y, right, bottom, tolerance, imagePath)
        Return result
    End Function

    Public Shared Function Execute(location As Point, rightBottom As Point, imagePath As String, Optional tolerance As Integer = 0) As ImageSearchResult
        Dim result = DoSearch(location.X, location.Y, rightBottom.X, rightBottom.Y, tolerance, imagePath)
        Return result
    End Function

    Private Shared Function DoSearch(x As Integer, y As Integer, right As Integer, bottom As Integer, imagePath As String, Optional tolerance As Integer = 0) As ImageSearchResult
        imagePath = $"*{tolerance} {imagePath}"

        Dim result = ImageSearch(x, y, right, bottom, imagePath)
        Dim res = Marshal.PtrToStringAnsi(result)

        Dim imageSearchResult = New ImageSearchResult(res(0) <> "0")
        If Not imageSearchResult.Found Then
            Return imageSearchResult
        End If

        Dim data = res.Split("|")

        imageSearchResult.X = Integer.Parse(data(1))
        imageSearchResult.Y = Integer.Parse(data(2))

        imageSearchResult.Width = Integer.Parse(data(3))
        imageSearchResult.Height = Integer.Parse(data(4))

        Return imageSearchResult
    End Function

End Class

Ein Beispiel mit den Hilfsklassen

Hier folgt nun das Beispiel mit Hilfe der Hilfsklassen:

Dim result = ImageSearch.Execute("stop_button.png")
' providing a tolerance
' ImageSearch.Execute("stop_button.png", 50)
' and more overloads..
If Not result.Found Then
    MessageBox.Show("Image not found")
    ' if inside a sub, etc..
    Return
End If
' move to the found coordinates
AutoItX.MouseMove(result.X, result.Y)

Besonders interessant dabei sind die verschiedenen Überladungen, Welche Dir den Aufruf vermutlich verkürzen werden.

Weiterführende Links

Downloads

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.