Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
ForwardMappingNearestNeighbour.cpp
1 #include "ForwardMappingNearestNeighbour.hh"
2 #include <Base/Common/BIASpragma.hh>
3 #include <algorithm>
4 
5 using namespace BIAS;
6 using namespace std;
7 
8 template <class InputStorageType, class OutputStorageType>
11  fillblack_ = true;
12  fillAreaWindowSize_=5;
13 }
14 
15 template <class InputStorageType, class OutputStorageType>
18 
19 }
20 
21 template <class InputStorageType, class OutputStorageType>
24 
25 }
26 
27 template <class InputStorageType, class OutputStorageType>
31  SourceP_ = src.SourceP_;
32  SinkP_ = src.SinkP_;
33  intermediate_ = src.intermediate_;
34  intermediateTex_ = src.intermediateTex_;
35  dSourceWidth_ = src.dSourceWidth_;
36  dSourceHeight_ = src.dSourceHeight_;
37  dTargetWidth_ = src.dTargetWidth_;
38  dTargetHeight_ = src.dTargetHeight_;
39 
40  return *this;
41 }
42 
43 template <class InputStorageType, class OutputStorageType>
47  bool withTex_= (texin == NULL) ? false : true;
48 
49  in->GetROI()->GetCorners(ulx_, uly_, lrx_, lry_);
50  lrx_--; lry_--;
51  if (out.IsEmpty()) {
52  out.Init(dTargetWidth_, dTargetHeight_);
53  }
54  out.FillImageWithConstValue((OutputStorageType)0);
55  intermediate_.FillImageWithConstValue((OutputStorageType)0);
56 
57  const InputStorageType** idaSource_ = in->GetImageDataArray();
58  OutputStorageType** idaTarget_ = out.GetImageDataArray();
59  const InputStorageType** idaTexIn_ = NULL;
60  OutputStorageType** idaTexOut_ = NULL;
61  OutputStorageType** idaIntermediate_=intermediate_.GetImageDataArray();
62  OutputStorageType** idaIntermediateTex_=intermediateTex_.GetImageDataArray();
63  if (withTex_) {
64  idaTexIn_ = texin->GetImageDataArray();
65  if (texout.IsEmpty())
66  texout.Init(dTargetWidth_, dTargetHeight_, dTexChannels_);
67  texout.FillImageWithConstValue((OutputStorageType)0);
68  idaTexOut_ = texout.GetImageDataArray();
69  intermediateTex_.FillImageWithConstValue((OutputStorageType)0);
70  }
71 
72  //calculate projection of roi corners in cylindric image;
73  int cornerpos[8] = { ulx_,uly_, lrx_,uly_, ulx_,lry_, lrx_,lry_ };
74  HomgPoint2D corners[4];
75  for (int i=0;i<4;i++) {
76  HomgPoint2D p2d;
77  p2d[0]=cornerpos[2*i];
78  p2d[1]=cornerpos[2*i+1];
79  p2d[2]=1;
80  float fDepth = idaSource_[ cornerpos[2*i+1] ][ cornerpos[2*i] ];
81  if (fDepth < 5.0)
82  fDepth = 1000.0;
83  HomgPoint3D p3d = (BIAS::HomgPoint3D)SourceP_.UnProjectToPoint(p2d, fDepth);
84  if (SinkP_.DoesPointProjectIntoImage(p3d, p2d)) {
85 
86  p2d.Homogenize();
87  corners[i] = p2d;
88  }
89  else {
90 
91  if (p2d[0] < 0)
92  p2d[0] = 0;
93  if (p2d[0] >= dTargetWidth_)
94  p2d[0] = dTargetWidth_ -1;
95  if (p2d[1] < 0)
96  p2d[1] = 0;
97  if (p2d[1] >= dTargetHeight_)
98  p2d[1] = dTargetHeight_ -1;
99  corners[i] = p2d;
100  }
101  }
102 
103  //check if all bounding corners are within panorama image and
104  //sort bounding corners in min and max
105  boundMin_[0]=dTargetWidth_; boundMin_[1]=dTargetHeight_; boundMin_[2] = 1;
106  boundMax_[0]=0; boundMax_[1]=0; boundMax_[2] = 1;
107  for (unsigned int j=0;j<2;j++) {
108  for (unsigned int i=0;i<4;i++) {
109  if (corners[i][j] < boundMin_[j]) {
110  boundMin_[j] = corners[i][j];
111  }
112  if (corners[i][j]> boundMax_[j]) {
113  boundMax_[j] = corners[i][j];
114  }
115  }
116  }
117 
118  // cout<<"Bound min:"<<boundMin_<<" BoundMax:"<<boundMax_<<endl;
119  // vector<float> xy_value[2];
120  // for (unsigned int i=0;i<2;i++) {
121  // for (unsigned int j=0;j<4;j++) {
122  // xy_value[i].push_back(corners[j][i]);
123  // }
124  // std::sort(xy_value[i].begin(), xy_value[i].end());
125  // }
126  // boundMin_[0]=xy_value[0][1]; boundMin_[1]=xy_value[1][1]; boundMin_[2] = 1;
127  // boundMax_[0]=xy_value[0][2]; boundMax_[1]=xy_value[1][2]; boundMax_[2] = 1;
128  // cout<<"Sorted Bound min:"<<boundMin_<<" BoundMax:"<<boundMax_<<endl;
129 
130  bool wrapAround = false;
131 
132  //detect wrap around in y here
133  if(boundMax_[1] > boundMin_[1] &&
134  boundMax_[1]-dTargetHeight_/2 > boundMin_[1]){
135  cout<<"wrap around detected!"<<endl;
136 
137  //x stays the same
138  boundMinWrap_[0] = boundMin_[0];
139  boundMaxWrap_[0] = boundMax_[0];
140  boundMin_[0] = boundMin_[0];
141  boundMax_[0] = boundMax_[0];
142 
143  //y changes
144  boundMinWrap_[1] = boundMax_[1];
145  boundMaxWrap_[1] = dTargetHeight_-2;
146 
147  boundMax_[1] = boundMin_[1];
148  boundMin_[1] = 1;
149 
150  wrapAround=true;
151  }
152 
153 
154  //project depth and texture to cylindric panorama via unproject/project
155  BIAS::HomgPoint2D point2d_src;
156  BIAS::HomgPoint3D point3d;
157  BIAS::HomgPoint2D point2d_dst;
158  float depth_src=0.0;
159  for (int y=uly_;y<lry_;y++) {
160  for (int x=ulx_;x<lrx_;x++) {
161  point2d_src[0] = x;
162  point2d_src[1] = y;
163  point2d_src[2] = 1;
164  depth_src = idaSource_[y][x];
165  if (depth_src > 500) {
166  point3d =(BIAS::HomgPoint3D)SourceP_.UnProjectToPoint(point2d_src, depth_src);
167  if (SinkP_.DoesPointProjectIntoImage(point3d, point2d_dst)) {
168  //cout<<"Point:"<<point3d<<" projects to sink at:"<<point2d_dst<<endl;
169  point2d_dst.Homogenize();
170  int xdst = point2d_dst[0];
171  int ydst = point2d_dst[1];
172  idaIntermediate_[ydst][xdst] = depth_src;
173  if (withTex_) {
174  for (unsigned int i=0;i<dTexChannels_;i++)
175  idaIntermediateTex_[ydst][xdst*dTexChannels_+i] = idaTexIn_[y][x*dTexChannels_+i];
176  }
177  }
178  // else
179  // cout<<"Point:"<<point3d<<" does not project to sink!"<<endl;
180  }
181  }
182  }
183 
184  // fill black areas with neighbouring pixels in DEPTH image
185  if (fillblack_) {
186  for (unsigned int y=boundMin_[1]+fillAreaWindowSize_;
187  y<boundMax_[1]-fillAreaWindowSize_;y++) {
188  for (unsigned int x=boundMin_[0]+fillAreaWindowSize_;
189  x<boundMax_[0]-fillAreaWindowSize_;x++) {
190  if (idaIntermediate_[y][x] == 0) {
191  for (unsigned int mod=1;mod<fillAreaWindowSize_;mod++) {
192  if (idaIntermediate_[y][x+mod] != 0) {
193  idaTarget_[y][x] = idaIntermediate_[y][x+mod];
194  break;
195  }
196  if (idaIntermediate_[y][x-mod] != 0) {
197  idaTarget_[y][x] = idaIntermediate_[y][x-mod];
198  break;
199  }
200  if (idaIntermediate_[y+mod][x+mod] != 0) {
201  idaTarget_[y][x] = idaIntermediate_[y+mod][x+mod];
202  break;
203  }
204  if (idaIntermediate_[y+mod][x] != 0) {
205  idaTarget_[y][x] = idaIntermediate_[y+mod][x];
206  break;
207  }
208  if (idaIntermediate_[y+mod][x-mod] != 0) {
209  idaTarget_[y][x] = idaIntermediate_[y+mod][x-mod];
210  break;
211  }
212  if (idaIntermediate_[y-mod][x+mod] != 0) {
213  idaTarget_[y][x] = idaIntermediate_[y-mod][x+mod];
214  break;
215  }
216  if (idaIntermediate_[y-mod][x] != 0) {
217  idaTarget_[y][x] = idaIntermediate_[y-mod][x];
218  break;
219  }
220  if (idaIntermediate_[y-mod][x-mod] != 0) {
221  idaTarget_[y][x] = idaIntermediate_[y-mod][x-mod];
222  break;
223  }
224  }
225  } else {
226  idaTarget_[y][x] = idaIntermediate_[y][x];
227  }
228  }
229  }
230 
231 
232  if(wrapAround){
233  for (unsigned int y=boundMinWrap_[1]+fillAreaWindowSize_;
234  y<boundMaxWrap_[1]-fillAreaWindowSize_;y++) {
235  for (unsigned int x=boundMinWrap_[0]+fillAreaWindowSize_;
236  x<boundMaxWrap_[0]-fillAreaWindowSize_;x++) {
237  if (idaIntermediate_[y][x] == 0) {
238  for (unsigned int mod=1;mod<fillAreaWindowSize_;mod++) {
239  if (idaIntermediate_[y][x+mod] != 0) {
240  idaTarget_[y][x] = idaIntermediate_[y][x+mod];
241  break;
242  }
243  if (idaIntermediate_[y][x-mod] != 0) {
244  idaTarget_[y][x] = idaIntermediate_[y][x-mod];
245  break;
246  }
247  if (idaIntermediate_[y+mod][x+mod] != 0) {
248  idaTarget_[y][x] = idaIntermediate_[y+mod][x+mod];
249  break;
250  }
251  if (idaIntermediate_[y+mod][x] != 0) {
252  idaTarget_[y][x] = idaIntermediate_[y+mod][x];
253  break;
254  }
255  if (idaIntermediate_[y+mod][x-mod] != 0) {
256  idaTarget_[y][x] = idaIntermediate_[y+mod][x-mod];
257  break;
258  }
259  if (idaIntermediate_[y-mod][x+mod] != 0) {
260  idaTarget_[y][x] = idaIntermediate_[y-mod][x+mod];
261  break;
262  }
263  if (idaIntermediate_[y-mod][x] != 0) {
264  idaTarget_[y][x] = idaIntermediate_[y-mod][x];
265  break;
266  }
267  if (idaIntermediate_[y-mod][x-mod] != 0) {
268  idaTarget_[y][x] = idaIntermediate_[y-mod][x-mod];
269  break;
270  }
271  }
272  } else {
273  idaTarget_[y][x] = idaIntermediate_[y][x];
274  }
275  }
276  }
277  }
278  }
279  // fill black areas with neighbouring pixels in TEXTURE image
280  if (withTex_ && fillblack_) {
281  if (dTexChannels_ == 1) {
282  for (unsigned int y=boundMin_[1]+fillAreaWindowSize_;
283  y<boundMax_[1]-fillAreaWindowSize_;y++) {
284  for (unsigned int x=boundMin_[0]+fillAreaWindowSize_;
285  x<boundMax_[0]-fillAreaWindowSize_;x++) {
286  if (idaIntermediate_[y][x] == 0) {
287  for (unsigned int mod=1;mod<fillAreaWindowSize_;mod++) {
288  if (idaIntermediateTex_[y][x+mod] != 0) {
289  idaTexOut_[y][x] = idaIntermediateTex_[y][x+mod];
290  break;
291  }
292  if (idaIntermediateTex_[y][x-mod] != 0) {
293  idaTexOut_[y][x] = idaIntermediateTex_[y][x-mod];
294  break;
295  }
296  if (idaIntermediateTex_[y+mod][x+mod] != 0) {
297  idaTexOut_[y][x] = idaIntermediateTex_[y+mod][x+mod];
298  break;
299  }
300  if (idaIntermediateTex_[y+mod][x] != 0) {
301  idaTexOut_[y][x] = idaIntermediateTex_[y+mod][x];
302  break;
303  }
304  if (idaIntermediateTex_[y+mod][x-mod] != 0) {
305  idaTexOut_[y][x] = idaIntermediateTex_[y+mod][x-mod];
306  break;
307  }
308  if (idaIntermediateTex_[y-mod][x+mod] != 0) {
309  idaTexOut_[y][x] = idaIntermediateTex_[y-mod][x+mod];
310  break;
311  }
312  if (idaIntermediateTex_[y-mod][x] != 0) {
313  idaTexOut_[y][x] = idaIntermediateTex_[y-mod][x];
314  break;
315  }
316  if (idaIntermediateTex_[y-mod][x-mod] != 0) {
317  idaTexOut_[y][x] = idaIntermediateTex_[y-mod][x-mod];
318  break;
319  }
320  }
321  } else {
322  idaTexOut_[y][x] = idaIntermediateTex_[y][x];
323  }
324  }
325  }
326  } else {
327  for (unsigned int y=boundMin_[1]+fillAreaWindowSize_;
328  y<boundMax_[1]-fillAreaWindowSize_;y++) {
329  for (unsigned int x=((int)boundMin_[0]+fillAreaWindowSize_)*dTexChannels_;
330  x<((int)boundMax_[0]-fillAreaWindowSize_)*dTexChannels_;
331  x+=dTexChannels_) {
332  unsigned int val = 0;
333  val = GetSummedValue_(&(idaIntermediateTex_[y][x]));
334  if (val == 0) {
335  for (unsigned int mod=1;mod<fillAreaWindowSize_;mod++) {
336  unsigned int xmod = mod * dTexChannels_;
337  if (GetSummedValue_(&(idaIntermediateTex_[y][x+xmod])) != 0) {
338  SetValue_(&(idaIntermediateTex_[y][x+xmod]), &(idaTexOut_[y][x]));
339  break;
340  }
341  if (GetSummedValue_(&(idaIntermediateTex_[y][x-xmod])) != 0) {
342  SetValue_(&(idaIntermediateTex_[y][x-xmod]), &(idaTexOut_[y][x]));
343  break;
344  }
345  if (GetSummedValue_(&(idaIntermediateTex_[y+mod][x+xmod])) != 0) {
346  SetValue_(&(idaIntermediateTex_[y+mod][x+xmod]), &(idaTexOut_[y][x]));
347  break;
348  }
349  if (GetSummedValue_(&(idaIntermediateTex_[y+mod][x])) != 0) {
350  SetValue_(&(idaIntermediateTex_[y+mod][x]), &(idaTexOut_[y][x]));
351  break;
352  }
353  if (GetSummedValue_(&(idaIntermediateTex_[y+mod][x-xmod])) != 0) {
354  SetValue_(&(idaIntermediateTex_[y+mod][x-xmod]), &(idaTexOut_[y][x]));
355  break;
356  }
357  if (GetSummedValue_(&(idaIntermediateTex_[y-mod][x+xmod])) != 0) {
358  SetValue_(&(idaIntermediateTex_[y-mod][x+xmod]), &(idaTexOut_[y][x]));
359  break;
360  }
361  if (GetSummedValue_(&(idaIntermediateTex_[y-mod][x])) != 0) {
362  SetValue_(&(idaIntermediateTex_[y-mod][x]), &(idaTexOut_[y][x]));
363  break;
364  }
365  if (GetSummedValue_(&(idaIntermediateTex_[y-mod][x-xmod])) != 0) {
366  SetValue_(&(idaIntermediateTex_[y-mod][x-xmod]), &(idaTexOut_[y][x]));
367  break;
368  }
369  }
370  } else {
371  SetValue_(&(idaIntermediateTex_[y][x]), &(idaTexOut_[y][x]));
372  }
373  }
374  }
375  }
376 
377 
378  if(wrapAround){
379  if (dTexChannels_ == 1) {
380  for (unsigned int y=boundMinWrap_[1]+fillAreaWindowSize_;
381  y<boundMaxWrap_[1]-fillAreaWindowSize_;y++) {
382  for (unsigned int x=boundMinWrap_[0]+fillAreaWindowSize_;
383  x<boundMaxWrap_[0]-fillAreaWindowSize_;x++) {
384  if (idaIntermediate_[y][x] == 0) {
385  for (unsigned int mod=1;mod<fillAreaWindowSize_;mod++) {
386  if (idaIntermediateTex_[y][x+mod] != 0) {
387  idaTexOut_[y][x] = idaIntermediateTex_[y][x+mod];
388  break;
389  }
390  if (idaIntermediateTex_[y][x-mod] != 0) {
391  idaTexOut_[y][x] = idaIntermediateTex_[y][x-mod];
392  break;
393  }
394  if (idaIntermediateTex_[y+mod][x+mod] != 0) {
395  idaTexOut_[y][x] = idaIntermediateTex_[y+mod][x+mod];
396  break;
397  }
398  if (idaIntermediateTex_[y+mod][x] != 0) {
399  idaTexOut_[y][x] = idaIntermediateTex_[y+mod][x];
400  break;
401  }
402  if (idaIntermediateTex_[y+mod][x-mod] != 0) {
403  idaTexOut_[y][x] = idaIntermediateTex_[y+mod][x-mod];
404  break;
405  }
406  if (idaIntermediateTex_[y-mod][x+mod] != 0) {
407  idaTexOut_[y][x] = idaIntermediateTex_[y-mod][x+mod];
408  break;
409  }
410  if (idaIntermediateTex_[y-mod][x] != 0) {
411  idaTexOut_[y][x] = idaIntermediateTex_[y-mod][x];
412  break;
413  }
414  if (idaIntermediateTex_[y-mod][x-mod] != 0) {
415  idaTexOut_[y][x] = idaIntermediateTex_[y-mod][x-mod];
416  break;
417  }
418  }
419  } else {
420  idaTexOut_[y][x] = idaIntermediateTex_[y][x];
421  }
422  }
423  }
424  } else {
425  for (unsigned int y=boundMinWrap_[1]+fillAreaWindowSize_;
426  y<boundMaxWrap_[1]-fillAreaWindowSize_;y++) {
427  for (unsigned int x=((int)boundMinWrap_[0]+fillAreaWindowSize_)*dTexChannels_;
428  x<((int)boundMaxWrap_[0]-fillAreaWindowSize_)*dTexChannels_;
429  x+=dTexChannels_) {
430  unsigned int val = 0;
431  val = GetSummedValue_(&(idaIntermediateTex_[y][x]));
432  if (val == 0) {
433  for (unsigned int mod=1;mod<fillAreaWindowSize_;mod++) {
434  unsigned int xmod = mod * dTexChannels_;
435  if (GetSummedValue_(&(idaIntermediateTex_[y][x+xmod])) != 0) {
436  SetValue_(&(idaIntermediateTex_[y][x+xmod]), &(idaTexOut_[y][x]));
437  break;
438  }
439  if (GetSummedValue_(&(idaIntermediateTex_[y][x-xmod])) != 0) {
440  SetValue_(&(idaIntermediateTex_[y][x-xmod]), &(idaTexOut_[y][x]));
441  break;
442  }
443  if (GetSummedValue_(&(idaIntermediateTex_[y+mod][x+xmod])) != 0) {
444  SetValue_(&(idaIntermediateTex_[y+mod][x+xmod]), &(idaTexOut_[y][x]));
445  break;
446  }
447  if (GetSummedValue_(&(idaIntermediateTex_[y+mod][x])) != 0) {
448  SetValue_(&(idaIntermediateTex_[y+mod][x]), &(idaTexOut_[y][x]));
449  break;
450  }
451  if (GetSummedValue_(&(idaIntermediateTex_[y+mod][x-xmod])) != 0) {
452  SetValue_(&(idaIntermediateTex_[y+mod][x-xmod]), &(idaTexOut_[y][x]));
453  break;
454  }
455  if (GetSummedValue_(&(idaIntermediateTex_[y-mod][x+xmod])) != 0) {
456  SetValue_(&(idaIntermediateTex_[y-mod][x+xmod]), &(idaTexOut_[y][x]));
457  break;
458  }
459  if (GetSummedValue_(&(idaIntermediateTex_[y-mod][x])) != 0) {
460  SetValue_(&(idaIntermediateTex_[y-mod][x]), &(idaTexOut_[y][x]));
461  break;
462  }
463  if (GetSummedValue_(&(idaIntermediateTex_[y-mod][x-xmod])) != 0) {
464  SetValue_(&(idaIntermediateTex_[y-mod][x-xmod]), &(idaTexOut_[y][x]));
465  break;
466  }
467  }
468  } else {
469  SetValue_(&(idaIntermediateTex_[y][x]), &(idaTexOut_[y][x]));
470  }
471  }
472  }
473  }
474  }
475 
476  }
477 
478  return 0;
479 }
480 
481 template <class InputStorageType, class OutputStorageType>
483 GetSummedValue_(const OutputStorageType* pixel) {
484  unsigned int ret=0;
485  for (unsigned int i=0;i<dTexChannels_;i++) {
486  ret+=pixel[i];
487  }
488  return ret;
489 }
490 
491 template <class InputStorageType, class OutputStorageType>
493 SetValue_(const OutputStorageType* in, OutputStorageType* out) {
494  for (unsigned int i=0;i<dTexChannels_;i++) {
495  out[i]=in[i];
496  }
497 }
498 
499 namespace BIAS{
504 }
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
void GetCorners(unsigned &UpperLeftX, unsigned &UpperLeftY, unsigned &LowerRightX, unsigned &LowerRightY) const
Return the region of interest, by saving the coordinates within the variables defined by the paramete...
Definition: ROI.hh:443
bool IsEmpty() const
check if ImageData_ points to allocated image buffer or not
Definition: ImageBase.hh:245
HomgPoint2D & Homogenize()
homogenize class data member elements to W==1 by divison by W
Definition: HomgPoint2D.hh:215
ROI * GetROI()
Returns a pointer to the roi object.
Definition: ImageBase.hh:615
void FillImageWithConstValue(StorageType Value)
fill grey images
Definition: Image.cpp:456
class HomgPoint3D describes a point with 3 degrees of freedom in projective coordinates.
Definition: HomgPoint3D.hh:61
int Map(const BIAS::Image< InputStorageType > *in, BIAS::Image< OutputStorageType > &out, const BIAS::Image< InputStorageType > *texin, BIAS::Image< OutputStorageType > &texout)
void Init(unsigned int Width, unsigned int Height, unsigned int channels=1, enum EStorageType storageType=ST_unsignedchar, const bool interleaved=true)
calls Init from ImageBase storageType is ignored, just dummy argument
Definition: Image.cpp:421
BIAS::Image< OutputStorageType > intermediateTex_
ForwardMappingNearestNeighbour< InputStorageType, OutputStorageType > & operator=(const ForwardMappingNearestNeighbour< InputStorageType, OutputStorageType > &src)
class BIASGeometryBase_EXPORT HomgPoint3D
BIAS::Image< OutputStorageType > intermediate_
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153