1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4 // This functions have been contributed by Jonas Geisters <geistert@nue.tu-berlin.de>
5
6 #include "../precomp.hpp"
7
8 #include "geo_interpolation.hpp"
9 #include <string>
10 #include <map>
11 namespace cv {
12 namespace optflow {
13
14 struct Graph_helper {
15 std::vector<int> mem;
16 int e_size;
Graph_helpercv::optflow::Graph_helper17 Graph_helper(int k, int num_nodes) {
18 e_size = (2 * k + 1);
19 mem.resize(e_size * num_nodes, 0);
20 }
sizecv::optflow::Graph_helper21 inline int size(int id) {
22 int r_addr = id * (e_size);
23 return mem[r_addr];
24 }
datacv::optflow::Graph_helper25 inline int * data(int id) {
26 int r_addr = id * (e_size)+1;
27 return &mem[r_addr];
28 }
addcv::optflow::Graph_helper29 inline void add(int id, std::pair<float, int> data) {
30 int r_addr = id * (e_size);
31 int size = ++mem[r_addr];
32 r_addr += 2 * size - 1;//== 1 + 2*(size-1);
33 *(float*)&mem[r_addr] = data.first;
34 mem[r_addr + 1] = data.second;
35 }
color_in_targetcv::optflow::Graph_helper36 inline bool color_in_target(int id, int color) {
37 int r_addr = id * (e_size);
38 int size = mem[r_addr];
39 r_addr += 2;
40 for (int i = 0; i < size; i++) {
41 if (mem[r_addr] == color) {
42 return true;
43 }
44 r_addr += 2;
45 }
46 return false;
47 }
48
49 };
50
sgeo_dist(const Mat & gra,int y,int x,float max,Mat & prev)51 Mat sgeo_dist(const Mat& gra, int y, int x, float max, Mat &prev)
52 {
53 std::vector <Point2f> points;
54 points.push_back(Point2f(static_cast<float>(x), static_cast<float>(y)));
55 return sgeo_dist(gra, points, max, prev);
56 }
sgeo_dist(const Mat & gra,const std::vector<Point2f> & points,float max,Mat & prev)57 Mat sgeo_dist(const Mat& gra, const std::vector<Point2f> & points, float max, Mat &prev)
58 {
59 int Dx[] = { -1,0,1,-1,1,-1,0,1 };
60 int Dy[] = { -1,-1,-1,0,0,1,1,1 };
61 Mat dm(gra.rows, gra.cols, CV_32F, Scalar(max));
62 prev = Mat(gra.rows, gra.cols, CV_8U, Scalar(255));
63
64 std::multimap<float, Vec2i > not_visited_with_value;
65
66 for (auto i = points.begin(); i != points.end(); i++)
67 {
68 int y = static_cast<int>(i->y);
69 int x = static_cast<int>(i->x);
70 not_visited_with_value.insert(std::pair<float, Vec2i >(0.f, Vec2i(y, x)));
71 dm.at<float>(y, x) = 0;
72 }
73
74 bool done = false;
75 while (!done)
76 {
77 if (not_visited_with_value.begin() == not_visited_with_value.end()) {
78 done = true;
79 break;
80 }
81 std::multimap<float, Vec2i >::iterator current_it = not_visited_with_value.begin();
82 std::pair<float, Vec2i > current_p = *current_it;
83 not_visited_with_value.erase(current_it);
84
85 int y = current_p.second[0];
86 int x = current_p.second[1];
87 float cur_d = current_p.first;
88
89 if (dm.at<float>(y, x) != cur_d) {
90 continue;
91 }
92
93 Vec8f gra_e = gra.at<Vec8f>(y, x);
94
95 for (int i = 0; i < 8; i++) {
96 if (gra_e[i] < 0) {
97 continue;
98 }
99 int dx = Dx[i];
100 int dy = Dy[i];
101
102 if (dm.at<float>(y + dy, x + dx) > cur_d + gra_e[i]) {
103 dm.at<float>(y + dy, x + dx) = cur_d + gra_e[i];
104 prev.at<uchar>(y + dy, x + dx) = static_cast<uchar>(7 - i);
105 not_visited_with_value.insert(std::pair<float, Vec2i >(cur_d + gra_e[i], Vec2i(y + dy, x + dx)));
106 }
107
108 }
109 }
110
111
112
113
114 return dm;
115 }
116
interpolate_irregular_nn_raster(const std::vector<Point2f> & prevPoints,const std::vector<Point2f> & nextPoints,const std::vector<uchar> & status,const Mat & i1)117 Mat interpolate_irregular_nn_raster(const std::vector<Point2f> & prevPoints,
118 const std::vector<Point2f> & nextPoints,
119 const std::vector<uchar> & status,
120 const Mat & i1)
121 {
122 Mat gra = getGraph(i1, 0.1f);
123 int Dx[] = { -1,0,1,-1,1,-1,0,1 };
124 int Dy[] = { -1,-1,-1,0,0,1,1,1 };
125 int max_rounds = 10;
126 Mat dirt = Mat(gra.rows, gra.cols, CV_8U, Scalar(0));
127 Mat quellknoten = Mat(gra.rows, gra.cols, CV_32S, Scalar(-1));
128 Mat dist = Mat(gra.rows, gra.cols, CV_32F, Scalar(std::numeric_limits<float>::max()));
129 /*
130 * assign quellknoten ids.
131 */
132 for (int i = 0; i < static_cast<int>(prevPoints.size()); i++)
133 {
134 int x = (int)prevPoints[i].x;
135 int y = (int)prevPoints[i].y;
136 if (status[i] == 0)
137 continue;
138 dirt.at<uchar>(y, x) = 1;
139 dist.at<float>(y, x) = 0;
140 quellknoten.at<int>(y, x) = i;
141 }
142
143 bool clean = true;
144 bool done = false;
145 int x = 0;
146 int y = 0;
147 int rounds = 0;
148 while (!done) {
149 /*
150 * Update x and y
151 * on even rounds go rasterscanorder , on odd round inverse rasterscanorder
152 */
153 if (rounds % 2 == 0) {
154 x++;
155 if (x >= gra.cols) {
156 x = 0;
157 y++;
158 if (y >= gra.rows) {
159 y = 0;
160 rounds++;
161 y = gra.rows - 1;
162 x = gra.cols - 1;
163 if (rounds >= max_rounds || clean) {
164 done = true;
165 break;
166 }
167 }
168 }
169 }
170 else {
171 x--;
172 if (x < 0) {
173 x = gra.cols - 1;
174 y--;
175 if (y < 0) {
176 y = gra.rows - 1;
177 rounds++;
178 y = 0;
179 x = 0;
180 if (rounds >= max_rounds || clean) {
181 done = true;
182 break;
183 }
184 }
185 }
186 }
187 if (dirt.at<uchar>(y, x) == 0) {
188 continue;
189 }
190 dirt.at<uchar>(y, x) = 0;
191
192 float c_dist = dist.at<float>(y, x);
193 Vec8f gra_e = gra.at<Vec8f>(y, x);
194
195 for (int i = 0; i < 8; i++) {
196 int tx = Dx[i];
197 int ty = Dy[i];
198 if (ty == 0 && tx == 0) {
199 continue;
200 }
201 if (x + tx < 0 || x + tx >= gra.cols) {
202 continue;
203 }
204 if (y + ty < 0 || y + ty >= gra.rows) {
205 continue;
206 }
207 if (c_dist > dist.at<float>(y + ty, x + tx)) {
208 if (c_dist > dist.at<float>(y + ty, x + tx) + gra_e[i]) {
209 quellknoten.at<int>(y, x) = quellknoten.at<int>(y + ty, x + tx);
210 dist.at<float>(y, x) = dist.at<float>(y + ty, x + tx) + gra_e[i];
211 dirt.at<uchar>(y, x) = 1;
212 clean = false;
213 }
214 }
215 else {
216 if (c_dist + gra_e[i] < dist.at<float>(y + ty, x + tx)) {
217 quellknoten.at<int>(y + ty, x + tx) = quellknoten.at<int>(y, x);
218 dist.at<float>(y + ty, x + tx) = dist.at<float>(y, x) + gra_e[i];
219 dirt.at<uchar>(y + ty, x + tx) = 1;
220 clean = false;
221 }
222 }
223 }
224
225
226
227 }
228
229 Mat nnFlow(i1.rows, i1.cols, CV_32FC2, Scalar(0));
230 for (y = 0; y < i1.rows; y++) {
231 for (x = 0; x < i1.cols; x++) {
232
233 int id = quellknoten.at<int>(y, x);
234 if (id != -1)
235 {
236 nnFlow.at<Point2f>(y, x) = nextPoints[id] - prevPoints[id];
237 }
238 }
239 }
240 return nnFlow;
241 }
242
interpolate_irregular_knn(const std::vector<Point2f> & _prevPoints,const std::vector<Point2f> & _nextPoints,const std::vector<uchar> & status,const Mat & color_img,int k,float pixeldistance)243 Mat interpolate_irregular_knn(
244 const std::vector<Point2f> & _prevPoints,
245 const std::vector<Point2f> & _nextPoints,
246 const std::vector<uchar> & status,
247 const Mat &color_img,
248 int k,
249 float pixeldistance)
250 {
251 Mat in(color_img.rows, color_img.cols, CV_32FC2);
252 Mat mask = Mat::zeros(color_img.rows, color_img.cols, CV_8UC1);
253
254 for (unsigned n = 0; n < _prevPoints.size(); n++)
255 {
256 if (_prevPoints[n].x >= 0 && _prevPoints[n].y >= 0 && _prevPoints[n].x < color_img.cols && _prevPoints[n].y < color_img.rows)
257 {
258 in.at<Point2f>(_prevPoints[n]) = _nextPoints[n] - _prevPoints[n];
259 mask.at<uchar>(_prevPoints[n]) = status[n];
260 }
261
262 }
263 int Dx[] = { -1,0,1,-1,1,-1,0,1 };
264 int Dy[] = { -1,-1,-1,0,0,1,1,1 };
265 Mat gra = getGraph(color_img, pixeldistance);
266 Mat nnFlow(in.rows, in.cols, CV_32FC2, Scalar(0));
267
268 std::multimap<float, Vec2i > my_agents; // <arrivaltim , < target, color >>
269 Graph_helper graph_helper(k, in.rows*in.cols); //< arrivaltime, color>
270
271
272 int color = 0;
273 std::vector<Vec2i> flow_point_list;
274 for (int y = 0; y < in.rows; y++) {
275 for (int x = 0; x < in.cols; x++) {
276 if (mask.at<uchar>(y, x) > 0) {
277 flow_point_list.push_back(Vec2i(y, x));
278 nnFlow.at<Vec2f>(y, x) = in.at<Vec2f>(y, x);
279
280 int v_id = (y * in.cols + x);
281 graph_helper.add(v_id, std::pair<float, int>(0.f, color));
282
283
284 Vec8f gra_e = gra.at<Vec8f>(y, x);
285 for (int i = 0; i < 8; i++) {
286 if (gra_e[i] < 0)
287 continue;
288 int dx = Dx[i];
289 int dy = Dy[i];
290 int target = (y + dy) * in.cols + (x + dx);
291 Vec2i agent(target, color);
292 my_agents.insert(std::pair<float, Vec2i >(gra_e[i], agent));
293
294 }
295 color++;
296 }
297 }
298 }
299
300 int global_time = 0;
301
302 bool done = false;
303 while (!done) {
304 if (my_agents.size() == 0) {
305 done = true;
306 break;
307 }
308 global_time++;
309
310 std::multimap<float, Vec2i >::iterator current_it = my_agents.begin();
311 std::pair<float, Vec2i > current_p = *current_it;
312 my_agents.erase(current_it);
313
314 int target = current_p.second[0];
315 color = current_p.second[1];
316 float arriv_time = current_p.first;
317
318 Vec8f gra_e = gra.at<Vec8f>(target);// (y*cols+x)
319 if (graph_helper.size(target) >= k) {
320 continue;
321 }
322
323 bool color_found_in_target = graph_helper.color_in_target(target, color);
324 if (color_found_in_target) {
325 continue;
326 }
327 graph_helper.add(target, std::pair<float, int>(arriv_time, color));
328
329
330 for (int i = 0; i < 8; i++) {
331 if (gra_e[i] < 0)
332 continue;
333
334 int dx = Dx[i];
335 int dy = Dy[i];
336 int new_target = target + dx + (dy*in.cols);
337 if (graph_helper.size(new_target) >= k) {
338 continue;
339 }
340 color_found_in_target = graph_helper.color_in_target(new_target, color);
341 if (color_found_in_target) {
342 continue;
343 }
344 Vec2i new_agent(new_target, color);
345 my_agents.insert(std::pair<float, Vec2i >(arriv_time + gra_e[i], new_agent));
346
347 }
348 }
349
350 Mat ret(in.rows, in.cols*k, CV_32FC2);
351 for (int y = 0; y < in.rows; y++) {
352 for (int x = 0; x < in.cols; x++) {
353 for (int i = 0; i < k; i++) {
354 float dist = *((float*)(graph_helper.data(y*in.cols + x) + 2 * i));
355 float id = *((float*)(graph_helper.data(y*in.cols + x) + 2 * i + 1));
356 ret.at<Vec2f>(y, k*x + i) = Vec2f(dist, id);
357 }
358 }
359 }
360 return ret;
361 }
362
getGraph(const Mat & image,float edge_length)363 Mat getGraph(const Mat &image, float edge_length)
364 {
365
366 int Dx[] = { -1,0,1,-1,1,-1,0,1 };
367 int Dy[] = { -1,-1,-1,0,0,1,1,1 };
368 Mat gra(image.rows, image.cols, CV_32FC(8));
369
370 for (int y = 0; y < gra.rows; y++) {
371 for (int x = 0; x < gra.cols; x++) {
372
373 for (int i = 0; i < 8; i++) {
374 int dx = Dx[i];
375 int dy = Dy[i];
376 gra.at<Vec8f>(y, x)[i] = -1;
377
378 if (x + dx < 0 || y + dy < 0 || x + dx >= gra.cols || y + dy >= gra.rows) {
379 continue;
380 }
381
382 if (i < 4) {
383 int si = 7 - i;
384 gra.at<Vec8f>(y, x)[i] = gra.at<Vec8f>(y + dy, x + dx)[si];
385 }
386 else {
387 float p1 = dx * dx*edge_length*edge_length + dy * dy*edge_length*edge_length;
388 float p2 = static_cast<float>(image.at<Vec3b>(y, x)[0] - image.at<Vec3b>(y + dy, x + dx)[0]);
389 float p3 = static_cast<float>(image.at<Vec3b>(y, x)[1] - image.at<Vec3b>(y + dy, x + dx)[1]);
390 float p4 = static_cast<float>(image.at<Vec3b>(y, x)[2] - image.at<Vec3b>(y + dy, x + dx)[2]);
391 gra.at<Vec8f>(y, x)[i] = sqrt(p1 + p2 * p2 + p3 * p3 + p4 * p4);
392 }
393
394 }
395
396 }
397 }
398
399 return gra;
400 }
401
402
interpolate_irregular_nn(const std::vector<Point2f> & _prevPoints,const std::vector<Point2f> & _nextPoints,const std::vector<uchar> & status,const Mat & color_img,float pixeldistance)403 Mat interpolate_irregular_nn(
404 const std::vector<Point2f> & _prevPoints,
405 const std::vector<Point2f> & _nextPoints,
406 const std::vector<uchar> & status,
407 const Mat &color_img,
408 float pixeldistance)
409 {
410 int Dx[] = { -1,0,1,-1,1,-1,0,1 };
411 int Dy[] = { -1,-1,-1,0,0,1,1,1 };
412 std::vector<Point2f> prevPoints, nextPoints;
413 std::map<std::pair<float, float>, std::pair<float, float>> flowMap;
414 for (unsigned n = 0; n < _prevPoints.size(); n++)
415 {
416 if (status[n] != 0)
417 {
418 flowMap.insert(std::make_pair(
419 std::make_pair(_prevPoints[n].x, _prevPoints[n].y),
420 std::make_pair(_nextPoints[n].x, _nextPoints[n].y)));
421 prevPoints.push_back(_prevPoints[n]);
422 nextPoints.push_back(_nextPoints[n]);
423 }
424
425 }
426
427 Mat gra = getGraph(color_img, pixeldistance);
428
429 Mat prev;
430 Mat geo_dist = sgeo_dist(gra, prevPoints, std::numeric_limits<float>::max(), prev);
431
432
433 Mat nnFlow = Mat::zeros(color_img.size(), CV_32FC2);
434 for (int y = 0; y < nnFlow.rows; y++)
435 {
436 for (int x = 0; x < nnFlow.cols; x++)
437 {
438 int cx = x;
439 int cy = y;
440 while (prev.at<uchar>(cy, cx) != 255)
441 {
442 int i = prev.at<uchar>(cy, cx);
443 cx += Dx[i];
444 cy += Dy[i];
445 }
446 auto val = flowMap[std::make_pair(static_cast<float>(cx), static_cast<float>(cy))];
447 nnFlow.at<Vec2f>(y, x) = Vec2f(val.first - cx, val.second - cy);
448 }
449 }
450 return nnFlow;
451 }
452
453 }} // namespace
454