2016-05-08 17 views
0

私は顔の追跡のためのサンプルしか見つけませんでした。特定の色の長方形を追跡する方法

どのように特定の色の四角形を追跡できますか?

そして、そのピクセルが必要です。

enter image description here

+0

あなたは基本的にあなたのスクリーンを反復処理すると、特定の色の値を探します。一度あなたがそれを見つけたら、その位置からの矩形のサイズであるセクションを繰り返し繰り返し、すべての値が一致するかどうかをチェックする必要があります。これは、ビデオゲームのボットを書く最悪の方法だと教えてください。それは、スーパーエラーが発生しやすく、最適化の方法を見つけたとしても、すべての単一フレームを更新したい場合は1トンの計算力が必要です。より良い方法は、Ramから、またはソケットストリームから直接これらの座標を取得することです。これはPythonでは不可能です。 –

答えて

1

はここでそれを行いますスクリプトです場合:

from PIL import Image 
from math import sqrt 

RED = 0 
GREEN = 1 
BLUE = 2 
COLORS = [RED, GREEN, BLUE] 
RED_HEALTH = (234, 105, 112) 
BLUE_HEALTH = (84, 165, 226) 
HEALTH_BORDER = (0, 0, 0) 
image = Image.open("image.jpg") 

def close_enough_to(src, target, delta): 
    diff = 0 
    for color in COLORS: 
     diff += (src[color] - target[color]) ** 2 
    diff = sqrt(diff) 
    return diff <= delta 

class HealthBar: 
    def __init__(self, team, health_percentage, length, pos): 
     self.team = team 
     self.health_percentage = health_percentage 
     self.length = length 
     self.pos = pos 

    def __str__(self): 
     return "team {}, percentage {}, length {}, pos {}".format(self.team, 
       self.health_percentage, 
       self.length, 
       self.pos 
       ) 

    def __repr__(self): 
     return str(self) 

def flood_fill_health_bar(image, pos, color, traversed): 
    (x, y) = pos 
    health_pixels = 0 
    while close_enough_to(image.getpixel((x, y)), color) \ 
     and (x, y) not in traversed: 
     health_pixels += 1 
     traversed.add((x, y)) 
     x += 1 
    black_pixels = 0 
    while close_enough_to(image.getpixel((x, y)), HEALTH_BORDER, 50) \ 
     and (x, y) not in traversed: 
     black_pixels += 1 
     traversed.add((x, y)) 
     x += 1 
    if black_pixels > 0: 
     if color is RED_HEALTH: 
      team = "red" 
     else: 
      team = "blue" 
     percent_health = health_pixels/(health_pixels + black_pixels) 
     return HealthBar(team, percent_health, health_pixels + black_pixels, pos) 

def in_bounds(image, pos): 
    return pos[0] >= 0 and pos[1] >= 0 \ 
      and pos[0] < image.width and pos[1] < image.height 

def flood_fill_image(image, start, delta): 
    flood_fill_queue = [start] 
    traversed = [] 
    color = image.getpixel(start) 
    pos = start 
    pix = image.load() 
    while len(flood_fill_queue): 
     (x, y) = flood_fill_queue.pop() 
     positions = [(x+1, y), (x-1, y), (x, y+1), (x, y-1)] 
     for position in positions: 
      if in_bounds(image, position) \ 
        and close_enough_to(image.getpixel(position), color, delta): 
       if position not in traversed: 
        flood_fill_queue.append(position) 
        traversed.append(position) 
        (x, y) = position 
        pix[x, y] = (0, 0, 255) 
    return traversed 

def get_width(positions): 
    return get_max_x(positions) - get_min_x(positions) 

def get_height(positions): 
    return get_max_y(positions) - get_min_y(positions) 

def get_max_x(positions): 
    return sorted(list(positions), key=lambda x: x[0])[-1][0] 

def get_max_y(positions): 
    return sorted(list(positions), key=lambda x: x[1])[-1][1] 

def get_min_x(positions): 
    return sorted(list(positions), key=lambda x: x[0])[0][0] 

def get_min_y(positions): 
    return sorted(list(positions), key=lambda x: x[1])[0][1] 

def find_health_bars(image): 
    traversed = set() 
    health_bars = [] 
    pix = image.load() 
    (width, height) = image.size 
    for col in range(0, width): 
     for row in range(0, height): 
      # pix = image.getpixel((col, row)) 
      if (col, row) in traversed: 
       continue 
      for health_color in [RED_HEALTH, BLUE_HEALTH]: 
       border_pixels = [] 
       if close_enough_to(image.getpixel((col, row)), health_color, 10): 
        health_pixels = flood_fill_image(image, (col, row), 100) 
        for pos in health_pixels: 
         (x, y) = pos 
         traversed.add(pos) 
         pix[x, y] = (255, 255, 0) 
        border_pixels = flood_fill_image(image, (col - 1, row - 1), 30) 
        if len(border_pixels) is 0: 
         continue 
        health_bar_width = get_width(border_pixels) 
        health_bar_height = get_height(border_pixels) 
        health_width = get_width(health_pixels) 
        if abs(health_bar_width/health_bar_height) - 10 <= 0.5: 
         team = "blue" if health_color == BLUE_HEALTH else "red" 
         percent_health = health_width/health_bar_width 
         health_bar = HealthBar(team, percent_health, health_bar_width, (col, row)) 
         health_bars.append(health_bar) 

       for pos in border_pixels: 
        (x, y) = pos 
        traversed.add(pos) 
        pix[x, y] = (0, 255, 255) 
    health_bars = [health_bar for health_bar in health_bars if health_bar is not None] 
    health_bars.sort(key=lambda x: x.length) 
    return health_bars 

health_bars = find_health_bars(image) 

print(health_bars) 

基本的にこれはアルゴリズムです:画像全体トラバース

  1. 、赤/青を探してヘルスバー
  2. これを見つけたら、スーパーハッキーのflood-fill関数を実行して、ヘルスバーが使用する座標を探します。
  3. ヘルスバーの境界線を取得するために同じフラッドフィル機能を実行します。
  4. 罫線の幅と正常性の幅を見つけ、もう一方を分割して正常性を取得します。 enter image description here

    :ここ

は洪水フィルは(関数が、私はそれはしかし問題になることはありません想像し、サークルで素晴らしいプレーしません...)が計算された後、それは視覚的にどのように見えるのです

黄色い部分は健康バーの健康部分で、シアンは境界線です。あなたが見ることができるようにそれは完璧ではないがうまくいけば十分に近い。また、私はあなたがこれを使用する画像はjpgの代わりにpngになると仮定します。そのため、不正確さがなくなります。

編集:ここではhealth_barsを印刷の出力です:

[team blue, percentage 1.0, length 20, pos (66, 433), team blue, percentage 1.0, length 34, pos (130, 436), team red, percentage 0.38095238095238093, length 63, pos (149, 357), team blue, percentage 0.953125, length 64, pos (27, 404), team red, percentage 0.6703296703296703, length 91, pos (480, 119), team red, percentage 0.5700934579439252, length 107, pos (500, 52)]

+0

うまくいきます。本当にありがとう@マーカスバフェット – Levi

+0

本当にありがとう、マーカス。 RED_HEALTH =(234、105、112)、close_enough_toの引数として、どのように健康価値を得るのですか? – Levi

+0

あなたは '(234、105、112)'を思いついたのですか?私はちょうどカラーピッカーを使用して、ヘルスバーのピクセルのRGB値を取得しました。ミニオンの健康価値を取得する方法を意味するならば、出力の 'percentage'フィールドを見たいと思っています。 –

0

、このリストを反復し、その赤または青のいずれかであれば見て、あなたはすべての手先に入れてリストを作成します。ザッツ可能...

関連する問題