Path: blob/master/Getting-Started-OpenCV-CUDA-Module/demo.cpp
3119 views
#include <iostream>1#include <string>2#include <vector>3#include <unordered_map>4#include <stdlib.h>5#include <chrono>67#include <opencv2/core.hpp>8#include <opencv2/imgproc.hpp>9#include <opencv2/highgui.hpp>10#include <opencv2/videoio.hpp>11#include <opencv2/video.hpp>12#include <opencv2/cudaarithm.hpp>13#include <opencv2/cudaimgproc.hpp>14#include <opencv2/cudawarping.hpp>15#include <opencv2/cudaoptflow.hpp>1617using namespace cv;18using namespace cv::cuda;19using namespace std;20using namespace std::chrono;212223void calculate_optical_flow(string videoFileName, string device)24{25// init map to track time for every stage at each iteration26unordered_map<string, vector<double>> timers;2728// init video capture with video29VideoCapture capture(videoFileName);30if (!capture.isOpened())31{32// error in opening the video file33cout << "Unable to open file!" << endl;34return;35}3637// get default video FPS38double fps = capture.get(CAP_PROP_FPS);3940// get total number of video frames41int num_frames = int(capture.get(CAP_PROP_FRAME_COUNT));4243// read the first frame44cv::Mat frame, previous_frame;45capture >> frame;4647if (device == "cpu")48{49// resize frame50cv::resize(frame, frame, Size(960, 540), 0, 0, INTER_LINEAR);5152// convert to gray53cv::cvtColor(frame, previous_frame, COLOR_BGR2GRAY);5455// declare outputs for optical flow56cv::Mat magnitude, normalized_magnitude, angle;57cv::Mat hsv[3], merged_hsv, hsv_8u, bgr;5859// set saturation to 160hsv[1] = cv::Mat::ones(frame.size(), CV_32F);6162while (true)63{64// start full pipeline timer65auto start_full_time = high_resolution_clock::now();6667// start reading timer68auto start_read_time = high_resolution_clock::now();6970// capture frame-by-frame71capture >> frame;7273if (frame.empty())74break;7576// end reading timer77auto end_read_time = high_resolution_clock::now();7879// add elapsed iteration time80timers["reading"].push_back(duration_cast<milliseconds>(end_read_time - start_read_time).count() / 1000.0);8182// start pre-process timer83auto start_pre_time = high_resolution_clock::now();8485// resize frame86cv::resize(frame, frame, Size(960, 540), 0, 0, INTER_LINEAR);8788// convert to gray89cv::Mat current_frame;90cv::cvtColor(frame, current_frame, COLOR_BGR2GRAY);9192// end pre-process timer93auto end_pre_time = high_resolution_clock::now();9495// add elapsed iteration time96timers["pre-process"].push_back(duration_cast<milliseconds>(end_pre_time - start_pre_time).count() / 1000.0);9798// start optical flow timer99auto start_of_time = high_resolution_clock::now();100101// calculate optical flow102cv::Mat flow;103calcOpticalFlowFarneback(previous_frame, current_frame, flow, 0.5, 5, 15, 3, 5, 1.2, 0);104105// end optical flow timer106auto end_of_time = high_resolution_clock::now();107108// add elapsed iteration time109timers["optical flow"].push_back(duration_cast<milliseconds>(end_of_time - start_of_time).count() / 1000.0);110111// start post-process timer112auto start_post_time = high_resolution_clock::now();113114// split the output flow into 2 vectors115cv::Mat flow_xy[2], flow_x, flow_y;116split(flow, flow_xy);117118// get the result119flow_x = flow_xy[0];120flow_y = flow_xy[1];121122// convert from cartesian to polar coordinates123cv::cartToPolar(flow_x, flow_y, magnitude, angle, true);124125// normalize magnitude from 0 to 1126cv::normalize(magnitude, normalized_magnitude, 0.0, 1.0, NORM_MINMAX);127128// get angle of optical flow129angle *= ((1 / 360.0) * (180 / 255.0));130131// build hsv image132hsv[0] = angle;133hsv[2] = normalized_magnitude;134merge(hsv, 3, merged_hsv);135136// multiply each pixel value to 255137merged_hsv.convertTo(hsv_8u, CV_8U, 255);138139// convert hsv to bgr140cv::cvtColor(hsv_8u, bgr, COLOR_HSV2BGR);141142// update previous_frame value143previous_frame = current_frame;144145// end post pipeline timer146auto end_post_time = high_resolution_clock::now();147148// add elapsed iteration time149timers["post-process"].push_back(duration_cast<milliseconds>(end_post_time - start_post_time).count() / 1000.0);150151// end full pipeline timer152auto end_full_time = high_resolution_clock::now();153154// add elapsed iteration time155timers["full pipeline"].push_back(duration_cast<milliseconds>(end_full_time - start_full_time).count() / 1000.0);156157// visualization158imshow("original", frame);159imshow("result", bgr);160int keyboard = waitKey(1);161if (keyboard == 27)162break;163}164}165else166{167// resize frame168cv::resize(frame, frame, Size(960, 540), 0, 0, INTER_LINEAR);169170// convert to gray171cv::cvtColor(frame, previous_frame, COLOR_BGR2GRAY);172173// upload pre-processed frame to GPU174cv::cuda::GpuMat gpu_previous;175gpu_previous.upload(previous_frame);176177// declare cpu outputs for optical flow178cv::Mat hsv[3], angle, bgr;179180// declare gpu outputs for optical flow181cv::cuda::GpuMat gpu_magnitude, gpu_normalized_magnitude, gpu_angle;182cv::cuda::GpuMat gpu_hsv[3], gpu_merged_hsv, gpu_hsv_8u, gpu_bgr;183184// set saturation to 1185hsv[1] = cv::Mat::ones(frame.size(), CV_32F);186gpu_hsv[1].upload(hsv[1]);187188while (true)189{190// start full pipeline timer191auto start_full_time = high_resolution_clock::now();192193// start reading timer194auto start_read_time = high_resolution_clock::now();195196// capture frame-by-frame197capture >> frame;198199if (frame.empty())200break;201202// upload frame to GPU203cv::cuda::GpuMat gpu_frame;204gpu_frame.upload(frame);205206// end reading timer207auto end_read_time = high_resolution_clock::now();208209// add elapsed iteration time210timers["reading"].push_back(duration_cast<milliseconds>(end_read_time - start_read_time).count() / 1000.0);211212// start pre-process timer213auto start_pre_time = high_resolution_clock::now();214215// resize frame216cv::cuda::resize(gpu_frame, gpu_frame, Size(960, 540), 0, 0, INTER_LINEAR);217218// convert to gray219cv::cuda::GpuMat gpu_current;220cv::cuda::cvtColor(gpu_frame, gpu_current, COLOR_BGR2GRAY);221222// end pre-process timer223auto end_pre_time = high_resolution_clock::now();224225// add elapsed iteration time226timers["pre-process"].push_back(duration_cast<milliseconds>(end_pre_time - start_pre_time).count() / 1000.0);227228// start optical flow timer229auto start_of_time = high_resolution_clock::now();230231// create optical flow instance232Ptr<cuda::FarnebackOpticalFlow> ptr_calc = cuda::FarnebackOpticalFlow::create(5, 0.5, false, 15, 3, 5, 1.2, 0);233// calculate optical flow234cv::cuda::GpuMat gpu_flow;235ptr_calc->calc(gpu_previous, gpu_current, gpu_flow);236237// end optical flow timer238auto end_of_time = high_resolution_clock::now();239240// add elapsed iteration time241timers["optical flow"].push_back(duration_cast<milliseconds>(end_of_time - start_of_time).count() / 1000.0);242243// start post-process timer244auto start_post_time = high_resolution_clock::now();245246// split the output flow into 2 vectors247cv::cuda::GpuMat gpu_flow_xy[2];248cv::cuda::split(gpu_flow, gpu_flow_xy);249250// convert from cartesian to polar coordinates251cv::cuda::cartToPolar(gpu_flow_xy[0], gpu_flow_xy[1], gpu_magnitude, gpu_angle, true);252253// normalize magnitude from 0 to 1254cv::cuda::normalize(gpu_magnitude, gpu_normalized_magnitude, 0.0, 1.0, NORM_MINMAX, -1);255256// get angle of optical flow257gpu_angle.download(angle);258angle *= ((1 / 360.0) * (180 / 255.0));259260// build hsv image261gpu_hsv[0].upload(angle);262gpu_hsv[2] = gpu_normalized_magnitude;263cv::cuda::merge(gpu_hsv, 3, gpu_merged_hsv);264265// multiply each pixel value to 255266gpu_merged_hsv.cv::cuda::GpuMat::convertTo(gpu_hsv_8u, CV_8U, 255.0);267268// convert hsv to bgr269cv::cuda::cvtColor(gpu_hsv_8u, gpu_bgr, COLOR_HSV2BGR);270271// send original frame from GPU back to CPU272gpu_frame.download(frame);273274// send result from GPU back to CPU275gpu_bgr.download(bgr);276277// update previous_frame value278gpu_previous = gpu_current;279280// end post pipeline timer281auto end_post_time = high_resolution_clock::now();282283// add elapsed iteration time284timers["post-process"].push_back(duration_cast<milliseconds>(end_post_time - start_post_time).count() / 1000.0);285286// end full pipeline timer287auto end_full_time = high_resolution_clock::now();288289// add elapsed iteration time290timers["full pipeline"].push_back(duration_cast<milliseconds>(end_full_time - start_full_time).count() / 1000.0);291292// visualization293imshow("original", frame);294imshow("result", bgr);295int keyboard = waitKey(1);296if (keyboard == 27)297break;298}299300}301302// release the capture303capture.release();304305// destroy all windows306destroyAllWindows();307308// print results309cout << "Number of frames: " << num_frames << std::endl;310311// elapsed time at each stage312cout << "Elapsed time" << std::endl;313for (auto const& timer : timers)314{315cout << "- " << timer.first << " : " << accumulate(timer.second.begin(), timer.second.end(), 0.0) << " seconds"<< endl;316}317318// calculate frames per second319cout << "Default video FPS : " << fps << endl;320float optical_flow_fps = (num_frames - 1) / accumulate(timers["optical flow"].begin(), timers["optical flow"].end(), 0.0);321cout << "Optical flow FPS : " << optical_flow_fps << endl;322323float full_pipeline_fps = (num_frames - 1) / accumulate(timers["full pipeline"].begin(), timers["full pipeline"].end(), 0.0);324cout << "Full pipeline FPS : " << full_pipeline_fps << endl;325}326327328int main( int argc, const char** argv )329{330string videoFileName;331string device;332333// parse arguments from command line334if (argc == 3)335{336videoFileName = argv[1];337device = argv[2];338}339else if (argc == 2)340{341videoFileName = argv[1];342device = "cpu";343}344else345{346cout << "Please input video filename." << endl;347cout << "Usage example: ./demo.out video/boat.mp4" << endl;348cout << "If you want to use GPU device instead of CPU, add one more argument." << endl;349cout << "Usage example: ./demo.out video/boat.mp4 gpu" << endl;350return 1;351}352353// output passed arguments354cout << "Configuration" << endl;355cout << "- device : "<< device << endl;356cout << "- video file : " << videoFileName << endl;357358calculate_optical_flow(videoFileName, device);359360return 0;361}362363364365