Dense Optical Flow의 결과를 알기 어려웠기 때문에 알기 쉽게 해 보았다

1. 동기



연구에서 Dence Optical Flow를 사용하고 있는데 Dense Optical Flow의 결과 표시는 인간의 시각적으로 알기 어렵지 않습니까?


인용: 옵티컬 플로우(Optical Flow) [ htp://bs. 그래 cs. 푹 빠져. 아 c. jp/sd/메 m r/오야마타/오펜 CV/html/py_개별 ls/py_ゃぃ로 오/py_ぅ인가 s_카나데/py_ぅ인가 s_카나데. HTML ]

이것으로 입력과 출력을 동시에 출력해 비교하지 않으면 제대로 실장되어 있는지 모르겠네요.
그래서, 취득한 동영상상의 이동하고 있는 물체에 대해서 직선을 기재하기로 했습니다. 이것에 의해 선의 방향과 길이로 물체의 이동 방향과 이동량을 알게 되었기 때문에, 1개의 결과로부터 1개의 프레임으로 입력과 결과를 볼 수 있게 되었습니다!

2. 코드



조속하지만 코드입니다. 일부로 구분하여 해설을 써 갑니다.
우선 동영상 로드입니다. 이번에는 OpenCV의 Github에서 공개 된 "vtest.avi"를 캡처했습니다.
우선은 캡처한 동영상(frame1)을 직전의 이미지로서 그레이 스케일화합니다.

opticalflow.py
import cv2
import numpy as np
import os

cap = cv2.VideoCapture("./data/src/vtest.avi")
ret, frame1 = cap.read()
prev = cv2.cvtColor(frame1,cv2.COLOR_BGR2GRAY)

다음 그리기 처리의 함수입니다. 입력 동영상으로부터 이동의 기준이 되는 수치를 산출해, 스스로 결정한 임계치보다 큰 경우에 직선을 추가한다고 하는 흐름입니다.

opticalflow.py
def drawOpticalFlow(frame2, flow, step):
    h, w = frame2.shape[:2]
    x, y = np.mgrid[0:w:step, 0:h:step].reshape(2, -1).astype(np.int32)
    dx, dy = flow[y, x].T
    dist = np.sqrt(dx**2 + dy**2)

    # whereを用いて表示する移動量の閾値を決定 -> threshold
    threshold = 1
    index = np.where(threshold < dist)
    x, y = x[index], y[index]
    dx, dy = dx[index], dy[index]
    line = np.vstack([x, y, x + dx, y + dy]).T.reshape(-1, 2, 2).astype(np.int32)

    # 結果描写
    result = cv2.polylines(frame2, line, False, (0, 0, 255))
    return result

마지막으로 바로 이미지(frame2)를 정의하고 옵티컬 플로우를 실행하여 그리기 함수를 호출합니다. 그런 다음 결과를 표시합니다. 이 근처는 조밀한 옵티컬 플로우에 대해 검색하면 여러가지 샘플 프로그램이 나온다고 생각하므로 참고해 보세요.
제가 기재하고 있는 것도 OpenCV의 튜토리얼( htp://bs. 그래 cs. 푹 빠져. 아 c. jp/sd/메 m r/오야마타/오펜 CV/html/py_개별 ls/py_ゃぃ로 오/py_ぅ인가 s_카나데/py_ぅ인가 s_카나데. HTML )라든지에 실려 있는 것 같은 느낌의 녀석입니다. 모듈을 호출하는 것만으로 계산해 준다니 편리하다.

opticalflow.py
while(1):
    ret, frame2 = cap.read()

    # frame2を直後のイメージとしてグレースケール化
    next = cv2.cvtColor(frame2,cv2.COLOR_BGR2GRAY)

    # アルゴリズムの引数
    # calcOpticalFlowFarneback(prevImg, nextImg, flow, pyrScale, levels, winsize, iterations, polyN, polySigma, flags)
    # prevImg : 直前のイメージ
    # nextImg : 直後のイメージ
    # flow : 計算済みのフロー画像
    # pyrScale : 各画像に対する画像ピラミッドを構築するためのスケール(<1)
    # levels : 最初の画像を含む画像ピラミッドの層の数
    # winsize : 平均化ウィンドウサイズ(ノイズに対する堅牢性)
    # iterations : 画像ピラミッドの各レベルで行う反復回数
    # polyN : ピクセル近傍領域のサイズ
    # polySigma : ガウス分布の標準偏差
    # flags : 処理フラグ
    # 今回のパラメータはほぼ適当な値とされているものを入れているだけである
    flow = cv2.calcOpticalFlowFarneback(prev,next, None, 0.5, 3, 15, 3, 5, 1.2, 0)

    # 描画処理を呼び出し
    opt_frame = drawOpticalFlow(frame2, flow, 16)
    cv2.imshow('opt_frame', opt_frame)

    # escキーを押されたらbreak
    if cv2.waitKey(30) & 0xff == 27:
        break

    # 前の画像を更新
    prev = next

cap.release()
cv2.destroyAllWindows()

3. 결과



얻은 결과는 다음과 같습니다. 선이 얇은 것 같은 생각이 들지만 이동 방향과 이동량은 맞을 것 같네요.


임계값을 작게 했을 경우(threshold=0.01)의 결과도 기재합니다. 이동량이 작은 것도 대상으로 하면 노이즈가 올라 버립니다. 이 근처의 수학적 관계는 잘 모르기 때문에 적절한 값을 선택할 수 있도록 요조사입니다. 지금은 1로 하면 어느 정도는 괜찮을 것 같습니다.


덧붙여서 선의 굵기는 다음과 같이 처리를 바꾸면 굵어집니다. 결과가 보기 어렵다고 하는 분은 참고로 해 주세요.
cv2.polylines(img_copy, lines, False, (0, 0, 255), thickness=2) # thicknessに任意の数値を入れてください

4. 정리



간단하지만 물체의 이동 방향과 이동량을 입력 동영상에 가시화할 수 있었습니다.
방향에 대해서 색을 바꿀 수 있으면 보다 옵티컬 플로우 같아지는 생각이군요.
단지 연구를 진행하는데 있어서는 가시화할 수 있으면 충분하기 때문에 아마 이대로 진행합니다. 시간이 있으면 변경하고 싶다고 생각합니다.

좋은 웹페이지 즐겨찾기