234 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			234 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| #include <iostream>
 | |
| #include <vector>
 | |
| #include <iomanip>
 | |
| 
 | |
| #include "opencv2/core/ocl.hpp"
 | |
| #include "opencv2/core/utility.hpp"
 | |
| #include "opencv2/imgcodecs.hpp"
 | |
| #include "opencv2/videoio.hpp"
 | |
| #include "opencv2/highgui/highgui.hpp"
 | |
| #include "opencv2/video/video.hpp"
 | |
| 
 | |
| using namespace std;
 | |
| using namespace cv;
 | |
| 
 | |
| typedef unsigned char uchar;
 | |
| #define LOOP_NUM 10
 | |
| int64 work_begin = 0;
 | |
| int64 work_end = 0;
 | |
| 
 | |
| static void workBegin()
 | |
| {
 | |
|     work_begin = getTickCount();
 | |
| }
 | |
| static void workEnd()
 | |
| {
 | |
|     work_end += (getTickCount() - work_begin);
 | |
| }
 | |
| static double getTime()
 | |
| {
 | |
|     return work_end * 1000. / getTickFrequency();
 | |
| }
 | |
| 
 | |
| template <typename T> inline T clamp (T x, T a, T b)
 | |
| {
 | |
|     return ((x) > (a) ? ((x) < (b) ? (x) : (b)) : (a));
 | |
| }
 | |
| 
 | |
| template <typename T> inline T mapValue(T x, T a, T b, T c, T d)
 | |
| {
 | |
|     x = clamp(x, a, b);
 | |
|     return c + (d - c) * (x - a) / (b - a);
 | |
| }
 | |
| 
 | |
| static void getFlowField(const Mat& u, const Mat& v, Mat& flowField)
 | |
| {
 | |
|     float maxDisplacement = 1.0f;
 | |
| 
 | |
|     for (int i = 0; i < u.rows; ++i)
 | |
|     {
 | |
|         const float* ptr_u = u.ptr<float>(i);
 | |
|         const float* ptr_v = v.ptr<float>(i);
 | |
| 
 | |
|         for (int j = 0; j < u.cols; ++j)
 | |
|         {
 | |
|             float d = max(fabsf(ptr_u[j]), fabsf(ptr_v[j]));
 | |
| 
 | |
|             if (d > maxDisplacement)
 | |
|                 maxDisplacement = d;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     flowField.create(u.size(), CV_8UC4);
 | |
| 
 | |
|     for (int i = 0; i < flowField.rows; ++i)
 | |
|     {
 | |
|         const float* ptr_u = u.ptr<float>(i);
 | |
|         const float* ptr_v = v.ptr<float>(i);
 | |
| 
 | |
| 
 | |
|         Vec4b* row = flowField.ptr<Vec4b>(i);
 | |
| 
 | |
|         for (int j = 0; j < flowField.cols; ++j)
 | |
|         {
 | |
|             row[j][0] = 0;
 | |
|             row[j][1] = static_cast<unsigned char> (mapValue (-ptr_v[j], -maxDisplacement, maxDisplacement, 0.0f, 255.0f));
 | |
|             row[j][2] = static_cast<unsigned char> (mapValue ( ptr_u[j], -maxDisplacement, maxDisplacement, 0.0f, 255.0f));
 | |
|             row[j][3] = 255;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| int main(int argc, const char* argv[])
 | |
| {
 | |
|     const char* keys =
 | |
|         "{ h help     | false           | print help message }"
 | |
|         "{ l left     |                 | specify left image }"
 | |
|         "{ r right    |                 | specify right image }"
 | |
|         "{ o output   | tvl1_output.jpg | specify output save path }"
 | |
|         "{ c camera   | 0               | enable camera capturing }"
 | |
|         "{ m cpu_mode | false           | run without OpenCL }"
 | |
|         "{ v video    |                 | use video as input }";
 | |
| 
 | |
|     CommandLineParser cmd(argc, argv, keys);
 | |
| 
 | |
|     if (cmd.has("help"))
 | |
|     {
 | |
|         cout << "Usage: pyrlk_optical_flow [options]" << endl;
 | |
|         cout << "Available options:" << endl;
 | |
|         cmd.printMessage();
 | |
|         return EXIT_SUCCESS;
 | |
|     }
 | |
| 
 | |
|     string fname0 = cmd.get<string>("l");
 | |
|     string fname1 = cmd.get<string>("r");
 | |
|     string vdofile = cmd.get<string>("v");
 | |
|     string outpath = cmd.get<string>("o");
 | |
|     bool useCPU = cmd.get<bool>("s");
 | |
|     bool useCamera = cmd.get<bool>("c");
 | |
|     int inputName = cmd.get<int>("c");
 | |
| 
 | |
|     UMat frame0, frame1;
 | |
|     imread(fname0, cv::IMREAD_GRAYSCALE).copyTo(frame0);
 | |
|     imread(fname1, cv::IMREAD_GRAYSCALE).copyTo(frame1);
 | |
|     cv::Ptr<cv::DenseOpticalFlow> alg = cv::createOptFlow_DualTVL1();
 | |
| 
 | |
|     UMat flow;
 | |
|     Mat show_flow;
 | |
|     vector<UMat> flow_vec;
 | |
|     if (frame0.empty() || frame1.empty())
 | |
|         useCamera = true;
 | |
| 
 | |
|     if (useCamera)
 | |
|     {
 | |
|         VideoCapture capture;
 | |
|         UMat frame, frameCopy;
 | |
|         UMat frame0Gray, frame1Gray;
 | |
|         UMat ptr0, ptr1;
 | |
| 
 | |
|         if(vdofile.empty())
 | |
|             capture.open( inputName );
 | |
|         else
 | |
|             capture.open(vdofile.c_str());
 | |
| 
 | |
|         if(!capture.isOpened())
 | |
|         {
 | |
|             if(vdofile.empty())
 | |
|                 cout << "Capture from CAM " << inputName << " didn't work" << endl;
 | |
|             else
 | |
|                 cout << "Capture from file " << vdofile << " failed" <<endl;
 | |
|             goto nocamera;
 | |
|         }
 | |
| 
 | |
|         cout << "In capture ..." << endl;
 | |
|         for(int i = 0;; i++)
 | |
|         {
 | |
|             if( !capture.read(frame) )
 | |
|                 break;
 | |
| 
 | |
|             if (i == 0)
 | |
|             {
 | |
|                 frame.copyTo( frame0 );
 | |
|                 cvtColor(frame0, frame0Gray, COLOR_BGR2GRAY);
 | |
|             }
 | |
|             else
 | |
|             {
 | |
|                 if (i%2 == 1)
 | |
|                 {
 | |
|                     frame.copyTo(frame1);
 | |
|                     cvtColor(frame1, frame1Gray, COLOR_BGR2GRAY);
 | |
|                     ptr0 = frame0Gray;
 | |
|                     ptr1 = frame1Gray;
 | |
|                 }
 | |
|                 else
 | |
|                 {
 | |
|                     frame.copyTo(frame0);
 | |
|                     cvtColor(frame0, frame0Gray, COLOR_BGR2GRAY);
 | |
|                     ptr0 = frame1Gray;
 | |
|                     ptr1 = frame0Gray;
 | |
|                 }
 | |
| 
 | |
|                 alg->calc(ptr0, ptr1, flow);
 | |
|                 split(flow, flow_vec);
 | |
| 
 | |
|                 if (i%2 == 1)
 | |
|                     frame1.copyTo(frameCopy);
 | |
|                 else
 | |
|                     frame0.copyTo(frameCopy);
 | |
|                 getFlowField(flow_vec[0].getMat(ACCESS_READ), flow_vec[1].getMat(ACCESS_READ), show_flow);
 | |
|                 imshow("tvl1 optical flow field", show_flow);
 | |
|             }
 | |
| 
 | |
|             char key = (char)waitKey(10);
 | |
|             if (key == 27)
 | |
|                 break;
 | |
|             else if (key == 'm' || key == 'M')
 | |
|             {
 | |
|                 ocl::setUseOpenCL(!cv::ocl::useOpenCL());
 | |
|                 cout << "Switched to " << (ocl::useOpenCL() ? "OpenCL" : "CPU") << " mode\n";
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         capture.release();
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| nocamera:
 | |
|         if (cmd.has("cpu_mode"))
 | |
|         {
 | |
|             ocl::setUseOpenCL(false);
 | |
|             std::cout << "OpenCL was disabled" << std::endl;
 | |
|         }
 | |
|         for(int i = 0; i <= LOOP_NUM; i ++)
 | |
|         {
 | |
|             cout << "loop" << i << endl;
 | |
| 
 | |
|             if (i > 0) workBegin();
 | |
| 
 | |
|             alg->calc(frame0, frame1, flow);
 | |
|             split(flow, flow_vec);
 | |
| 
 | |
|             if (i > 0 && i <= LOOP_NUM)
 | |
|                 workEnd();
 | |
| 
 | |
|             if (i == LOOP_NUM)
 | |
|             {
 | |
|                 if (useCPU)
 | |
|                     cout << "average CPU time (noCamera) : ";
 | |
|                 else
 | |
|                     cout << "average GPU time (noCamera) : ";
 | |
|                 cout << getTime() / LOOP_NUM << " ms" << endl;
 | |
| 
 | |
|                 getFlowField(flow_vec[0].getMat(ACCESS_READ), flow_vec[1].getMat(ACCESS_READ), show_flow);
 | |
|                 imshow("PyrLK [Sparse]", show_flow);
 | |
|                 imwrite(outpath, show_flow);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     waitKey();
 | |
| 
 | |
|     return EXIT_SUCCESS;
 | |
| }
 | 
