spielkarten erkennen

  • VB.NET

Es gibt 15 Antworten in diesem Thema. Der letzte Beitrag () ist von Mangafreak1995.

    spielkarten erkennen

    Hallo,

    ich bin dabei ein kartenspiel zu programmieren.

    Ich habe auf dem bildschirm spielkarten und möchte die erkennen (wert und farbe sind IMMER in dem selben bereich)

    jetzt brauch ich etwas, was mir sagt, welche karte sich in einem definiertem Bereich (gerne auch frei wählbaren) befindet.

    bis jetzt kann ich mit meiner funktion

    VB.NET-Quellcode

    1. pixel(200,500)

    die RGB farben eines pixels auslesen. als ergebnis bekomm ich dieses format: "Color [A=255, R=35, G=65, B=25]"

    jedoch weiß ich jetzt nicht wie ich das benutzen soll um buchstaben und zeichen auszulesen.

    Außerdem muss ich erst ein screenshot machen bevor ich das pixel auslesen kann. das dauert zwar etwas, aber schlimmstenfalls kann ich damit leben.

    gibt es vielleicht externe software die das kann? ich kann nämlich auch schon mit VB mausklicks simulieren, d.h. ich könnte dann mit VB die exterene software bedienen.

    bin offen für jede hilfe, stichpunkte und teillösungen
    Hallo,

    da würde dann das Thema OOP kommen ;) dafür würdest du doch einfach ein Objekt machen, welches eine Eigenschaft hat, an der die Karte erkannt werden soll...wenn du das nicht willst, dann solltest du dir mal die LockBits Funktion von Image/Bitmap angucken und System.Marshall.Copy...

    welche externe Software willst du denn steuern? Wenn du ein Kartenspiel programmierst, dann musst du dieses doch nicht von extern steuern?!

    Mfg jvbsl
    Ich wollte auch mal ne total überflüssige Signatur:
    ---Leer---
    ne ich mein sowas wie ein tool, wo du mit der maus ein kästchen ziehst und das sagt dann herz ass oder sowas.

    das mit OOP ist glaub schwer, weil die karten nicht von mir sind. Ich spiel online mau mau und will eine automatische routine programmieren, die drauf antwortet.

    von deinen tipps sagt mir jetzt alles nix, aber ich werd jetzt mal probieren googlen und dann feedbacken :)

    danke schonmal
    also was ich jetzt so über die LockBits gelesen habe scheint irgendwie nicht das richtige zu sein. angeblich kann man so zeichenfolgen sperren. lass mich aber gern eines besseren belehren.

    gibt es vielleicht eine möglichkeit bilder zu vergleichen? das ich sagen kann ich hab hier ein 50x50 pixel bild und ich möchte vergleichen ob im bereich 100x100 bis 150x150 dasselbe, oder ähnliche bild zu finden ist?

    so eine art OCR eben
    wie oben gesagt ich antworte auf ein bereits vorhandenes programm. mann kann ja zb über ICQ karten spielen und mein programm soll voll automatisch spielen, ohne menschliche bedienung. die endscheidungsroutine hab ich schon programiert, ich muss nur noch rauskriegen welche karte mein gegner gespielt hat.
    es gibt einen bestimmten Bereich wo die Karte des Gegners liegt
    die bestimmts du abhängig von dem Screen (oder Form)
    dann machst du einen Shot vom Screen (oder der Form)
    an der Stelle der Karte und wertest das Bild aus
    am besten mit einem Vergleich wie diesem

    VB.NET-Quellcode

    1. Public Function Ähnlichkeit(img1, iimg2 as Bitmap) as Double
    2. Dim col as list of Color
    3. Dim count as list of Integer
    4. For x as integer = 0 to img1.width - 1
    5. For y as integer = 0 to img1.Height -1
    6. If Not(col.Contains(img1.getpixel(x,y))) Then
    7. col.Add(img1.getpixel(x,y))
    8. Else
    9. count(col.IndexOf(img1.getpixel(x,y)) += 1
    10. End If
    11. NExt
    12. Next
    13. Dim col2 as list of Color
    14. Dim count2 as list of Integer
    15. For x as integer = 0 to img2.width - 1
    16. For y as integer = 0 to img2.Height -1
    17. If Not(col.Contains(img2.getpixel(x,y))) Then
    18. col2.Add(img2.getpixel(x,y))
    19. Else
    20. count2(col.IndexOf(img2.getpixel(x,y)) += 1
    21. End If
    22. NExt
    23. Next
    24. ' ...

    das ist nur schnell überlegt aber der Ansatz könnte helfen
    bei dem jetztigen Code werden deine Farben aufgelisten und dazu die Anzahl der Farbe
    wenn du jetzt dir etwas zusammenbastelst um rauszufinden wie anhand der Daten der beiden Bilder sie wie stark übereinstimmen
    hast du es
    den Wert würd ich dann als Prozentwert (Double) zurückgeben damit du eine Toleranz einbringen kannst

    Ein Screen direkt von der Form hat einen Vorteil [VB 2008] Screen von der FORM machen
    eine funktion die mir ein screenshot erstellt habe ich bereits geschrieben :)
    wie kann ich denn die funktion änhlichkeit aufrufen?

    was ist denn "list of integer" und "list of color" für ein typ? die werden bei mir auch gar nicht erkannt.

    VB.NET-Quellcode

    1. Public Function Ähnlichkeit(ByVal img1 As Bitmap, ByVal img2 As Bitmap) As Double
    2. Dim col1 as list of Color
    3. Dim count1 as list of Integer
    4. For x As Integer = 0 To img1.width - 1
    5. For y As Integer = 0 To img1.Height - 1
    6. If Not (col1.Contains(img1.GetPixel(x, y))) Then
    7. col1.Add(img1.GetPixel(x, y))
    8. Else
    9. count1(col1.IndexOf(img1.GetPixel(x, y)) = +1)
    10. End If
    11. Next
    12. Next
    13. Dim col2 as list of Color
    14. Dim count2 as list of Integer
    15. For x As Integer = 0 To img2.Width - 1
    16. For y As Integer = 0 To img2.Height - 1
    17. If Not (col.Contains(img2.GetPixel(x, y))) Then
    18. col2.Add(img2.GetPixel(x, y))
    19. Else
    20. count2(col.IndexOf(img2.GetPixel(x, y)) = +1)
    21. End If
    22. Next
    23. Next
    24. End Function


    und muss das unten in der schleife nicht beides mal col2 heißten?

    vielen dank für deine hilfe :)

    ist die funkton so richtig?
    ich kanns kompilieren, aber hab halt paar kleine warnungen:

    VB.NET-Quellcode

    1. Public Function Ähnlichkeit(ByVal img1 As Bitmap, ByVal img2 As Bitmap) As Double
    2. Dim col1 As List(Of Color)
    3. Dim count1 As List(Of Integer)
    4. For x As Integer = 0 To img1.width - 1
    5. For y As Integer = 0 To img1.Height - 1
    6. If Not (col1.Contains(img1.GetPixel(x, y))) Then
    7. col1.Add(img1.GetPixel(x, y))
    8. Else
    9. count1(col1.IndexOf(img1.GetPixel(x, y))) = +1
    10. End If
    11. Next
    12. Next
    13. Dim col2 As List(Of Color)
    14. Dim count2 As List(Of Integer)
    15. For x As Integer = 0 To img2.Width - 1
    16. For y As Integer = 0 To img2.Height - 1
    17. If Not (col2.Contains(img2.GetPixel(x, y))) Then
    18. col2.Add(img2.GetPixel(x, y))
    19. Else
    20. count2(col2.IndexOf(img2.GetPixel(x, y))) = +1
    21. End If
    22. Next
    23. Next
    24. End Function
    klar kann es sein dass ich mich verschrieben habe
    ich meinte auch List (of Type)

    die Function bis jetzt ist richtig
    nur gibt sie keinen Wert zurück

    ich hab schon mal ja einen Anfang gemacht
    jetzt denkst du dir was aus wie du mit den Daten
    Bild1:
    Anzahl der Farben
    Anzahl wie oft eine Farbe benutzt wurde

    Bild2:
    Anzahl der Farben
    Anzahl wie oft eine Farbe benutzt wurde

    dir eine prozentualen Wert zurückgeben lässt wie stark sie sich unterscheiden
    Hi
    Ich will ja jetzt nicht deine Enthusiasmusjuhurufe stören, aber das was du zu OOP (Objektorientierte Programmierung) gesagt hast, zeigt, wie gut du Bescheid weißt. Meine Empfehlung wäre, einfach bei was leichtem einzusteigen, weil Schrifterkennung Bilderkennung nicht unbedingt das leichteste ist.
    Mangafreak1995 hat zwar bereits einen Ansatz geliefert, dieser ist aber noch sehr ausbaufähig. Viel mehr solltest du eine gewisse Toleranzgrenze machen und bestimmte Bitarrays oder Bitmaps verwenden um die beiden Bilder zu vergleichen. Dabei ist es sinnvoll, hier ein Foto von der Karte zu posten.

    zur Erläuterung: Bei der Methode mit den Bit-Arrays denke ich an eine Realisierung, die ein Bild über Helligkeiten vergleicht. Liegt die Helligkeit(Color.GetBrightness) beispielsweise unter 0.75F, so ist es ein aktiver Punkt mit Schrift. Dann die einzelnen Pixel entweder mit der Marshal-Methode von jvbsl oder per GetPixel vergleichen. Die GetBrightness-Methode würde wegfallen, wenn du mehrere Bitmaps vergleichst.
    Auf jeden Fall solltest du dir schon mal viel Zeit einplanen, um ein wenig mehr VB zu lernen.

    Gruß
    ~blaze~
    vielen dank erstmal für eure hilfe.

    ich bin mittlerweile soweit gekommen, dass ich einen bereich im bildschirm definiert hab und von dort die ein pixelarray erstellt hab mit der rgb nummer für jedes pixel.

    dann hab ich fest definierte arrays erstellt die die karten ergaben und konnte dann schön sagen vergleiche das erstellte array mit den arrays aus den fest definierten arrays, und wenn eins gleich ist, dann hab ich die richtige karte gefunden.

    das hat bis jetzt meisten ganz gut geklappt.

    das blöde ist nur, es klappt nicht immer. es liegt nicht an ungenauigkeit der pixel oder so, sndern die kartenbilder sind nicht immer gleich. da gibts ein zwei pixel, die sich mal unterscheiden, und dann kommts mal vor das ich die karte nicht finde :(

    bin kurz davor aufzugeben....
    das einzige was ich noch im kopf habe, wäre eine mit einer OCR software den screenshot auslesen.
    kennt da jemand eins das das kann und auch kostenlos ist?

    oder hat jemand eine andere idee?
    Wie überprüfst du die Arrays? Sicher gibts hierbei auch die Möglichkeit den Grad der Abweichung zu ermitteln und wenn sich 2 Pixel unterscheiden kann man davon ausgehen das die Karte trotzdem stimmt, somit könnte man einen Wert festlegen wie z.B. die Abweichung muss unter 15 Pixel oder so sein.
    ich vergleiche in einer schleife jedes einzelne element.

    der bereich indem die karte ist geht vom punkt(700,210) bis punkt(709,240)
    ich hab immer jedes dritte pixel in das array geschrieben, damit das vergleichen nicht solang dauert, hab also arrays der dimension (2,9)

    VB.NET-Quellcode

    1. Private Function AVergleich(ByVal q As Array, ByVal b As Array)
    2. Dim m, n As Integer
    3. n = 0
    4. Do
    5. m = 0
    6. Do
    7. If q(m, n) <> b(m, n) Then
    8. Return "00" '"Kartenwert nicht gefunden"
    9. Exit Function
    10. End If
    11. m = m + 1
    12. Loop Until m = 3
    13. n = n + 1
    14. Loop Until n = 9
    15. Select Case ArNr
    16. Case 1
    17. ArNr = 0
    18. Return "ak"
    19. Case 2
    20. ArNr = 0
    21. Return "ap"
    22. Case 3
    23. ArNr = 0
    24. Return "as"
    25. Case 4
    26. ArNr = 0
    27. Return "ah"
    28. Case 5
    29. ArNr = 0
    30. Return "kk"
    31. Case 6
    32. ArNr = 0
    33. Return "kp"
    34. Case 7
    35. ArNr = 0
    36. Return "ks"
    37. Case 8
    38. ArNr = 0
    39. Return "kh"
    40. Case 9
    41. ArNr = 0
    42. Return "qk"
    43. Case 10
    44. ArNr = 0
    45. Return "qp"
    46. Case 11
    47. ArNr = 0
    48. Return "qs"
    49. Case 12
    50. ArNr = 0
    51. Return "qh"
    52. Case 13
    53. ArNr = 0
    54. Return "jk"
    55. Case 14
    56. ArNr = 0
    57. Return "jp"
    58. Case 15
    59. ArNr = 0
    60. Return "js"
    61. Case 16
    62. ArNr = 0
    63. Return "jh"
    64. Case 17
    65. ArNr = 0
    66. Return "tk"
    67. Case 18
    68. ArNr = 0
    69. Return "tp"
    70. Case 19
    71. ArNr = 0
    72. Return "ts"
    73. Case 20
    74. ArNr = 0
    75. Return "th"
    76. Case 21
    77. ArNr = 0
    78. Return "9k"
    79. Case 22
    80. ArNr = 0
    81. Return "9p"
    82. Case 23
    83. ArNr = 0
    84. Return "9s"
    85. Case 24
    86. ArNr = 0
    87. Return "9h"
    88. Case 25
    89. ArNr = 0
    90. Return "8k"
    91. Case 26
    92. ArNr = 0
    93. Return "8p"
    94. Case 27
    95. ArNr = 0
    96. Return "8s"
    97. Case 28
    98. ArNr = 0
    99. Return "8h"
    100. Case 29
    101. ArNr = 0
    102. Return "7k"
    103. Case 30
    104. ArNr = 0
    105. Return "7p"
    106. Case 31
    107. ArNr = 0
    108. Return "7s"
    109. Case 32
    110. ArNr = 0
    111. Return "7h"
    112. Case 33
    113. ArNr = 0
    114. Return "6k"
    115. Case 34
    116. ArNr = 0
    117. Return "6p"
    118. Case 35
    119. ArNr = 0
    120. Return "6s"
    121. Case 36
    122. ArNr = 0
    123. Return "6h"
    124. Case 37
    125. ArNr = 0
    126. Return "5k"
    127. Case 38
    128. ArNr = 0
    129. Return "5p"
    130. Case 39
    131. ArNr = 0
    132. Return "5s"
    133. Case 40
    134. ArNr = 0
    135. Return "5h"
    136. Case 41
    137. ArNr = 0
    138. Return "4k"
    139. Case 42
    140. ArNr = 0
    141. Return "4p"
    142. Case 43
    143. ArNr = 0
    144. Return "4s"
    145. Case 44
    146. ArNr = 0
    147. Return "4h"
    148. Case 45
    149. ArNr = 0
    150. Return "3k"
    151. Case 46
    152. ArNr = 0
    153. Return "3p"
    154. Case 47
    155. ArNr = 0
    156. Return "3s"
    157. Case 48
    158. ArNr = 0
    159. Return "3h"
    160. Case 49
    161. ArNr = 0
    162. Return "2k"
    163. Case 50
    164. ArNr = 0
    165. Return "2p"
    166. Case 51
    167. ArNr = 0
    168. Return "2s"
    169. Case 52
    170. ArNr = 0
    171. Return "2h"
    172. Case Else
    173. Return "01" '"Kartenname nicht gefunden"
    174. End Select
    175. End Function


    die funktion hab ArNr hochzählen lassen und dann zB bei ArNr = 1 hab ich die funktion mir as kreuz aufgerufenbei ArNr = 2 mit as piek usw...

    ArNr = 0 heißt die Karte ist gefunden und die Schleife wird beendet. Sobald ein Arrayelement nicht übereinstimmt wird der Vergleich mit der nächsten Karte gestartet. So hab ich in weniger als 5 sekunden eine karte gefunden. (getestet habe ich das mit screenshots, aber im richtigen spiel dann waren die karten mal um ein pixel anders und schon konnte man das nicht finden)

    hab erst gedacht das ich vielleicht die pixel runden kann, aber das ging auch nicht weil in meinem beispiel statt ein weißes pixel das eine diesmal schwarz war, und das sind ja ganz andere farben.

    wie würdest du das genau realisieren mit der abweichung?
    ich werd sobald ich wieder zeit hab mal schauen, wie viel pixel sich da ungefähr unterscheiden.

    vielen dank schonmal :)
    du nimmst noch einen counter der die Fehler zählt und erst wenn der über 15 ist dann wird erst abgebrochen
    das ist im Prinzip eine Art für die Toleranz
    Zudem würde man hier auf eine For Next Schleif zurückgreifen und eine Do Loop Schleife.

    VB.NET-Quellcode

    1. Dim Toleranz As Integer = 0
    2. For x As Integer = 0 To 2
    3. For y As Integer = 0 To 9
    4. If Not q(x,y) = b(x,y) Then Toleranz += 1
    5. Next y
    6. Next x
    7. If Toleranz < 15 Then MessageBox.Show("Das Array 'q' entspricht dem Array 'b' mit einer Abweichung von " & Toleranz & " Pixel")
    naja man muss nich die ganze Karte nehmen
    reicht ja das Zeichen oder das Bild