pcaflow_demo.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #include "opencv2/core/ocl.hpp"
  2. #include "opencv2/highgui.hpp"
  3. #include "opencv2/imgcodecs.hpp"
  4. #include "opencv2/optflow.hpp"
  5. #include <fstream>
  6. #include <iostream>
  7. #include <stdio.h>
  8. using namespace cv;
  9. using optflow::OpticalFlowPCAFlow;
  10. using optflow::PCAPrior;
  11. const String keys = "{help h ? | | print this message}"
  12. "{@image1 |<none>| image1}"
  13. "{@image2 |<none>| image2}"
  14. "{@groundtruth |<none>| path to the .flo file}"
  15. "{@prior |<none>| path to a prior file for PCAFlow}"
  16. "{@output |<none>| output image path}"
  17. "{g gpu | | use OpenCL}";
  18. static double normL2( const Point2f &v ) { return sqrt( v.x * v.x + v.y * v.y ); }
  19. static bool fileProbe( const char *name ) { return std::ifstream( name ).good(); }
  20. static Vec3d getFlowColor( const Point2f &f, const bool logScale = true, const double scaleDown = 5 )
  21. {
  22. if ( f.x == 0 && f.y == 0 )
  23. return Vec3d( 0, 0, 1 );
  24. double radius = normL2( f );
  25. if ( logScale )
  26. radius = log( radius + 1 );
  27. radius /= scaleDown;
  28. radius = std::min( 1.0, radius );
  29. double angle = ( atan2( -f.y, -f.x ) + CV_PI ) * 180 / CV_PI;
  30. return Vec3d( angle, radius, 1 );
  31. }
  32. static void displayFlow( InputArray _flow, OutputArray _img )
  33. {
  34. const Size sz = _flow.size();
  35. Mat flow = _flow.getMat();
  36. _img.create( sz, CV_32FC3 );
  37. Mat img = _img.getMat();
  38. for ( int i = 0; i < sz.height; ++i )
  39. for ( int j = 0; j < sz.width; ++j )
  40. img.at< Vec3f >( i, j ) = getFlowColor( flow.at< Point2f >( i, j ) );
  41. cvtColor( img, img, COLOR_HSV2BGR );
  42. }
  43. static bool isFlowCorrect( const Point2f &u )
  44. {
  45. return !cvIsNaN( u.x ) && !cvIsNaN( u.y ) && ( fabs( u.x ) < 1e9 ) && ( fabs( u.y ) < 1e9 );
  46. }
  47. static double calcEPE( const Mat &f1, const Mat &f2 )
  48. {
  49. double sum = 0;
  50. Size sz = f1.size();
  51. size_t cnt = 0;
  52. for ( int i = 0; i < sz.height; ++i )
  53. for ( int j = 0; j < sz.width; ++j )
  54. if ( isFlowCorrect( f1.at< Point2f >( i, j ) ) && isFlowCorrect( f2.at< Point2f >( i, j ) ) )
  55. {
  56. sum += normL2( f1.at< Point2f >( i, j ) - f2.at< Point2f >( i, j ) );
  57. ++cnt;
  58. }
  59. return sum / cnt;
  60. }
  61. static void displayResult( Mat &i1, Mat &i2, Mat &gt, Ptr< DenseOpticalFlow > &algo, OutputArray _img, const char *descr,
  62. const bool useGpu = false )
  63. {
  64. Mat flow( i1.size[0], i1.size[1], CV_32FC2 );
  65. TickMeter meter;
  66. meter.start();
  67. if ( useGpu )
  68. algo->calc( i1, i2, flow.getUMat( ACCESS_RW ) );
  69. else
  70. algo->calc( i1, i2, flow );
  71. meter.stop();
  72. displayFlow( flow, _img );
  73. Mat img = _img.getMat();
  74. putText( img, descr, Point2i( 24, 40 ), FONT_HERSHEY_DUPLEX, 1, Vec3b( 1, 0, 0 ), 2, LINE_AA );
  75. char buf[256];
  76. sprintf( buf, "Average EPE: %.2f", calcEPE( flow, gt ) );
  77. putText( img, buf, Point2i( 24, 80 ), FONT_HERSHEY_DUPLEX, 1, Vec3b( 1, 0, 0 ), 2, LINE_AA );
  78. sprintf( buf, "Time: %.2fs", meter.getTimeSec() );
  79. putText( img, buf, Point2i( 24, 120 ), FONT_HERSHEY_DUPLEX, 1, Vec3b( 1, 0, 0 ), 2, LINE_AA );
  80. }
  81. static void displayGT( InputArray _flow, OutputArray _img, const char *descr )
  82. {
  83. displayFlow( _flow, _img );
  84. Mat img = _img.getMat();
  85. putText( img, descr, Point2i( 24, 40 ), FONT_HERSHEY_DUPLEX, 1, Vec3b( 1, 0, 0 ), 2, LINE_AA );
  86. }
  87. int main( int argc, const char **argv )
  88. {
  89. CommandLineParser parser( argc, argv, keys );
  90. parser.about( "PCAFlow demonstration" );
  91. if ( parser.has( "help" ) )
  92. {
  93. parser.printMessage();
  94. return 0;
  95. }
  96. String img1 = parser.get< String >( 0 );
  97. String img2 = parser.get< String >( 1 );
  98. String groundtruth = parser.get< String >( 2 );
  99. String prior = parser.get< String >( 3 );
  100. String outimg = parser.get< String >( 4 );
  101. const bool useGpu = parser.has( "gpu" );
  102. if ( !parser.check() )
  103. {
  104. parser.printErrors();
  105. return 1;
  106. }
  107. if ( !fileProbe( prior.c_str() ) )
  108. {
  109. std::cerr << "Can't open the file with prior! Check the provided path: " << prior << std::endl;
  110. return 1;
  111. }
  112. cv::ocl::setUseOpenCL( useGpu );
  113. Mat i1 = imread( img1 );
  114. Mat i2 = imread( img2 );
  115. Mat gt = readOpticalFlow( groundtruth );
  116. Mat i1g, i2g;
  117. cvtColor( i1, i1g, COLOR_BGR2GRAY );
  118. cvtColor( i2, i2g, COLOR_BGR2GRAY );
  119. Mat pcaflowDisp, pcaflowpriDisp, farnebackDisp, gtDisp;
  120. {
  121. Ptr< DenseOpticalFlow > pcaflow = makePtr< OpticalFlowPCAFlow >( makePtr< PCAPrior >( prior.c_str() ) );
  122. displayResult( i1, i2, gt, pcaflow, pcaflowpriDisp, "PCAFlow with prior", useGpu );
  123. }
  124. {
  125. Ptr< DenseOpticalFlow > pcaflow = makePtr< OpticalFlowPCAFlow >();
  126. displayResult( i1, i2, gt, pcaflow, pcaflowDisp, "PCAFlow without prior", useGpu );
  127. }
  128. {
  129. Ptr< DenseOpticalFlow > farneback = optflow::createOptFlow_Farneback();
  130. displayResult( i1g, i2g, gt, farneback, farnebackDisp, "Farneback", useGpu );
  131. }
  132. displayGT( gt, gtDisp, "Ground truth" );
  133. Mat disp1, disp2;
  134. vconcat( pcaflowpriDisp, farnebackDisp, disp1 );
  135. vconcat( pcaflowDisp, gtDisp, disp2 );
  136. hconcat( disp1, disp2, disp1 );
  137. disp1 *= 255;
  138. imwrite( outimg, disp1 );
  139. return 0;
  140. }