PICCANTE  0.4
The hottest HDR imaging library!
live_wire.hpp
Go to the documentation of this file.
1 /*
2 
3 PICCANTE
4 The hottest HDR imaging library!
5 http://vcg.isti.cnr.it/piccante
6 
7 Copyright (C) 2014
8 Visual Computing Laboratory - ISTI CNR
9 http://vcg.isti.cnr.it
10 First author: Francesco Banterle
11 
12 This Source Code Form is subject to the terms of the Mozilla Public
13 License, v. 2.0. If a copy of the MPL was not distributed with this
14 file, You can obtain one at http://mozilla.org/MPL/2.0/.
15 
16 */
17 
18 #ifndef PIC_ALGORITHMS_LIVE_WIRE_HPP
19 #define PIC_ALGORITHMS_LIVE_WIRE_HPP
20 
21 #include <functional>
22 #include <vector>
23 
24 #include "../base.hpp"
25 
26 #include "../image.hpp"
27 #include "../filtering/filter_luminance.hpp"
28 #include "../filtering/filter_gradient.hpp"
29 #include "../filtering/filter_log_2d_opt.hpp"
30 #include "../filtering/filter_channel.hpp"
31 #include "../filtering/filter_sampler_2d.hpp"
32 #include "../util/vec.hpp"
33 #include "../util/std_util.hpp"
34 
35 namespace pic {
36 
37 class LiveWire
38 {
39 protected:
40  float fD_const;
41 
42  float *fG_min, *fG_max;
43 
44  Image *img_G, *fZ, *g;
45  int *pointers;
46  bool *e;
47 
54  float getCost(Vec2i &p, Vec2i &q)
55  {
56  float out;
57  float *tmp;
58 
59  //fZ cost
60  tmp = (*fZ)(q[0], q[1]);
61  out = 0.43f * tmp[0];
62 
63  //fG cost
64  tmp = (*img_G)(q[0], q[1]);
65 
66  float fG = 1.0f - (tmp[2] - fG_min[2]) / fG_max[2];
67  float dist_qp = sqrtf(float(q.distanceSq(p)));
68  out += 0.14f * fG / dist_qp;
69 
70  //fD cost
71 
72  //D_p
73  tmp = (*img_G)(p[0], p[1]);
74  Vec2f D_p(tmp[1], -tmp[0]);
75  float n_D_p_sq = D_p.lengthSq();
76  if(n_D_p_sq > 0.0f) {
77  D_p /= sqrtf(n_D_p_sq);
78  }
79 
80  //D_q
81  tmp = (*img_G)(q[0], q[1]);
82  Vec2f D_q(tmp[1], -tmp[0]);
83  float n_D_q_sq = D_q.lengthSq();
84  if(n_D_q_sq > 0.0f) {
85  D_q /= sqrtf(n_D_q_sq);
86  }
87 
88  //Delta_qp
89  Vec2f delta_qp(float(q[0] - p[0]), float(q[1] - p[1]));
90 
91  Vec2f L;
92  if(D_p.dot(delta_qp) >= 0.0f) {
93  L = delta_qp;
94  } else {
95  L = -delta_qp;
96  }
97 
98  float n_L_sq = L.lengthSq();
99  if(n_L_sq > 0.0f) {
100  L /= sqrtf(n_L_sq);
101  }
102 
103  float dp_pq = D_p.dot(L);
104  float dq_pq = L.dot(D_q);
105 
106  float fD = (acosf(dp_pq) + acosf(dq_pq)) * fD_const;
107 
108  out += 0.43f * fD;
109 
110  return out;
111  }
112 
116  void release()
117  {
118  img_G = delete_s(img_G);
119  fZ = delete_s(fZ);
120  g = delete_s(g);
121  e = delete_s(e);
123  }
124 
130  static float f1minusx(float x)
131  {
132  return 1.0f - x;
133  }
134 
135 public:
136 
138  {
139  fD_const = 2.0f / (C_PI * 3.0f);
140 
141  img_G = NULL;
142  fZ = NULL;
143  g = NULL;
144  e = NULL;
145  pointers = NULL;
146 
147  set(img);
148  }
149 
151  {
152  release();
153  }
154 
159  void set(Image *img)
160  {
161  release();
162 
163  Image *img_L = FilterLuminance::execute(img, NULL);
164 
165  //compute fG
167  fG_min = img_G->getMinVal(NULL, NULL);
168  fG_max = img_G->getMaxVal(NULL, NULL);
169 
170  //compute fZ
171  fZ = FilterLoG2DOpt::execute(img_L, fZ, 1.0f);
173 
174  //aux buffers
175  g = img_L;
176 
177  e = new bool[img_L->nPixels()];
178 
179  pointers = new int[img_L->nPixels()];
180  }
181 
190  void execute(Vec2i pS, Vec2i pE, std::vector< Vec2i > &out, bool bConstrained = false, bool bMultiple = false)
191  {
192  float *tmp;
193 
194  e = Buffer<bool>::assign(e, g->nPixels(), false);
195  //*g = FLT_MAX;
196  //pointers = Buffer<int>::assign(pointers, g->nPixels(), 0);
197 
198  int width = g->width;
199  int height = g->height;
200 
201  int nx[] = {-1, 0, 1, -1, 1, -1, 0, 1};
202  int ny[] = { 1, 1, 1, 0, 0, -1, -1, -1};
203 
204  int bX[2], bY[2];
205 
206  if(!bConstrained) {
207  bX[0] = -1;
208  bX[1] = width;
209 
210  bY[0] = -1;
211  bY[1] = height;
212  } else {
213  int boundSize = 11;
214 
215  bX[0] = MAX(MIN(pS[0], pE[0]) - boundSize, -1);
216  bX[1] = MIN(MAX(pS[0], pE[0]) + boundSize, width);
217 
218  bY[0] = MAX(MIN(pS[1], pE[1]) - boundSize, -1);
219  bY[1] = MIN(MAX(pS[1], pE[1]) + boundSize, height);
220  }
221 
222  tmp = (*g)(pS[0], pS[1]);
223  tmp[0] = 0.0f;
224 
225  std::vector< Vec2i > list;
226  list.push_back(pS);
227 
228  while(!list.empty()) { //get the best
229  std::vector< Vec2i >::iterator index;
230  Vec2i q;
231 
232  float g_q = FLT_MAX;
233  bool bCheck = false;
234  for(auto it = list.begin(); it != list.end(); it++) {
235  float g_it = (*g)((*it)[0], (*it)[1])[0];
236  if(g_it < g_q) {
237  g_q = g_it;
238  index = it;
239  bCheck = true;
240  }
241  }
242 
243  if(!bCheck) {
244  break;
245  }
246 
247  q[0] = (*index)[0];
248  q[1] = (*index)[1];
249 
250  list.erase(index);
251 
252  //update
253  int index_q = q[1] * width + q[0];
254  e[index_q] = true;
255 
256  for(int i = 0; i < 8; i++) {
257  Vec2i r(q[0] + nx[i], q[1] + ny[i]);
258 
259  if((r[0] > bX[0]) && (r[0] < bX[1]) &&
260  (r[1] > bY[0]) && (r[1] < bY[1])) {
261 
262  if(!e[r[1] * width + r[0]]) {
263  float g_tmp = g_q + getCost(q, r);
264 
265  //check list
266  bool bFlag = false;
267  for(auto it = list.begin(); it != list.end(); it++) {
268  if(r.equal(*it)) {
269  index = it;
270  bFlag = true;
271  }
272  }
273 
274  if(bFlag && (g_tmp < g_q)) {
275  list.erase(index);
276  }
277 
278  if(!bFlag) {
279  tmp = (*g)(r[0], r[1]);
280  tmp[0] = g_tmp;
281 
282  int index = (r[1] * width + r[0]);
283  pointers[index] = index_q;
284  list.push_back(r);
285  }
286 
287  }
288 
289  }
290 
291  }
292  }
293 
294  //forward pass -- tracking
295  if(!bMultiple) {
296  out.clear();
297  }
298 
299  out.push_back(pE);
300  Vec2i m = pE;
301  Vec2i prev(-1, -1);
302 
303  int maxIter = (width * height);
304  int i = 0;
305 
306  while((!prev.equal(m)) && (i < maxIter)) {
307  prev = m;
308 
309  if(m.equal(pS)) {
310  break;
311  }
312 
313  int index = (m[1] * width + m[0]);
314  int t_x = pointers[index] % width;
315  int t_y = pointers[index] / width;
316  Vec2i t(t_x, t_y);
317 
318  out.push_back(t);
319  m = t;
320 
321  i++;
322  }
323 
324  }
325 
333  static void executeLiveWireSingle(Image *in, Vec2i pS, Vec2i pE, std::vector< Vec2i > &out)
334  {
335  if(in != NULL) {
336  pic::LiveWire *lw = new pic::LiveWire(in);
337 
338  lw->execute(pS, pE, out, true, false);
339 
340  delete lw;
341  }
342  }
343 
350  static void executeLiveWireMultiple(Image *in, std::vector< Vec2i > &controlPoints, std::vector< Vec2i > &out)
351  {
352  if(in != NULL) {
353  pic::LiveWire *lw = new pic::LiveWire(in);
354 
355  for(auto i = 0; i < (controlPoints.size() - 1); i++) {
356  lw->execute(controlPoints.at(i), controlPoints.at(i + 1), out, true, true);
357  }
358 
359  delete lw;
360  }
361  }
362 };
363 
364 } // end namespace pic
365 
366 #endif /* PIC_ALGORITHMS_LIVE_WIRE_HPP */
367 
static void executeLiveWireSingle(Image *in, Vec2i pS, Vec2i pE, std::vector< Vec2i > &out)
executeLiveWireSingle
Definition: live_wire.hpp:333
float * fG_max
Definition: live_wire.hpp:42
T * delete_s(T *data)
delete_s
Definition: std_util.hpp:123
int * pointers
Definition: live_wire.hpp:45
void execute(Vec2i pS, Vec2i pE, std::vector< Vec2i > &out, bool bConstrained=false, bool bMultiple=false)
execute
Definition: live_wire.hpp:190
bool * e
Definition: live_wire.hpp:46
float * fG_min
Definition: live_wire.hpp:42
const float C_PI
Definition: math.hpp:50
float * getMinVal(BBox *box, float *ret)
getMinVal computes the minimum value for the current Image.
Image * g
Definition: live_wire.hpp:44
Image * img_G
Definition: live_wire.hpp:44
static Image * execute(Image *imgIn, Image *imgOut=NULL, GRADIENT_TYPE type=G_SOBEL, int colorChannel=0)
execute
Definition: filter_gradient.hpp:89
int nPixels() const
nPixels computes the number of pixels.
Definition: image.hpp:499
float fD_const
Definition: live_wire.hpp:40
static void executeLiveWireMultiple(Image *in, std::vector< Vec2i > &controlPoints, std::vector< Vec2i > &out)
executeLiveWireMultiple
Definition: live_wire.hpp:350
static Image * execute(Image *imgIn, Image *imgOut, LUMINANCE_TYPE type=LT_CIE_LUMINANCE)
execute
Definition: filter_luminance.hpp:166
void applyFunction(float(*func)(float))
applyFunction is an operator that applies an input function to all values in data.
LiveWire(Image *img)
Definition: live_wire.hpp:137
T dot(Vec< N, T > a)
dot
Definition: vec.hpp:276
#define MIN(a, b)
Definition: math.hpp:69
The Image class stores an image as buffer of float.
Definition: image.hpp:60
Image * fZ
Definition: live_wire.hpp:44
Definition: live_wire.hpp:37
Definition: bilateral_separation.hpp:25
bool equal(Vec< N, T > a)
equal
Definition: vec.hpp:203
#define MAX(a, b)
Definition: math.hpp:73
void release()
release
Definition: live_wire.hpp:116
static float f1minusx(float x)
f1minusx
Definition: live_wire.hpp:130
float * getMaxVal(BBox *box, float *ret)
getMaxVal computes the maximum value for the current Image.
int width
Definition: image.hpp:80
float getCost(Vec2i &p, Vec2i &q)
getCost
Definition: live_wire.hpp:54
int height
Definition: image.hpp:80
T lengthSq()
lengthSq
Definition: vec.hpp:335
static Image * execute(Image *imgIn, Image *imgOut, float sigma)
execute
Definition: filter_log_2d_opt.hpp:51
~LiveWire()
Definition: live_wire.hpp:150
The Vec class.
Definition: vec.hpp:35
static T * assign(T *buffer, int n, T value)
assign assigns value to buffer
Definition: buffer.hpp:45