36
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PythonとOpenCVでブレ動画を定点カメラっぽくする

Last updated at Posted at 2015-04-06

元ネタ

手振れ動画を定点カメラっぽく補正した話 OpenCV | デジタルクリエイティブのスーパーソフトウエア東京

風でぶれた定点カメラを補正したかったので検索した所、上記サイトを見つけました。
しかしサンプルコードが見つからなかったのでPythonで書いてみました。

使ったもの

  • Python 2.7
    • numpy
  • OpenCV 3.0.0 beta

コード

エラー処理とかは一切やってません。
あと、動いたから良いだろ、と思っているので、肝心の関数の使い方が間違ってるかもしれないです。

findTransformECC_test.py
# -*- coding: utf-8 -*-
import cv2
import numpy as np

# FourCC指定
#fourcc = "DIB "
fourcc = "XVID"

# 変換メソッド指定(?)
#warp_type = cv2.MOTION_AFFINE
#warp_type = cv2.MOTION_EUCLIDEAN
#warp_type = cv2.MOTION_TRANSLATION
warp_type = cv2.MOTION_HOMOGRAPHY

# 出力画像を縦横1/2サイズ(面積1/4)に設定
scale = 2

# WarpMatrixと変換関数を設定
if warp_type == cv2.MOTION_HOMOGRAPHY:
    warp = np.eye(3,3,dtype=np.float32)
    warpTransform = cv2.warpPerspective
else:
    warp = np.eye(2,3,dtype=np.float32)
    warpTransform = cv2.warpAffine

# 入力動画
cap = cv2.VideoCapture(r'./test.mp4')

# キャプチャの情報取得し出力情報を作成
fps = cap.get(cv2.CAP_PROP_FPS)
size = cap.get(cv2.CAP_PROP_FRAME_WIDTH), cap.get(cv2.CAP_PROP_FRAME_HEIGHT)
size = tuple(map(lambda x: int(x / scale), size))

# 基準となる画像を取得
ret, base = cap.read()
base = cv2.resize(base, size)
base = cv2.cvtColor(base, cv2.COLOR_BGR2GRAY)

# 出力先
video1 = cv2.VideoWriter("./out1.avi", cv2.VideoWriter_fourcc(*fourcc), fps, size)

while True:

    # フレーム取得
    ret, frame = cap.read()
    if not ret:
        break
    frame = cv2.resize(frame, size)
    tmp = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    cv2.findTransformECC(tmp, base, warp, warp_type)

    # 出力は元画像(カラー画像)
    out = warpTransform(frame, warp, size)

    # 表示かつAVIに出力
    cv2.imshow("", out)
    video1.write(out)

    k = cv2.waitKey(1)
    if k in [27, ord('q')]:
        # ESCかQキー押下で終了
        break

# 解放
cap.release()
video1.release()
cv2.destroyAllWindows()

追記
wrap_typewarp_typeに直して、findTransfomrECCの引数に入れました。
追記ここまで

嵌まったところ

import cv2.cvが使えない(?)のでwarpMatrixのためのcv2.cv.CreateMatのような、cvパッケージを使ったネットのサンプルソースの部分を置換するときに嵌まりました。

warpMatrix

エラーコード
warpMatrix must be single-channel floating-point matrix in function cv::findTransformECC
みてもサッパリ(フロート指定してんだろ!とずっと思ってた)だったのですが、dtype指定であっさり。

FourCC

これもネットだとcv2.cv.CV_FOURCCで指定する方法ばかりで使えませんでした。
Vimの補完プラグインNeoCompleteがVideoWriter_fourccを教えてくれなかったらどうなっていたか…
ここは後になって見つけました。

まだ気になっていること

  • findTransformECCの第1、第2引数の関係が逆の様な気がする
    • でもwarpAffineの引数を考えるとあっている?

追加のひと工夫

上記のソースはリサイズこそしてるものの、画像全体を対象にしているので、動く物体が動画に大きく写っていると上手く補正してくれないことがありました。

なので、findTransformECCの第1・第2引数に渡す画像を背景の殆ど動かない箇所を選んでbase[:300, :], tmp[:300,:]な感じでクロップ(トリミング?)してやって、warpAffine, warpPerspectiveで変換する時だけもとの画像を使ってやれば劇的に良くなりました。

出力動画もクロップしたものを使えば外側の欠落部分も見えなくなって良い感じになります。

あとは、1日ほっとく場合、最初のフレームじゃなく、直前のフレームを変換したものをベースとしてやれば時間変化に多少強くなるかもしれません。

36
32
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
32

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?