adaptiveFR.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. /*
  2. * adaptiveFR.cpp
  3. *
  4. * Created on: Sep 15, 2016
  5. * Author: jjanai
  6. */
  7. #include "configuration.h"
  8. #include <fstream>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <string>
  12. #include <cmath>
  13. #include <omp.h>
  14. #include <unistd.h>
  15. #include <stdio.h>
  16. #include <boost/filesystem.hpp>
  17. #include <boost/regex.hpp>
  18. #include <opencv2/core.hpp>
  19. #include <opencv2/highgui.hpp>
  20. #include <opencv2/imgproc.hpp>
  21. #include "epic_flow_extended/image.h"
  22. #include "epic_flow_extended/io.h"
  23. #include "epic_flow_extended/epic.h"
  24. #include "epic_flow_extended/variational.h"
  25. #include "utils/utils.h"
  26. #include "utils/parameter_list.h"
  27. // include Hamilton-Adams demosaicing
  28. extern "C"
  29. {
  30. #ifdef DMGUNTURK
  31. #include DMGUNTURK_PATH(/dmha.h)
  32. #endif
  33. }
  34. // include flowcode (middlebury devkit)
  35. #include MIDDLEBURY_PATH(/colorcode.h)
  36. #include MIDDLEBURY_PATH(/flowIO.h)
  37. // include TRWS
  38. #include TRWS_PATH(/MRFEnergy.h)
  39. void HADemosaicing(float *Output, const float *Input, int Width, int Height, int RedX, int RedY) {
  40. #ifdef DMGUNTURK
  41. HamiltonAdamsDemosaic(Output, Input, Width, Height, RedX, RedY); // Hamilton-Adams implemented by Pascal Getreuer
  42. #endif
  43. }
  44. using namespace std;
  45. using namespace cv;
  46. namespace fs = boost::filesystem;
  47. enum COMPARISON {GROUNDTRUTH = 0, WARPING = 1};
  48. /* show usage information */
  49. void usage(){
  50. printf("usage:\n");
  51. printf(" ./adaptiveFR -path [path] -folder [specific folder | file with list] -format [file format] -scale [default 0.25] -skip [target frame (2)] -sample [number of estimation (10)] -step [frames between estimation (10)] -start [first frame (0)] -quantil -raw -overwrite -sintel -subframes -threads\n");
  52. printf("\n");
  53. }
  54. void setDefault(ParameterList& params) {
  55. // general
  56. params.insert("verbose", "0", true);
  57. params.insert("threads", "1", true);
  58. params.insert("scale", "1.0f", true);
  59. params.insert("slow_flow_S", "2", true);
  60. // energy function
  61. params.insert("slow_flow_alpha", "4.0f");
  62. params.insert("slow_flow_gamma", "6.0f", true);
  63. params.insert("slow_flow_delta", "1.0f", true);
  64. // image pyramid
  65. params.insert("slow_flow_layers", "1", true);
  66. params.insert("slow_flow_p_scale", "0.9f", true);
  67. // optimization
  68. params.insert("slow_flow_niter_alter", "10", true);
  69. params.insert("slow_flow_niter_outer", "10", true);
  70. params.insert("slow_flow_thres_outer", "1e-5", true);
  71. params.insert("slow_flow_niter_inner", "1", true);
  72. params.insert("slow_flow_thres_inner", "1e-5", true);
  73. params.insert("slow_flow_niter_solver", "30", true);
  74. params.insert("slow_flow_sor_omega", "1.9f", true);
  75. // occlusion reasoning
  76. params.insert("slow_flow_occlusion_reasoning", "1", true);
  77. params.insert("slow_flow_occlusion_penalty", "0.1", true);
  78. params.insert("slow_flow_occlusion_alpha", "0.1", true);
  79. params.insert("slow_flow_output_occlusions", "1", true);
  80. // regularization
  81. params.insert("slow_flow_robust_color", "1", true);
  82. params.insert("slow_flow_robust_color_eps", "0.001", true);
  83. params.insert("slow_flow_robust_color_truncation", "0.5", true);
  84. params.insert("slow_flow_robust_reg", "1", true);
  85. params.insert("slow_flow_robust_reg_eps", "0.001", true);
  86. params.insert("slow_flow_robust_reg_truncation", "0.5", true);
  87. }
  88. inline bool insideImg(double x, double y, int width, int height) {
  89. return (y >= 0 && y < height && x >= 0 && x < width);
  90. }
  91. int main(int argc, char **argv){
  92. if( argc < 2){
  93. if(argc>1) fprintf(stderr,"Error, not enough arguments\n");
  94. usage();
  95. exit(1);
  96. }
  97. // read optional arguments
  98. string format = "%07i.tif";
  99. uint32_t start = 0;
  100. #define isarg(key) !strcmp(a,key)
  101. string path = "";
  102. string folder = "";
  103. string append = "";
  104. bool overwrite = false;
  105. int samples = 40; // number of optical flow estimates
  106. int sample_step = 10; // step size
  107. uint32_t all_frames = 2; // frames for optical flow estimation (classical two frame formulation)
  108. int skip = 2;
  109. float q = 0.90f; // quantil
  110. double scale = 0.25;
  111. double dm_scale = 1.0f;
  112. bool sintel = false; // specific file names (we would like to be able to distinguish frame number from 24 fps and 1008 fps)
  113. bool subframes = false; // are subframes specified
  114. bool raw = false;
  115. int threads = 1;
  116. int current_arg = 0;
  117. while(current_arg < argc ){
  118. const char* a = argv[current_arg++];
  119. if(a[0] != '-') {
  120. continue;
  121. }
  122. if( isarg("-h") || isarg("-help") )
  123. usage();
  124. else if( isarg("-path") )
  125. path = string(argv[current_arg++]);
  126. else if( isarg("-folder") )
  127. folder = string(argv[current_arg++]);
  128. else if( isarg("-threads") )
  129. threads = atoi(argv[current_arg++]);
  130. else if( isarg("-append") )
  131. append = string(argv[current_arg++]);
  132. else if( isarg("-scale") )
  133. scale = atof(argv[current_arg++]);
  134. else if( isarg("-skip") )
  135. skip = max(1, atoi(argv[current_arg++]));
  136. else if( isarg("-samples") )
  137. samples = atoi(argv[current_arg++]);
  138. else if( isarg("-step") )
  139. sample_step = atoi(argv[current_arg++]);
  140. else if( isarg("-start") )
  141. start = atoi(argv[current_arg++]);
  142. else if( isarg("-quantil") )
  143. q = atof(argv[current_arg++]);
  144. else if( isarg("-overwrite") )
  145. overwrite = true;
  146. else if( isarg("-sintel") )
  147. sintel = true;
  148. else if( isarg("-raw") )
  149. raw = true;
  150. else if( isarg("-subframes") )
  151. subframes = true;
  152. else if( isarg("-format") )
  153. format = string(argv[current_arg++]);
  154. else {
  155. fprintf(stderr, "unknown argument %s", a);
  156. usage();
  157. exit(1);
  158. }
  159. }
  160. vector<string> folders;
  161. if(folder.empty()) {
  162. fs::path apk_path(path + "/");
  163. boost::filesystem::directory_iterator dir(path + "/"), it, end;
  164. for(it = dir; it != end; it++)
  165. {
  166. const boost::filesystem::path& p = *it;
  167. folder = p.filename().string();
  168. if(boost::filesystem::is_directory(p) &&
  169. folder.compare("$RECYCLE.BIN") != 0 && folder.compare("preview") != 0 && folder.compare("Rallye") != 0 && folder.compare("System Volume Information") != 0 &&
  170. folder.compare("WDApps") != 0 && folder.c_str()[0] != '.') {
  171. folders.push_back(p.filename().string());
  172. }
  173. }
  174. } else {
  175. if(boost::filesystem::is_directory(path + "/" + folder + "/")) {
  176. folders.push_back(folder);
  177. } else {
  178. ifstream folder_input;
  179. string ifilename(folder);
  180. if (std::strcmp(ifilename.c_str(), "-") != 0) {
  181. folder_input.open(ifilename.c_str());
  182. if (!folder_input.is_open()) {
  183. std::cerr << ifilename << ": " << "no such file or directory" << "\n";
  184. return EXIT_FAILURE;
  185. }
  186. string line;
  187. // parse header
  188. while(getline(folder_input, line)) {
  189. if(boost::filesystem::is_directory(path + "/" + line + "/")) {
  190. folders.push_back(line);
  191. } else
  192. std::cerr << path + "/" + line + "/" << ": " << "no such directory" << "\n";
  193. }
  194. }
  195. folder_input.close();
  196. }
  197. }
  198. sort(folders.begin(), folders.end());
  199. if(sintel && !subframes)
  200. start = start * 1000;
  201. stringstream overview;
  202. #pragma omp parallel for num_threads(threads) schedule(static,1)
  203. for(uint32_t fidx = 0; fidx < folders.size(); fidx++) {
  204. string thread_folder = folders[fidx];
  205. ParameterList params;
  206. setDefault(params); // set default parameters
  207. // add input path and output path
  208. string sequence_path = "", output = "";
  209. params.file = path + "/" + thread_folder + "/" + format;
  210. vector<int> seq_compression_params;
  211. seq_compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
  212. seq_compression_params.push_back(0);
  213. seq_compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
  214. seq_compression_params.push_back(100);
  215. params.Jets = 1;
  216. int start_format = (params.file.find_last_of('/') + 1);
  217. int end_format = params.file.length() - start_format;
  218. sequence_path = params.file.substr(0,start_format);
  219. string format = params.file.substr(start_format, end_format);
  220. if(sequence_path[sequence_path.length() - 1] != '/') sequence_path = sequence_path + "/";
  221. params.file = sequence_path;
  222. params.insert("format", format, true);
  223. // set output folder!
  224. output = sequence_path + "/adaptiveFR/";
  225. if(sequence_path.empty() || output.empty())
  226. continue;
  227. int len_format = format.find_last_of('.');
  228. string format_flow = format.substr(0,len_format);
  229. params.sequence_start = start;
  230. for(uint32_t i = 0; i < params.sequence_start_list.size(); i++)
  231. params.sequence_start_list[i] = start;
  232. if(output[output.length() - 1] != '/') output = output + "/";
  233. // set standard stinel params for epic flow
  234. epic_params_t epic_params;
  235. epic_params_default(&epic_params);
  236. variational_params_t flow_params;
  237. variational_params_default(&flow_params);
  238. epic_params.pref_nn= 25;
  239. epic_params.nn= 160;
  240. epic_params.coef_kernel = 1.1f;
  241. flow_params.niter_outer = 5;
  242. flow_params.alpha = 1.0f;
  243. flow_params.gamma = 0.72f;
  244. flow_params.delta = 0.0f;
  245. flow_params.sigma = 1.1f;
  246. // create results folder
  247. boost::filesystem::create_directories(output);
  248. boost::filesystem::create_directories(output+"tmp/"); // ParameterList result folder
  249. boost::filesystem::create_directories(output+"sequence/"); // ParameterList result folder
  250. image_t **wx = new image_t*[samples],
  251. **wy = new image_t*[samples];
  252. // TODO: TAKE SAMPLES FROM DIFFERENT STEPS
  253. for(int it = 0; it < samples; it++) {
  254. if(it > 0) {
  255. params.sequence_start += params.Jets * sample_step;
  256. for(uint32_t i = 0; i < params.sequence_start_list.size(); i++) {
  257. params.sequence_start_list[i] = params.sequence_start; //
  258. }
  259. }
  260. wx[it] = NULL;
  261. wy[it] = NULL;
  262. /*
  263. * ################### read in image sequence ###################
  264. */
  265. vector<int> red_loc = params.splitParameter<int>("raw_red_loc","1,0");
  266. char** img_files = new char*[all_frames];
  267. color_image_t **seq = new color_image_t*[all_frames];
  268. bool success = true;
  269. for(uint32_t f = 0; f < all_frames; f++) {
  270. char img_file[200];
  271. if(!sintel) {
  272. sprintf(img_file, (sequence_path+format).c_str(), params.sequence_start + f * skip);
  273. } else {
  274. int sintel_frame = params.sequence_start / 1000;
  275. int hfr_frame = f * skip + (params.sequence_start % 1000);
  276. while(hfr_frame < 0) {
  277. sintel_frame--;
  278. hfr_frame = 42 + hfr_frame;
  279. }
  280. while(hfr_frame > 41) {
  281. sintel_frame++;
  282. hfr_frame = hfr_frame - 42;
  283. }
  284. sprintf(img_file, (sequence_path+format).c_str(), sintel_frame, hfr_frame);
  285. }
  286. if(access(img_file, F_OK) == -1) {
  287. cerr << "Could not find " << img_file << "!" << endl;
  288. success = false;
  289. break;
  290. }
  291. cout << "Reading " << img_file << "..." << endl;
  292. Mat img = imread(string(img_file), CV_LOAD_IMAGE_UNCHANGED); // load images
  293. float norm = 1;
  294. if(img.type() == 2 || params.parameter<bool>("16bit", "0")) {
  295. norm = 1.0f/255; // for 16 bit images
  296. params.insert("16bit", "1", true);
  297. }
  298. // convert to floating point
  299. img.convertTo(img, CV_32FC(img.channels()));
  300. /*
  301. * DEMOSAICING
  302. */
  303. if(raw) {
  304. Mat tmp = img.clone();
  305. color_image_t* tmp_in = color_image_new(img.cols, img.rows);
  306. color_image_t* tmp_out = color_image_new(img.cols, img.rows);
  307. switch(params.parameter<int>("raw_demosaicing", "0")) {
  308. case 0: // use bilinear demosaicing
  309. img = Mat::zeros(tmp.rows, tmp.cols, CV_32FC3);
  310. bayer2rgbGR(tmp, img, red_loc[0], red_loc[1]); // red green
  311. break;
  312. case 1: // use hamilton adams demosaicing
  313. mat2colorImg<float>(img, tmp_in);
  314. HADemosaicing(tmp_out->c1, tmp_in->c1, tmp_in->width, tmp_in->height, red_loc[0], red_loc[1]); // Hamilton-Adams implemented by Pascal Getreuer
  315. img = Mat::zeros(img.rows, img.cols, CV_32FC3);
  316. colorImg2colorMat<Vec3f>(tmp_out, img);
  317. break;
  318. case 2: // use opencv demosaicing
  319. tmp.convertTo(tmp, CV_8UC1);
  320. img = Mat::zeros(tmp.rows, tmp.cols, CV_8UC3);
  321. int code = CV_BayerBG2RGB;
  322. if(red_loc[1] == 0) // y
  323. if(red_loc[0] == 0) // x
  324. code = CV_BayerBG2RGB;
  325. else
  326. code = CV_BayerGB2RGB;
  327. else
  328. if(red_loc[0] == 0) // x
  329. code = CV_BayerGR2RGB;
  330. else
  331. code = CV_BayerRG2RGB;
  332. cv::cvtColor(tmp, img, code); // components from second row, second column !!!!!!!!!!!!!!!!!
  333. img.convertTo(img, CV_32FC(img.channels()));
  334. break;
  335. }
  336. color_image_delete(tmp_in);
  337. color_image_delete(tmp_out);
  338. } else {
  339. // covert to RGB
  340. cv::cvtColor(img, img, CV_BGR2RGB);
  341. }
  342. // use only a part of the images
  343. if(params.extent.x > 0 || params.extent.y > 0) {
  344. img = img.rowRange(Range(params.center.y - params.extent.y/2,params.center.y + params.extent.y/2));
  345. img = img.colRange(Range(params.center.x - params.extent.x/2,params.center.x + params.extent.x/2));
  346. }
  347. // rescale image with gaussian blur to avoid anti-aliasing
  348. if(scale != 1) {
  349. GaussianBlur(img, img,Size(),1/sqrt(2*scale),1/sqrt(2*scale),BORDER_REPLICATE);
  350. resize(img, img, Size(0,0), scale, scale, INTER_LINEAR);
  351. }
  352. // print to file
  353. img_files[f] = new char[500];
  354. sprintf(img_files[f], (output+"sequence/frame_%i.png").c_str(), params.sequence_start + f * skip);
  355. Mat output_img;
  356. if(params.verbosity(WRITE_FILES)) {
  357. if(params.parameter<bool>("16bit", "0")) {
  358. img.convertTo(output_img, CV_16UC(img.channels()));
  359. } else {
  360. img.convertTo(output_img, CV_8UC(img.channels()), norm);
  361. }
  362. cv::cvtColor(output_img, output_img, CV_RGB2BGR); // OpenCV uses BGR
  363. imwrite(img_files[f], output_img, seq_compression_params);
  364. }
  365. // use 8 bit for further processing
  366. img.convertTo(img, CV_8UC(img.channels()), norm);
  367. int width = img.cols;
  368. int height = img.rows;
  369. // copy data
  370. seq[f] = color_image_new(width, height);
  371. if(img.channels() == 1) {
  372. mat2colorImg<uchar>(img, seq[f]);
  373. } else
  374. colorMat2colorImg<Vec3b>(img, seq[f]);
  375. // resize and copy data for deep match
  376. GaussianBlur(img, img,Size(),1/sqrt(2*dm_scale),1/sqrt(2*dm_scale),BORDER_REPLICATE);
  377. resize(img, img, Size(0,0), dm_scale, dm_scale, INTER_LINEAR);
  378. sprintf(img_files[f], (output+"sequence/frame_epic_%i.png").c_str(), params.sequence_start + f * skip);
  379. output_img = Mat(img.rows, img.cols, CV_8UC(img.channels()));
  380. cv::cvtColor(img, output_img, CV_RGB2BGR); // OpenCV uses BGR
  381. imwrite(img_files[f], output_img, seq_compression_params);
  382. }
  383. if(!success)
  384. continue;
  385. /*
  386. * write infos to file
  387. */
  388. params.print();
  389. ofstream infos;
  390. infos.open((output + "config.cfg").c_str());
  391. infos << "# Epic Flow estimation\n";
  392. infos << params;
  393. infos.close();
  394. // write stats
  395. stringstream results;
  396. results << "frame\ttime\n\n";
  397. int avg_time = 0;
  398. int counter = 0;
  399. for(uint32_t j = 0; j < params.Jets; j++) {
  400. ParameterList thread_params(params);
  401. int f = j;
  402. color_image_t **im = &seq[f];
  403. // prepare variables
  404. wx[it] = image_new(im[0]->width*dm_scale, im[0]->height*dm_scale);
  405. wy[it] = image_new(im[0]->width*dm_scale, im[0]->height*dm_scale);
  406. time_t pp_start, pp_stop;
  407. int t_preprocessing = 0;
  408. char edges_f[1000], edges_cmd[1000], match_f[1000], match_cmd[1000], epic_cmd[1000], epic_f[1000];
  409. char forward_flow_file[200];
  410. if(!sintel)
  411. sprintf(forward_flow_file, (output + format_flow + ".flo").c_str(), params.sequence_start + f * skip);
  412. else
  413. sprintf(forward_flow_file, (output + format_flow + ".flo").c_str(), params.sequence_start + f * skip, 0);
  414. time_t t_start, t_stop;
  415. // skip finished frames
  416. if(overwrite || access( forward_flow_file, F_OK ) == -1) {
  417. /*
  418. * ################### extract edges and get matches ###################
  419. */
  420. cout << "Computing edges ..." << endl;
  421. sprintf(edges_f, (output+"tmp/edges_%i.dat").c_str(), params.sequence_start + f);
  422. if(overwrite || access( edges_f, F_OK ) == -1) {
  423. sprintf(edges_cmd, "matlab -nodesktop -nojvm -r \"addpath(\'%s/matlab/\'); detect_edges(\'%s\',\'%s\'); exit\"", SOURCE_PATH.c_str(), img_files[j], edges_f);
  424. time(&pp_start);
  425. system(edges_cmd);
  426. // Call the function
  427. time(&pp_stop);
  428. t_preprocessing += (int) difftime(pp_stop, pp_start);
  429. }
  430. // matches to target frame
  431. cout << "Computing matches between " << params.sequence_start + f * skip << " and " << params.sequence_start + (f + 1) * skip<< " ..." << endl;
  432. sprintf(match_f, (output+"tmp/matches_%i_%i.dat").c_str(), params.sequence_start + f * skip, params.sequence_start + (f + 1) * skip);
  433. cout << img_files[j] << " and " << img_files[j + 1] << endl;
  434. if(overwrite || access( match_f, F_OK ) == -1) {
  435. sprintf(match_cmd, "%s/deepmatching %s %s -png_settings -out %s", DEEPMATCHING_PATH.c_str(), img_files[j], img_files[j + 1], match_f);
  436. time(&pp_start);
  437. system(match_cmd);
  438. time(&pp_stop);
  439. t_preprocessing += (int) difftime(pp_stop, pp_start);
  440. }
  441. /*
  442. * ############ forward flow ##################
  443. */
  444. cout << "Forward flow estimation ..." << endl;
  445. // matches to target frame
  446. float_image forward_edges = read_edges(edges_f, im[0]->width, im[0]->height);
  447. time(&pp_start);
  448. float_image forward_matches = read_matches(match_f);
  449. time(&pp_stop);
  450. t_preprocessing += (int) difftime(pp_stop, pp_start);
  451. color_image_t *imlab = rgb_to_lab(im[0]);
  452. // initilize with deep matches
  453. cout << "Epic interpolation of forward flow ..." << endl;
  454. time(&pp_start);
  455. epic(wx[it], wy[it], imlab, &forward_matches, &forward_edges, &epic_params, 1);
  456. time(&pp_stop);
  457. t_preprocessing += (int) difftime(pp_stop, pp_start);
  458. // energy minimization
  459. time(&t_start);
  460. variational(wx[it], wy[it], im[0], im[1], &flow_params);
  461. system(epic_cmd);
  462. time(&t_stop);
  463. t_preprocessing += difftime(t_stop, t_start);
  464. color_image_delete(imlab);
  465. free(forward_matches.pixels);
  466. free(forward_edges.pixels);
  467. // write output file
  468. writeFlowFile(forward_flow_file, wx[it], wy[it]);
  469. cout << "Forward flow from frame " << params.sequence_start + f * skip << " to " << params.sequence_start + (f + 1) * skip << " finished! (Computation took " << t_preprocessing<< " s)" << endl;
  470. } else {
  471. image_t **tmp;
  472. tmp = readFlowFile(forward_flow_file);
  473. wx[it] = tmp[0];
  474. wy[it] = tmp[1];
  475. cout << "Forward flow from frame " << params.sequence_start + f * skip << " to " << params.sequence_start + (f + 1) * skip << " already exist!" << endl;
  476. }
  477. Mat floImg = flowColorImg(wx[it], wy[it], params.verbosity(VER_CMD));
  478. // write flow image to file
  479. if(!floImg.data) { // Check for invalid input
  480. cout << "No forward flow for frame " << params.sequence_start + f * skip << std::endl ;
  481. } else {
  482. if(!output.empty()) {
  483. stringstream flowF;
  484. flowF << output << "tmp/frame_" << params.sequence_start + f * skip << ".png";
  485. imwrite((flowF.str()), floImg);
  486. }
  487. }
  488. // normalize flow to recorded resolution and frame rate
  489. image_mul_scalar(wx[it], 1.0f / (scale * skip)); // scale flow
  490. image_mul_scalar(wy[it], 1.0f / (scale * skip)); // scale flow
  491. }
  492. if(counter > 0) avg_time /= counter;
  493. cout << "Average computation was " << avg_time << " s" << endl;
  494. results << "\n\navg\t" << avg_time << "s\n";
  495. // write experiment results to file
  496. if(!params.output.empty() && counter > 0) {
  497. ofstream infos;
  498. infos.open((output + "results.info").c_str());
  499. infos << "Epic Flow Multi Frame\n";
  500. infos << "\n";
  501. infos << results.str();
  502. infos.close();
  503. }
  504. // clean up
  505. for(uint32_t f = 0; f < all_frames; f++) {
  506. color_image_delete(seq[f]);
  507. delete[] img_files[f];
  508. }
  509. delete[] img_files;
  510. delete[] seq;
  511. }
  512. /*
  513. * ########################################### compute quantil ##############################################
  514. */
  515. int used = 0;
  516. vector<double> magnitudes;
  517. magnitudes.reserve(samples * wx[0]->height * wx[0]->width);
  518. for(int it = 0; it < samples; it++) {
  519. if(wx[it] == NULL || wy[it] == NULL) continue;
  520. for (int y = 0; y < wx[it]->height; y++) {
  521. for (int x = 0; x < wx[it]->width; x++) {
  522. magnitudes.push_back(sqrt(wx[it]->data[y * wx[it]->stride + x] * wx[it]->data[y * wx[it]->stride + x] + wy[it]->data[y * wy[it]->stride + x] * wy[it]->data[y * wy[it]->stride + x]));
  523. }
  524. }
  525. used++;
  526. }
  527. sort(magnitudes.begin(), magnitudes.end());
  528. float np = q * magnitudes.size() - 1;
  529. double quantil = 0;
  530. if((np < magnitudes.size() - 1) && fmod(np,2.0f) == 0) {
  531. quantil = 0.5f * (magnitudes[(int) np] + magnitudes[(int) np + 1]);
  532. } else {
  533. quantil = (magnitudes[(int) ceil(np)]);
  534. }
  535. double maxq = magnitudes.back();
  536. cout << "Quantil: " << quantil << endl;
  537. // write experiment results to file
  538. ofstream infos;
  539. infos.open((output + "results.info").c_str());
  540. infos << "Adaptive Frame rate\n";
  541. infos << "\n";
  542. infos << "samples " << used << "\n";
  543. infos << "sample_step " << sample_step << "\n";
  544. infos << "skip " << skip << "\n";
  545. infos << q << " quantil " << quantil << "\n";
  546. infos << "max " << maxq << "\n";
  547. infos.close();
  548. #pragma omp critical (overview)
  549. {
  550. overview << thread_folder << "\t" << q << " quantil\t" << quantil << "\n";
  551. }
  552. string fname = sequence_path + "quantil.dat";
  553. if(!append.empty())
  554. infos.open(append.c_str(), std::ofstream::out | std::ofstream::app);
  555. else
  556. infos.open(fname.c_str());
  557. infos << quantil << "\n";
  558. infos << maxq << "\n";
  559. infos.close();
  560. for(int it = 0; it < samples; it++) {
  561. image_delete(wx[it]);
  562. image_delete(wy[it]);
  563. }
  564. delete[] wx;
  565. delete[] wy;
  566. }
  567. ofstream infos;
  568. infos.open((path + "results.info").c_str());
  569. infos << "Adaptive Frame rate\n";
  570. infos << "\n";
  571. infos << "samples " << samples << "\n";
  572. infos << "sample_step " << sample_step << "\n";
  573. infos << "skip " << skip << "\n\n";
  574. infos << overview.str();
  575. infos.close();
  576. cout << "Done!" << endl;
  577. return 0;
  578. }