스플래툰 동영상을 분석해 보았습니다.

스플래툰 동영상 분석 해 보았습니다.



스플래툰의 관전 동영상에서 플레이어의 위치 정보를 해석해 보았습니다.
전 재료는, 홋카이도 고시엔(?)의 오징어 자랑 콘테스트로 유명 팀의 해석을 실시하고 싶었고, 흥미가 있었으므로 자신도 해 보았습니다.

분석 결과



INPUT은 관전 시점의 동영상.
OUTPUT은 각 플레이어의 위치 정보 분포입니다.
예를 들어 한 경기의 네 명의 위치 정보는 다음과 같습니다.
슈터 쪽이 스테이지를 골고루 움직이고 있는 것을 알 수 있군요-.

■리터


■스퍼터리


■프라임


■스퀴크


분석 방법



이런 느낌입니다
① 관전 동영상을 찍는다(수수하게 허들 높다. 설명은 할애)
②동영상을 흑백 변환
③ 흑백 변환된 동영상에서 각 플레이어 이름의 이미지를 추출
④openCV의 패턴 매칭으로 위치 정보 취득
⑤④에서 취득한 위치정보의 주변도 적당히 가중하여 위치정보를 화상으로 출력
⑥스테이지 화상을 ⑤의 화상을 합성

해석 방법의 상세



① 관전 동영상을 찍다
캡처 보드를 샀습니다.
배달자 찾아 풀어 섞어 주었습니다.

②동영상을 흑백 변환
그레이스케일로 변환하여 220을 임계값으로 하여 흑백 변환하였다.
소스 분위기만 쓰면 이하. 보다 편리한 방법 있는 생각도 하지만.

color2gray.py
# 閾値の設定
threshold = 220

fmt = cv2.VideoWriter_fourcc('m', 'p', '4', 'v') # ファイル形式(ここではmp4)
#グレースケールの場合は、ライターの最後の引数をFalseにする(カラーの場合はTrueか省略)
out = cv2.VideoWriter('./video/g_area_1_gray_2.mp4', fmt, frame_rate, (width,height),False) # ライター作成
 while(cap.isOpened()):
    ret, frame = cap.read()
    if ret==True:
        #グレースケール化
        gray_cv = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
        # 二値化(閾値thresholdを超えた画素を255にする。)
        ret, img_thresh = cv2.threshold(gray_cv, threshold, 255, cv2.THRESH_BINARY)

        # write the flipped frame
        out.write(img_thresh)          #output.aviにframe毎書込み
        cv2.imshow('gray_cv',img_thresh)  #グレースケールframeを表示
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break

③ 흑백 변환된 동영상에서 각 플레이어 이름의 이미지를 추출
여기는 수작업. . .
일단 화상 잘라내기 위한 소스는 이하.

cutImage.py
import cv2
playerImg = cv2.imread('./XXX.jpg')
playerImg = playerImg[0:30, 80:150]#ここで切り取る箇所指定
cv2.imwrite('./YYY.jpg', playerImg)
cv2.imshow('playerImg',playerImg)
cv2.waitKey(0)
cv2.destroyAllWindows()

④openCV의 패턴 매칭으로 위치 정보 취득
openCV에서 패턴 매칭.
1프레임마다 위치 정보가 튜플로 반환되므로 리스트에 보관.
매칭에는 몇가지 알고리즘이 있는 것 같고, 어느 것이 좋은가는 잘 모르겠습니다. 비교하는 것도 귀찮아서 적당히 선택했다.
소스는 분위기 이하.

getLocation.py
###読み込む動画(②で白黒変換した動画)###
cap = cv2.VideoCapture('./grayMovie.mp4')
###テンプレート画像(#③で切り取ったプレイヤー名の画像)###
template = cv2.imread('./XXX.jpg',0)
###パターンマッチングのアルゴリズム###
method = cv2.TM_CCOEFF
#位置情報のリスト
player1_locations = []

###パターンマッチング###
while(cap.isOpened()):
    ret, frame = cap.read()
    if ret==True:
        # Apply template Matching
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        res = cv2.matchTemplate(frame,template,method)
        min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

        # If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
        if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
            top_left = min_loc
        else:
            top_left = max_loc
        bottom_right = (top_left[0] + w, top_left[1] + h)
        center = ((top_left[0]+bottom_right[0])//2,(top_left[1]+bottom_right[1])//2)
        player1_locations.append(center)

⑤④에서 취득한 위치정보의 주변도 적당히 가중하여 위치정보를 화상으로 출력
취득한 위치 정보만을 화상에 맵핑하면 정말 미묘한 외형이 되기 때문에, “빛나”하기 위해 했습니다.
작성된 2차원 배열에서 수치가 큰 곳일수록 오랫동안 거주하게 됩니다.
소스 할애하지만, 수치가 클수록 색을 진하게 하고, 플레이어의 위치 정보를 화상으로 합니다.

makeLocationImg.py
#player1のmap上の統計情報を2次元配列で定義
player1_location_statistics_around = np.array([[0] * (width) for i in range(height)], dtype=float)

#player1のmap上の統計情報を計算
for x,y in player1_locations:
    x=int(x)
    y=int(y)
    player1_location_statistics_around[y:y+50,x-50:x+50] += 1
    player1_location_statistics_around[y:y+30,x-30:x+30] += 1
    player1_location_statistics_around[y:y+20,x-20:x+20] += 2
    player1_location_statistics_around[y:y+10,x-10:x+10] += 3
    player1_location_statistics_around[y:y+5,x-5:x+5] += 5

⑥스테이지 화상을 ⑤의 화상을 합성
스테이지 이미지와 ⑤ 플레이어의 위치 정보 이미지를 합성하여 완성🎊

gosei.py
import cv2

stageImg = cv2.imread('./stage_pic/hujiSport.jpg')
player1LocationImg = cv2.imread('./XXX.png')
dst = cv2.addWeighted(stageImg, 1.0, player1LocationImg, 1.0, 0)
cv2.imwrite('./result.jpg', dst)
cv2.imshow('location',dst)
cv2.waitKey(0)
cv2.destroyAllWindows()

끝에



스플래툰을 좋아해서 즐겁게 구현할 수 있었습니다.
오인식해 버리는 곳도 있어 완벽하지는 않지만, 상당히 간편하게 가시화할 수 있어 openCV의 패턴 매칭 굉장히 되어 있지요.
보다 좋은 실장(정밀도 높다든가, 화상 빛나는 아이디어라든지) 있으면 가르쳐 주었으면 합니다.

읽어 주셔서 감사합니다.

좋은 웹페이지 즐겨찾기