Apex LegendsのダメージをOCRで取得する試みをしてきたわけだが、部隊数や人数の変動により右上の表示エリアが白から赤に変わってしまって取得できないことが分かった。

ダメージの数値自体は白のままでその周りが赤っぽくなり、目印にしていたシンボルマークが赤くなってしまって検知できないため、OCRの取得処理ができていない。
そもそも赤くなってしまうのが問題なので、白くすればよいという結論に至る。
具体的な方法としては、前回も使用したHSV(色相、彩度、明度)に変換して、赤の色相の場合には彩度を0にすれば白くなると思った。
またこの時に明度が低い場合は、黒っぽい色のはずなので対象から省くこととする。
OpenCVの画像認識処理の書かれたブログなどを見ても、いつもながら適切なものが見つからないので、自作していくことにする。
完成したものがこちら、コメントに解説を入れようと思ったがゴチャつくので抜き出しながら個別に解説する。
def red2white(img):
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
white_image = np.copy(hsv)
coeff = 1.1
cond = ( ((hsv[:, :, 0]>150) | (hsv[:, :, 0]<30)) & (hsv[:, :, 1]>150) )
revised_val = np.array(hsv[:, :, 2],dtype="int16")*coeff
revised_val = np.clip(revised_val,None,255)
white_image[:, :, 1] = np.where(cond,0,hsv[:, :, 1])
white_image[:, :, 2] = np.where(cond,revised_val,hsv[:, :, 2])
return cv2.cvtColor(white_image, cv2.COLOR_HSV2BGR) # HSV->BGR変換
まずはnp.whereで使う条件を変数に入れている。
cond = ( ((hsv[:, :, 0]>150) | (hsv[:, :, 0]<30)) & (hsv[:, :, 1]>150) )
直接指定しても良いのだが長くなってしまい見にくいので、外に出した。
最初の部分は色相の30未満、150より上の値が今回の対象の赤を含んでいたためOR結合している。
最後のAND以降は、明度が低いと黒に近づくため対象外とするため150より大きい値を対象としている。
hsv[:, :, 0]という部分に関しては、0でHue,1ならSatiration,2がValueのnp.arrayに対しての操作を行っている。
次に置換する明度の配列を作成している。
revised_val = np.array(hsv[:, :, 2],dtype="int16")*coeff
np.arrayの部分は元々の配列がデバッガで確認したところ、uint8だったため255より大きい値になると桁あふれを起こしてしまうため、int16に変換してからcoeffを掛けることで起きる桁あふれを防いでいる。
ただし、255より大きい値は意味がなく後で置換したときにuint8に戻ってしまう。
このため、次にnp.clipでオーバーしている数値を255にしている。
revised_val = np.clip(revised_val,None,255)
最初のnp.whereで対象の部分の彩度を0にして、それ以外はそのまま使う。
white_image[:, :, 1] = np.where(cond,0,hsv[:, :, 1])
その次のnp.whereで対象の部分の明度を係数を掛けた値と置き換える。
white_image[:, :, 2] = np.where(cond,revised_val,hsv[:, :, 2])
あとはreturnの行で画像形式をBGRに戻して返す。
結果以下のように、ほぼほぼ白い時の画像に近づいた。

輪郭部分とシンボルがぼやけてしまっているが、係数をあまり大きくしてもアシストの握手している部分が潰れてしまうのでとりあえず1.1で検知できるかを試していくことにする。
今回は適当な値を入れたり、Windowsのペイントアプリのスポイトで気になる色を取得後、パレットでRGBからHSVにすることで大まかな値を調べた。
ただし、ペイントのHSV表示では色相が0~359,彩度が0~100,明度が0~100となっており、OpenCVのHSVとは値が異なるので値を直す必要があるので注意が必要となる。








