Merge pull request #3038 from yury-gorbachev:core_arithm_neon
[profile/ivi/opencv.git] / samples / cpp / simpleflow_demo.cpp
1 #include <opencv2/core/utility.hpp>
2 #include "opencv2/video/tracking.hpp"
3 #include "opencv2/imgproc.hpp"
4 #include "opencv2/imgcodecs.hpp"
5 #include "opencv2/highgui.hpp"
6
7 #include <cstdio>
8 #include <iostream>
9
10 using namespace cv;
11 using namespace std;
12
13 #define APP_NAME "simpleflow_demo : "
14
15 static void help()
16 {
17   // print a welcome message, and the OpenCV version
18   printf("This is a demo of SimpleFlow optical flow algorithm,\n"
19          "Using OpenCV version %s\n\n", CV_VERSION);
20
21   printf("Usage: simpleflow_demo frame1 frame2 output_flow"
22          "\nApplication will write estimated flow "
23          "\nbetween 'frame1' and 'frame2' in binary format"
24          "\ninto file 'output_flow'"
25          "\nThen one can use code from http://vision.middlebury.edu/flow/data/"
26          "\nto convert flow in binary file to image\n");
27 }
28
29 // binary file format for flow data specified here:
30 // http://vision.middlebury.edu/flow/data/
31 static void writeOpticalFlowToFile(const Mat& flow, FILE* file) {
32   int cols = flow.cols;
33   int rows = flow.rows;
34
35   fprintf(file, "PIEH");
36
37   if (fwrite(&cols, sizeof(int), 1, file) != 1 ||
38       fwrite(&rows, sizeof(int), 1, file) != 1) {
39     printf(APP_NAME "writeOpticalFlowToFile : problem writing header\n");
40     exit(1);
41   }
42
43   for (int i= 0; i < rows; ++i) {
44     for (int j = 0; j < cols; ++j) {
45       Vec2f flow_at_point = flow.at<Vec2f>(i, j);
46
47       if (fwrite(&(flow_at_point[0]), sizeof(float), 1, file) != 1 ||
48           fwrite(&(flow_at_point[1]), sizeof(float), 1, file) != 1) {
49         printf(APP_NAME "writeOpticalFlowToFile : problem writing data\n");
50         exit(1);
51       }
52     }
53   }
54 }
55
56 static void run(int argc, char** argv) {
57   if (argc < 3) {
58     printf(APP_NAME "Wrong number of command line arguments for mode `run`: %d (expected %d)\n",
59            argc, 3);
60     exit(1);
61   }
62
63   Mat frame1 = imread(argv[0]);
64   Mat frame2 = imread(argv[1]);
65
66   if (frame1.empty()) {
67     printf(APP_NAME "Image #1 : %s cannot be read\n", argv[0]);
68     exit(1);
69   }
70
71   if (frame2.empty()) {
72     printf(APP_NAME "Image #2 : %s cannot be read\n", argv[1]);
73     exit(1);
74   }
75
76   if (frame1.rows != frame2.rows && frame1.cols != frame2.cols) {
77     printf(APP_NAME "Images should be of equal sizes\n");
78     exit(1);
79   }
80
81   if (frame1.type() != 16 || frame2.type() != 16) {
82     printf(APP_NAME "Images should be of equal type CV_8UC3\n");
83     exit(1);
84   }
85
86   printf(APP_NAME "Read two images of size [rows = %d, cols = %d]\n",
87          frame1.rows, frame1.cols);
88
89   Mat flow;
90
91   float start = (float)getTickCount();
92   calcOpticalFlowSF(frame1, frame2,
93                     flow,
94                     3, 2, 4, 4.1, 25.5, 18, 55.0, 25.5, 0.35, 18, 55.0, 25.5, 10);
95   printf(APP_NAME "calcOpticalFlowSF : %lf sec\n", (getTickCount() - start) / getTickFrequency());
96
97   FILE* file = fopen(argv[2], "wb");
98   if (file == NULL) {
99     printf(APP_NAME "Unable to open file '%s' for writing\n", argv[2]);
100     exit(1);
101   }
102   printf(APP_NAME "Writing to file\n");
103   writeOpticalFlowToFile(flow, file);
104   fclose(file);
105 }
106
107 static bool readOpticalFlowFromFile(FILE* file, Mat& flow) {
108   char header[5];
109   if (fread(header, 1, 4, file) < 4 && (string)header != "PIEH") {
110     return false;
111   }
112
113   int cols, rows;
114   if (fread(&cols, sizeof(int), 1, file) != 1||
115       fread(&rows, sizeof(int), 1, file) != 1) {
116     return false;
117   }
118
119   flow = Mat::zeros(rows, cols, CV_32FC2);
120
121   for (int i = 0; i < rows; ++i) {
122     for (int j = 0; j < cols; ++j) {
123       Vec2f flow_at_point;
124       if (fread(&(flow_at_point[0]), sizeof(float), 1, file) != 1 ||
125           fread(&(flow_at_point[1]), sizeof(float), 1, file) != 1) {
126         return false;
127       }
128       flow.at<Vec2f>(i, j) = flow_at_point;
129     }
130   }
131
132   return true;
133 }
134
135 static bool isFlowCorrect(float u) {
136   return !cvIsNaN(u) && (fabs(u) < 1e9);
137 }
138
139 static float calc_rmse(Mat flow1, Mat flow2) {
140   float sum = 0;
141   int counter = 0;
142   const int rows = flow1.rows;
143   const int cols = flow1.cols;
144
145   for (int y = 0; y < rows; ++y) {
146     for (int x = 0; x < cols; ++x) {
147       Vec2f flow1_at_point = flow1.at<Vec2f>(y, x);
148       Vec2f flow2_at_point = flow2.at<Vec2f>(y, x);
149
150       float u1 = flow1_at_point[0];
151       float v1 = flow1_at_point[1];
152       float u2 = flow2_at_point[0];
153       float v2 = flow2_at_point[1];
154
155       if (isFlowCorrect(u1) && isFlowCorrect(u2) && isFlowCorrect(v1) && isFlowCorrect(v2)) {
156         sum += (u1-u2)*(u1-u2) + (v1-v2)*(v1-v2);
157         counter++;
158       }
159     }
160   }
161   return (float)sqrt(sum / (1e-9 + counter));
162 }
163
164 static void eval(int argc, char** argv) {
165   if (argc < 2) {
166     printf(APP_NAME "Wrong number of command line arguments for mode `eval` : %d (expected %d)\n",
167            argc, 2);
168     exit(1);
169   }
170
171   Mat flow1, flow2;
172
173   FILE* flow_file_1 = fopen(argv[0], "rb");
174   if (flow_file_1 == NULL) {
175     printf(APP_NAME "Cannot open file with first flow : %s\n", argv[0]);
176     exit(1);
177   }
178   if (!readOpticalFlowFromFile(flow_file_1, flow1)) {
179     printf(APP_NAME "Cannot read flow data from file %s\n", argv[0]);
180     exit(1);
181   }
182   fclose(flow_file_1);
183
184   FILE* flow_file_2 = fopen(argv[1], "rb");
185   if (flow_file_2 == NULL) {
186     printf(APP_NAME "Cannot open file with first flow : %s\n", argv[1]);
187     exit(1);
188   }
189   if (!readOpticalFlowFromFile(flow_file_2, flow2)) {
190     printf(APP_NAME "Cannot read flow data from file %s\n", argv[1]);
191     exit(1);
192   }
193   fclose(flow_file_2);
194
195   float rmse = calc_rmse(flow1, flow2);
196   printf("%lf\n", rmse);
197 }
198
199 int main(int argc, char** argv) {
200   if (argc < 2) {
201     printf(APP_NAME "Mode is not specified\n");
202     help();
203     exit(1);
204   }
205   string mode = (string)argv[1];
206   int new_argc = argc - 2;
207   char** new_argv = &argv[2];
208
209   if ("run" == mode) {
210     run(new_argc, new_argv);
211   } else if ("eval" == mode) {
212     eval(new_argc, new_argv);
213   } else if ("help" == mode)
214     help();
215   else {
216     printf(APP_NAME "Unknown mode : %s\n", argv[1]);
217     help();
218   }
219
220   return 0;
221 }