2017-09-05 12 views
3

単純なゲームChrome Dynoからイメージ上のオブジェクトを検出する必要があります。私はPythonとSeleniumを使ってゲームを始め、Canvas Imageを読み込んでいます。メインのタク、この画像上のオブジェクトを検出し、DynoとDynoのバリアを見つけます。Python - オブジェクト上のオブジェクトを解決する

enter image description here

私はOpenCVの、cv2ライブラリを使用して画面上のすべてのオブジェクトを解析するために、このコードを使用しています。 このコード(2つの主な機能)の下には、すべてのオブジェクトを認識するために約80〜200ミリ秒(障壁のサイズに基づいて)かかります。

`

# Finding only dino object based on Template. 
# This might be optimized later with searching by contours 

def find_dino__(self, cv2_image): 
    result = cv2.matchTemplate(cv2_image.astype(np.uint8), self.dino_image, cv2.TM_CCOEFF) 
    _, _, _, dino_top_left = cv2.minMaxLoc(result) 
    dino_bottom_right = (dino_top_left[0] + self.dino_width, dino_top_left[1] + self.dino_height) 
    return GenericGameObject(dino_top_left, dino_bottom_right) 

# Find other Barrier Objects, based on position, and except 
# that, which behind Dino location. Use Dino position. 
def find_dino_barriers__(self, cv2_image, dino_object): 
    img_fil = cv2.medianBlur(cv2.cvtColor(cv2_image, cv2.COLOR_BGR2GRAY), 13) 
    img_th = cv2.adaptiveThreshold(img_fil, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2) 
    im2, contours, hierarchy = cv2.findContours(img_th, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE) 

    objects = [] 
    for i in range(len(contours)): 
     x, y, w, h = cv2.boundingRect(contours[i]) 
     if y < Settings.DINO_WORKING_Y_AREA[0] \ 
       or y > Settings.DINO_WORKING_Y_AREA[1]: 
      continue 
     if x <= dino_object.top_right_point[0]\ 
       and y <= dino_object.top_right_point[1]: 
      continue 
     objects.append(GenericGameObject((x, y), (x + w, y + h))) 

    return objects 

`

私の目標は、他のスクリプトのためのゲームがプレイ可能にするために、それは可能な限り、この時間を短縮です。 BTW私はIAMDinosaurプロジェクトにインスピレーションを与えました.JSとRobot JSを使って、この作業はかなりうまくいっていました。

+0

あなたのマシンにGPUがある場合、OpenCVを使ってCuda/OpenCLを使うのが簡単です。 – zindarod

+0

@ Zindarod私はすべての提案を公開しており、後ほどOpenCLでこれをチェックするかもしれません。私はオブジェクトの認識中に時間を節約するために、ゲームを一時停止することを考えています(ウィンドウを有効/無効にする)。 – GensaGames

+0

私は数ヶ月前に同様のプロジェクトを行っていましたが、opencvの助けを借りてPyautoguiを使ってtrexボットをプレイしました。プログラムは約500点を獲得することができますが、スクリーンショットの技術が遅いため、ボットが死亡します。ここにレポがあります。https://github.com/arsho/t_rex_bot – arsho

答えて

1

スピードを上げるために3つの大きな提案があります。処理パイプラインのさまざまな部分について画像の異なる部分を分割します。異なるオブジェクトを探すことによって得られる追加のスピードアップがあります。 2つの目標は、ディノの位置を見つけて、画像内の新しいオブジェクトの位置を見つけることです。

高速化1

T-Rexの画像の一部を削除し、オブジェクトが中に座っていない。それによってIフレームの上半分(ISH)を意味します。オブジェクトはここにはなく、それは検索スペースを大幅に減らします。

スピードアップ2

あなたの投稿のコメントにこれを記載しました。フレーム全体を通してTレックスを探してはいけません。 T-レックスは、フレーム内のいくつかの水平境界内にスティックがあり、垂直方向にのみ移動することがわかります。テンプレートマッチングは間違いなく遅いプロセスなので、検索領域を減らすことで大きなスピードアップが得られます。小さなテンプレートと小さな検索領域を使用することで、これをさらに洗練させることができます。繰り返しますが、T-Rexが特定の部分にあることを知っていれば、T-Rex の頭部またはのテールは特定の小さな領域にあります。頭や尾などを検索しますその地域で検索領域を最後のフレームのどこに縮小するかによって、これをさらに洗練させることができます。私はこれをやりました。たとえば、tracking Marioです。あなたは、マリオの頭が最後のフレームにあった場所を移動する白い検索エリアボックスを見ることができます。

スピードアップあなただけ...あなたは、あなたがそれらを検出後、オブジェクトが移動どれだけ速く知っているので、スクロールがあるどれだけ速く知っ新しいオブジェクトを見つける必要があり、彼らはどこ終わるだろう3

注意次のフレームでアップする。オブジェクトはフレーム全体の幅ではなく、一度にフレームのある割合しか占めません。したがって、実際には、画面の右側から来る新しいオブジェクトを検索するだけで済みます。次に、それらのタグ(幅、高さ、位置)にを付けて、の位置を計算します。さて、あなたの輪郭検索は、フレームのより小さいサブセットでのみ起こり(より速く)、ループスルー(より速く)する輪郭が少なくなります。

スピードアップあなたは「地面」ラインの下に、単にそれらの底でサボテンを検出することができます4

注意。同様の高さのサボテンは同様の幅を持っているようです。したがって、幅が4ピクセルであるブロックを検出すると、実際に値が何であれ、サボテンが実際には8ピクセルを超えて広がり、30ピクセル高いことがわかります。これはあなたの問題を完全なサボテンの代わりにサボテンの底を検出するように変え、サボテンの探索領域を大幅に減らします。さらに、この方法で輪郭線を見つける必要もありません。画像の下部にあるブロックを探し、あらかじめ定義された距離よりも離れているときにそれらをグループ化することができます。これはの方法より速いはずです。これを行うと、おそらく右の境界線でオブジェクトを検出するだけで心配する必要はなく、新しいフレームで新しい位置を計算する必要があります...もし4px幅のストリップを見ているのであれば、たぶんフレームごとに見つけるよりもはるかに速くないでしょう。

その他の提案

私は本当に適応閾値をぼかすとやってのポイントを理解していません。イメージはすでに事実上バイナリです。黒または非黒の画素である。おそらく、これは複数の別々のオブジェクト(個々のサボテンのようなもの)をグループにまとめてグループにする方法でしょうか?いずれにしても、これを行うにはより良い(より速い)方法があるかもしれません。たとえば、画像を暗くして暗いピクセルを広げると、サボテンがマージされます。私はこれが速くなると思うが、あなたはテストする必要があるだろう。これを行った場合、等高線は実際の幅よりも少し大きくなりますが、拡大しているピクセル数によって境界ボックスを小さくすることで補間できます。もちろん、スピードアップ4を実装しても問題はありませんが、それは何か考えています。

関連する問題