背景
先日,マッサージ師の方に目の動きをよくすると体の動きもよくなると聞きました.具体的には,目の可動域を広げることで肩・腕の可動域が広がるそうで,スポーツ選手の練習にも一部取り入れられているみたいです.目の動きをトラッキングし,右を向いているのか左を向いているのかをトラッキングするプログラムを作ろうと思い立ち,pythonとOpenCVでコーディングしてみました.
概要
目を1/3ごとの領域に分け,下の図の赤の領域に黒目があれば目は左を向いていて,青の領域に黒目があれば右を向いているという識別をします.(inカメラで撮影しているので,下の図と実際の目の向きは左右反転していることにご注意ください.)目の領域を白黒画像にして,黒が80%以上を占めるときに該当する領域に黒目があると判断します.
ソースコード
pythonで記述しています.
目の黒い領域の割合を計算する部分が以下です.
def calc_white_area(bw_image): # 目の黒い領域を計算する.
image_size = bw_image.size
white_pixels = cv2.countNonZero(bw_image)
white_area_ratio = (white_pixels/image_size)*100#[%]
return white_area_ratio
肝心の,目が向いている方向を検出するコードは以下です.
def eye_moving_direction(img, parts, left=True): # 目の向いている方向を出力する.(LEFT of RIGHT or STRAIGHT)
eye_parts = get_eye_parts(parts, True)
if eye_parts == None: # 目の情報が読み取れなかった場合
return None
eye_left_edge = eye_parts[3].x
eye_right_edge = eye_parts[0].x
eye_left_part = img[eye_parts[1].y:eye_parts[2].y, (2*eye_left_edge + eye_right_edge)//3:eye_left_edge]
eye_right_part = img[eye_parts[1].y:eye_parts[2].y, eye_right_edge:(eye_left_edge + 2*eye_right_edge)//3]
eye_img = img[eye_parts[1].y:eye_parts[2].y, eye_parts[0].x:eye_parts[3].x]
_, eye_left_part = cv2.threshold(cv2.cvtColor(eye_left_part, cv2.COLOR_RGB2GRAY), get_median_value_from_img(eye_img), 255, cv2.THRESH_BINARY_INV) # 左目部分の2値化バイナリデータ
_, eye_right_part = cv2.threshold(cv2.cvtColor(eye_right_part, cv2.COLOR_RGB2GRAY), get_median_value_from_img(eye_img), 255, cv2.THRESH_BINARY_INV) # 右目部分の2値化バイナリデータ
black_eye_occupancy_rate_threshold = 80
if calc_white_area(eye_left_part) > black_eye_occupancy_rate_threshold:
return LEFT
elif calc_white_area(eye_right_part) > black_eye_occupancy_rate_threshold:
return RIGHT
else:
return STRAIGHT
フルスクラッチは以下に置いてあります.
https://github.com/remmaTech12/eyeMovementOnLinux
動画
左に目が動いたときにLEFT,右に目が動いたときにRIGHTと表示されることが確認できます.
参考
- ・OpenCVとpythonの基礎知識・黒目の重心位置を求める方法
- ・dlibで取得する特徴点に関する情報
- ・画像にモザイク処理をかける方法
備考
光の当たり具合によっては,目の向いている方向を識別するのが困難な場合があります.
コメント