LoginSignup
16
12

More than 5 years have passed since last update.

Deep Flow試してみたよ【OpenCV3】

Posted at

はじめに

OpenCV3にDeep Flow[1]というDeep Learningでオプティカルフローを推定するアルゴリズムが実装さてたので,試してみました.
このDeep Flowは,opencv_contribにしか入っていないので,使用するにはopencv_contribを含むビルドが必要です.
サクッと試してみただけなので,コード載せるだけで特にアルゴリズムの説明とかありません.

使用したデータセットは,KTH Human Action Datasetです.

ソースコード

作成したソースコードは,KTHのデータセットの一つの動画を読み込んで,Deep Flowを計算し,
フローの結果をHSV変換して表示するプログラムです.

#define USE_CUDA 0

の部分の0を1にするとCUDA使用の「Dual TV L1」という別のアルゴリズムが試せます(ちょっとCUDA使ってみたかっただけ).

#include<iostream>
#include<vector>
//自作のOpenCVヘッダ
#include"opencv320.h"

#define USE_CUDA 0 //0:Deep Flow 1:TVL1

using namespace cv;
using namespace std;


int main() 
{
    // 動画読み込み
    cv::VideoCapture cap("person22_jogging_d3_uncomp.avi");
    if (!cap.isOpened()) { return -1; }

    //オプティカルフローの初期化
#if USE_CUDA
    cv::Ptr<cv::cuda::OpticalFlowDual_TVL1> opt = cv::cuda::OpticalFlowDual_TVL1::create();
#else
    cv::Ptr<cv::DenseOpticalFlow> opt = cv::optflow::createOptFlow_DeepFlow();
#endif

    //グレースケール変換
    cv::Mat bimg,gbimg;
    cap >> bimg;
    cv::cvtColor(bimg, gbimg, cv::COLOR_BGR2GRAY);

    //動画保存準備
    cv::Size video_size = cv::Size(bimg.cols + bimg.cols,bimg.rows);
    cv::VideoWriter writer("sample.mp4", cv::VideoWriter::fourcc('m', 'p', '4', 'v'), 25.0, video_size);

    //実行
    while (true) {
        //フレーム読み込み,グレースケール変換
        cv::Mat img,gimg;
        cap >> img;
        if (img.empty()) { break; }
        cv::cvtColor(img, gimg, cv::COLOR_BGR2GRAY);

        //フローの計算
#if USE_CUDA
        cv::cuda::GpuMat ggbimg;
        cv::cuda::GpuMat ggimg;
        ggbimg.upload(gbimg);
        ggimg.upload(gimg);

        cv::cuda::GpuMat flow;
        opt->calc(ggimg, ggbimg,flow);

        cv::Mat nflow;
        flow.download(nflow);
#else
        cv::Mat nflow;
        opt->calc(gimg, gbimg, nflow);
#endif

        //描画用の変換
        std::vector<cv::Mat> vflow;
        cv::split(nflow, vflow);

        cv::Mat magnitude, angle;
        cv::cartToPolar(vflow[0], vflow[1], magnitude, angle, true);

        cv::Mat hsvPlanes[3];
        hsvPlanes[0] = angle;
        normalize(magnitude, magnitude, 0.0, 1.0, cv::NORM_MINMAX); // 正規化
        hsvPlanes[1] = magnitude;
        hsvPlanes[2] = cv::Mat::ones(magnitude.size(), CV_32F);

        //HSVを合成して一枚の画像にする
        cv::Mat hsv;
        merge(hsvPlanes, 3, hsv);

        //HSVからBGRに変換
        cv::Mat buf,flowBgr;
        cv::cvtColor(hsv, buf, cv::COLOR_HSV2BGR);
        buf *= 255.0;
        buf.convertTo(flowBgr, CV_8UC3);

        //  2つの画像を横に並べた大きさのMat型を作成する
        Mat base = cv::Mat::zeros(video_size, CV_8UC3);

        //  img1を張り付ける領域をあらわすMat型を作成する
        Mat roi1(base, Rect(0, 0, img.cols, img.rows));
        //  img1をroi1にコピーする
        img.copyTo(roi1);
        //  img2を張り付ける領域をあらわすMat型を作成する
        Mat roi2(base, Rect(img.cols, 0, flowBgr.cols, flowBgr.rows));
        //  img2をroi2にコピーする
        flowBgr.copyTo(roi2);

        cv::imshow("Match", base);

        writer << base;

        if (cv::waitKey(25) == 27) { //Escで終了
            break;
        }

        gbimg = gimg;  //前フレームをコピー
    }

    return 0;
}

出力結果

フローをHSVで表現していて,色がフローの方向を示し,色の彩度が移動量を示しています.

Match.png

参考サイトリンク

[1]Deep Flow
[2]OpenCVでDeepFlow

16
12
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
16
12