Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
CylindricDepthTrackingPanorama.cpp
1 #include <Image/CylindricDepthTrackingPanorama.hh>
2 #include <Base/Image/ImageIO.hh>
3 #include <Image/MixtureOfGaussians.hh>
4 #include <Base/ImageUtils/ImageDraw.hh>
5 #include <Image/CylindricDepthPanorama.hh>
6 #include <Base/Common/FileHandling.hh>
7 
8 using namespace std;
9 
10 namespace BIAS
11 {
12 
13 CylindricDepthTrackingPanorama::
14 CylindricDepthTrackingPanorama(const Projection& initialProjection,
15  unsigned int channels,
16  float depthScale)
17 : CylindricDepthPanorama(initialProjection, channels) {
18  dTexChannels_ = channels;
19  fDepthScale_ = depthScale;
22  mog_ = new MixtureOfGaussians<float>(5, 3, 0.2f );
23  mog_->InitWeights(100, 20, 2.9f );
24  mog_->SetSmoothing(true);
25  bInited_ = false;
26 }
27 
29 {
30 }
31 
34  BIAS::Projection & p,
36 {
37  if(!bFirstPoseSet_){
39  SetPose(p.GetParameters()->GetPose());
40  //contruct cylindrical projection
41  //obsolete, this is a pointer to the above anyway
43  bFirstPoseSet_ = true;
44  }
45 
46  int ret = 0;
47  unsigned int width = depthMap.GetWidth();
48  unsigned int height = depthMap.GetHeight();
49 
50  //float depthValue=0.0; not used anywhere
51 
52  normalizedDepthMap_ = depthMap;
53 
54  float **ida = depthMap.GetImageDataArray();
55  float **idaN = normalizedDepthMap_.GetImageDataArray();
56 
57  //determine bounding box
58 
59  HomgPoint2D min, max;
60  min[0] = width; min[1] = height;
61  max[0] = 0; max[1] = 0;
62  bool found = false;
63  for(unsigned int y=0;y<height;y++){
64  for(unsigned int x=0;x<width;x++){
65  if (ida[y][x] != 0.0 && ida[y][x] != 1.0) {
66  min[1] = y;
67  min[0] = x;
68  found = true;
69  break;
70  }
71  }
72  if (found) break;
73  }
74 
75  found = false;
76  for(unsigned int y=height-1;y>min[1];y--){
77  for(unsigned int x=width-1;x>0;x--){
78  if (ida[y][x] != 0.0 && ida[y][x] != 1.0) {
79  max[1] = y;
80  max[0] = x;
81  found = true;
82  break;
83  }
84  }
85  if (found) break;
86  }
87 
88  for(unsigned int y=(unsigned int)min[1];y<(unsigned int)max[1];y++){
89  for(unsigned int x=(unsigned int)min[0];x>0;x--){
90  if (ida[y][x] != 0.0 && ida[y][x] != 1.0) {
91  min[0] = x;
92  } else {
93  break;
94  }
95  }
96  }
97 
98  for(unsigned int y=(unsigned int)min[1];y<(unsigned int)max[1];y++){
99  for(unsigned int x=(unsigned int)max[0];x<width;x++){
100  if (ida[y][x] != 0.0 && ida[y][x] != 1.0) {
101  max[0] = x;
102  } else {
103  break;
104  }
105  }
106  }
107 
108  // roi to 2/3 of image
109  // cut 1/6 of each side
110  unsigned int xdiff = (unsigned int)rint(max[0]-min[0]) / 6;
111  unsigned int ydiff = (unsigned int)rint(max[1]-min[1]) / 6;
112  // roi to 1/2 of image
113  // cut 1/4 of each side
114 /* unsigned int xdiff = (max[0]-min[0]) / 4;
115  unsigned int ydiff = (max[1]-min[1]) / 4;
116 */
117  min[0] += xdiff;
118  min[1] += ydiff;
119  max[0] -= xdiff;
120  max[1] -= ydiff;
121  for(unsigned int x=(unsigned int)min[0];x<(unsigned int)max[0];x++){
122  for(unsigned int y=(unsigned int)min[1];y<(unsigned int)max[1];y++){
123  if (ida[y][x] == 1.0) {
124  ida[y][x] = 0.0;
125  idaN[y][x] = 0.0;
126  continue;
127  }
128  ida[y][x] *= fDepthScale_;
129  }
130  }
131  cout<<"determined roi:"<<min[0]<<","<< min[1]<<","<< max[0]<<","<< max[1]<<endl;
132 
133  depthMap.SetROICorners((unsigned int)min[0], (unsigned int)min[1],
134  (unsigned int)max[0], (unsigned int)max[1]); // if (time_ != -1 && track_) {
135  normalizedDepthMap_.SetROICorners((unsigned int)min[0], (unsigned int)min[1],
136  (unsigned int)max[0],(unsigned int) max[1]);
137  ret = doTrack(depthMap, p, texture);
138 
139  // mog_->GetDifferenceImageWithVisuals(visualisation_);
140 /* DEBUG
141  static int n=0;
142  if (!visualisation_.IsEmpty())
143  ImageIO::Save("MOGVisu"+LeadingZeroString(n++,3)+".mip", visualisation_);
144 */
145  return ret;
146 }
147 
148 int CylindricDepthTrackingPanorama::LoadPanorama(const std::string filename) {
149  int ret = 0;
150  ret += ImageIO::Load(filename+"-TrackingPanoramaDepth.mip", panorama_);
151  ret += ImageIO::Load(filename+"-TrackingPanoramaTexture.mip", panoramaTexture_);
152  ret += ImageIO::Load(filename+"-TrackingPanoramaHitCount.mip", panoramaHitCount_);
153  cout << " LOADING PANORAMA" << endl;
154  for (int i=0;i<50;i++) {
155  // cout << "doone." << endl;
156  mog_->Apply(panorama_);
157  }
158  bTextureFilled_ = true;
159  return ret;
160 }
161 
162 int CylindricDepthTrackingPanorama::SavePanorama(const std::string filename) {
163  int ret = 0;
164  ret += ImageIO::Save(filename+"-TrackingPanoramaDepth.mip", panorama_);
165  ret += ImageIO::Save(filename+"-TrackingPanoramaTexture.mip", panoramaTexture_);
166  ret += ImageIO::Save(filename+"-TrackingPanoramaHitCount.mip", panoramaHitCount_);
167 // cout << "setting up motion detection (might take a while)" << endl;
168 // if (!bInited_) {
169 // for (int i=0;i<50;i++) {
170 // mog_->Apply(panorama_);
171 // }
172 // }
173 // cout << "setting up motion detection complete" << endl;
174  bInited_ = true;
175  return ret;
176 }
177 
180  int ret =-1;
182  if(bTextureFilled_) {
183  int factor = 4;
184  BIAS::Projection pRescaledProjection_(initialProjection_);
185  pRescaledProjection_.Rescale((float)factor);
186  BIAS::Image<float> depthDownSampled_(panoramaWidth_ / factor, panoramaHeight_ / factor);
187  Rescale<float, float> pRescaleFilter_;
188  pRescaleFilter_.SetFactor((float)factor);
189  pRescaleFilter_.SetLowPassType(LPT_Gauss);
190  pRescaleFilter_.Filter(panorama_, depthDownSampled_);
191  int width = depthDownSampled_.GetWidth();
192  int height = depthDownSampled_.GetHeight();
193  // remove low depth values resulting from downsampling on 0.0 edges
194  BIAS::Image<float> filteredDepthMap_(width, height);
195  filteredDepthMap_.FillImageWithConstValue(0.0);
196 
197  // anti bubblegum: delete points of high variance
198  float **idaF = filteredDepthMap_.GetImageDataArray();
199  float **idaD = depthDownSampled_.GetImageDataArray();
200  for (int x=0;x<width;x++) {
201  for (int y=0;y<height;y++) {
202  if (idaD[y][x] < 10.0)
203  continue;
204  float minDepth_ = idaD[y][x];
205  float maxDepth_ = idaD[y][x];
206  for (int xw=x-1;xw<=x+1;xw+=1) {
207  for (int yw=y-1;yw<=y+1;yw+=1) {
208  if (xw >= 0 && yw >= 0 && xw < width && yw < height) {
209  if (idaD[yw][xw] > maxDepth_)
210  maxDepth_ = idaD[yw][xw];
211  if (idaD[yw][xw] < minDepth_)
212  minDepth_ = idaD[yw][xw];
213  }
214  }
215  }
216  if (maxDepth_ - minDepth_ < 1000.0)
217  idaF[y][x] = idaD[y][x];
218  }
219  }
220  depthDownSampled_ = filteredDepthMap_;
221 
222  cout << initialProjection_ << endl;
223  cout << pRescaledProjection_ << endl;
224  BIAS::ImageIO::Save("Panorama_DepthMap.mip", panorama_);
225  BIAS::ImageIO::Save("Panorama_DepthMap_Downsampled.mip", depthDownSampled_);
226  BIAS::ImageIO::Save("Panorama_Texture.mip", panoramaTexture_);
227  mesh.GenerateDenseMesh(depthDownSampled_,pRescaledProjection_,
229  //pInitialProjection_->Rescale((float)1.0/float(factor));
230 
231  static int n=0;
233  return 0;
234  }
235  return ret;
236 }
237 
238 int CylindricDepthTrackingPanorama::
239 doPanorama(BIAS::Image<float> &depthMap,
240  BIAS::Projection & p,
242 {
243  int ret =0;
244  BIAS::Vector4<unsigned> tmpCorners;
245  depthMap.GetROICorners(tmpCorners[0],tmpCorners[1],tmpCorners[2],tmpCorners[3]);
246 
247  bb_.UL[0] = (unsigned)tmpCorners[0];
248  bb_.UL[1] = (unsigned)tmpCorners[1];
249  bb_.LR[0] = (unsigned)tmpCorners[2];
250  bb_.LR[1] = (unsigned)tmpCorners[3];
251 
252  cout << " DO PANORAMA" << endl;
253  float **ida = depthMap.GetImageDataArray();
254  float **idaP = panorama_.GetImageDataArray();
255  float **idaPHC = panoramaHitCount_.GetImageDataArray();
256  unsigned char ** idaTex = panoramaTexture_.GetImageDataArray();
257 
258  //unsigned int width = depthMap.GetWidth();
259  //unsigned int height = depthMap.GetHeight();
260 
261  float depthValue=0.0;
262 
263  for (unsigned int y=(unsigned)bb_.UL[1];y<(unsigned)bb_.LR[1]-1;y++) {
264  for (unsigned int x=(unsigned)bb_.UL[0];x<(unsigned)bb_.LR[0]-1;x++) {
265  depthValue = ida[y][x];
266  if (depthValue > 0.0) {
267  //fill texture panorama with values
268  if(texture != NULL){
269  for (unsigned int i=0;i<dTexChannels_;i++)
270  idaTex[y][x*dTexChannels_+i] = texture->GetImageDataArray()[y][x*dTexChannels_+i];
271  bTextureFilled_ = true;
272  }
273  if(idaPHC[y][x] == 0.0){
274  idaP[y][x]=depthValue;
275  idaPHC[y][x]=1.0;
276  }
277  else{
278  idaP[y][x]=
279  (idaP[y][x] * idaPHC[y][x]+depthValue)/(idaPHC[y][x]+1);
280  idaPHC[y][x]+=1.0;
281  }
282  }
283  }
284  }
285 
286  return ret;
287 }
288 
289 int CylindricDepthTrackingPanorama::
290 doTrack(BIAS::Image<float> &depthMap,
291  BIAS::Projection & p,
293 {
294  mog_->Apply(normalizedDepthMap_);
296  //mog_->GetLargestBoundingBox(bb);
297  //
298  cout << "TRACK!" << endl;
299  BIAS::Vector4<unsigned> tmpCorners;
300  depthMap.GetROICorners(tmpCorners[0],tmpCorners[1],tmpCorners[2],tmpCorners[3]);
301 
302  bb_.UL[0] = (unsigned)tmpCorners[0];
303  bb_.UL[1] = (unsigned)tmpCorners[1];
304  bb_.LR[0] = (unsigned)tmpCorners[2];
305  bb_.LR[1] = (unsigned)tmpCorners[3];
306 
307  float **ida = depthMap.GetImageDataArray();
308  unsigned char **idaT = texture->GetImageDataArray();
309  unsigned char **idaDif = difference_.GetImageDataArray();
310  float **idaNsDep = panoramaNonStatic_.GetImageDataArray();
311  unsigned char **idaNsTex = panoramaNonStaticTexture_.GetImageDataArray();
312  float **idaD = panorama_.GetImageDataArray();
313  unsigned char ** idaTex = panoramaTexture_.GetImageDataArray();
314  float **idaPHC = panoramaHitCount_.GetImageDataArray();
315 
316  for (unsigned int y=(unsigned)bb_.UL[1];y<(unsigned)bb_.LR[1]-1;y++) {
317  for (unsigned int x=(unsigned)bb_.UL[0];x<(unsigned)bb_.LR[0]-1;x++) {
318  float depthValue = ida[y][x];
319  if (idaD[y][x]==0) {
320  if (depthValue > 0.0) {
321  //fill texture panorama with values
322  if(texture != NULL){
323  for (unsigned int i=0;i<dTexChannels_;i++)
324  idaTex[y][x*dTexChannels_+i] = idaT[y][x*dTexChannels_+i];
325  bTextureFilled_ = true;
326  }
327  if(idaPHC[y][x] == 0.0){
328  idaD[y][x]=depthValue;
329  idaPHC[y][x]=1.0;
330  }
331  else{
332  idaD[y][x]=
333  (idaD[y][x] * idaPHC[y][x]+depthValue)/(idaPHC[y][x]+1);
334  idaPHC[y][x]+=1.0;
335  }
336  }
337  } else {
338  if (idaDif[y][x] > 64) {
339  if (abs(depthValue - idaD[y][x]) > 400.0) {
340  idaNsDep[y][x] = depthValue;
341  for (unsigned int i=0;i<dTexChannels_;i++)
342  idaNsTex[y][x*dTexChannels_+i] = idaT[y][x*dTexChannels_+i];
343  } else {
344  for (unsigned int i=0;i<dTexChannels_;i++) {
345  // idaTex[y][x*dTexChannels_+i] = (idaTex[y][x*dTexChannels_+i] + idaT[y][x*dTexChannels_+i]) / 2; // TODO
346  idaTex[y][x*dTexChannels_+i] = idaT[y][x*dTexChannels_+i];
347  idaNsTex[y][x*dTexChannels_+i] = 0;
348  }
349  idaNsDep[y][x] = 0;
350  idaD[y][x]=
351  (idaD[y][x] * idaPHC[y][x]+depthValue)/(idaPHC[y][x]+1);
352  idaPHC[y][x]+=1.0;
353 
354  }
355  }
356  else {
357  idaNsDep[y][x] = 0;
358  for (unsigned int i=0;i<dTexChannels_;i++)
359  idaNsTex[y][x*dTexChannels_+i] = 0;
360  idaD[y][x]=
361  (idaD[y][x] * idaPHC[y][x]+depthValue)/(idaPHC[y][x]+1);
362  idaPHC[y][x]+=1.0;
363  }
364  }
365  }
366  }
367  //texture = &panoramaNonStaticTexture_;
368 
369  return 0;
370 }
371 
372 
375  BIAS::Image<unsigned char> &texture){
376  int ret = CylindricDepthPanorama::GetPanorama(image, texture);
377 
378  unsigned char **idaT = texture.GetImageDataArray();
379  unsigned char **idaNsTex = panoramaNonStaticTexture_.GetImageDataArray();
380  float **idaNsDep = panoramaNonStatic_.GetImageDataArray();
381  BIAS::BIASBlob rectangle;
382  rectangle.UL[0] = 0;
383  rectangle.UL[1] = 0;
384  rectangle.LR[0] = 0;
385  rectangle.LR[1] = 0;
386  bool draw = false;
387  for (unsigned int y=(unsigned)bb_.UL[1];y<(unsigned)bb_.LR[1]-1;y++) {
388  for (unsigned int x=(unsigned)bb_.UL[0];x<(unsigned)bb_.LR[0]-1;x++) {
389  if (idaNsDep[y][x] != 0) {
390  if (dTexChannels_ == 3) {
391  idaT[y][x*dTexChannels_+0] = (unsigned char)(idaNsTex[y][x*dTexChannels_+0]*2);
392  idaT[y][x*dTexChannels_+1] = 0;
393  idaT[y][x*dTexChannels_+2] = idaNsTex[y][x*dTexChannels_+2];
394 
395  }
396 // for (unsigned int i=0;i<dTexChannels_;i++)
397  // idaT[y][x*dTexChannels_+i] = idaNsTex[y][x*dTexChannels_+i];
398  if (!draw) {
399  draw = true;
400  rectangle.UL[0] = x;
401  rectangle.UL[1] = y;
402  rectangle.LR[0] = x;
403  rectangle.LR[1] = y;
404  }
405  if (draw) {
406  if (x < rectangle.UL[0])
407  rectangle.UL[0] = x;
408  if (y < rectangle.UL[1])
409  rectangle.UL[1] = y;
410  if (x > rectangle.LR[0])
411  rectangle.LR[0] = x;
412  if (y > rectangle.LR[1])
413  rectangle.LR[1] = y;
414  }
415  }
416  }
417  }
418 // if (draw) {
419 // ImageDraw<unsigned char>::RectangleCorners(texture, rectangle.UL.x,
420 // rectangle.UL.y, rectangle.LR.x, rectangle.LR.y);
421 // }
422 // if (time_ == -1 || !track_) {
423  return ret;
424 // } else {
425 // image = panorama_;
426 // image.ScaleShiftBetween(0,255);
427 // texture = panoramaNonStaticTexture_;
428 // DEBUG
429 // static int n=0;
430 // ImageIO::Save("MOGTexture"+LeadingZeroString(n,3)+".mip", panoramaNonStaticTexture_);
431 // ImageIO::Save("MOGDepth"+LeadingZeroString(n++,3)+".mip", panoramaNonStatic_);
432 
433 // return ret;
434 // }
435 }
436 
437 } // end namespace BIAS
int GenerateDenseMesh(const BIAS::Image< float > &DenseDepthMap, const BIAS::Image< unsigned char > &Texture)
Calculate a triangle mesh from dense depth map without PMatrix.
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
BIAS::ProjectionParametersCylindric * pCylinderProj_
void SetSmoothing(const bool smooth)
BIAS::MixtureOfGaussians< float > * mog_
void SetLowPassType(int lpt)
Sets the lowpass filter by a lowpass filter type.
Definition: Rescale.cpp:2060
BIAS::Vector2< double > LR
void Rescale(float ratio, unsigned int cam=0)
adapt internal params to resampled image
Definition: Projection.hh:471
Down-, Upsampling routines and Resize.
Definition: Rescale.hh:71
unsigned int GetWidth() const
Definition: ImageBase.hh:312
int GetPanorama(BIAS::Image< float > &image, BIAS::Image< unsigned char > &texture)
int InitWeights(const int maxWeight, const int minWeight, const float errorMargin)
init weights for background/object distinction
void GetROICorners(unsigned int &UpperLeftX, unsigned int &UpperLeftY, unsigned int &LowerRightX, unsigned int &LowerRightY) const
access region of interest rectangle JW
Definition: ImageBase.cpp:1067
virtual void SetPose(const BIAS::Pose pose)
Set pose from pose object.
BIAS::Image< unsigned char > panoramaTexture_
class Vector4 contains a Vector of dim.
Definition: Vector4.hh:65
Helper class to store blob corners.
BIAS::Image< float > panoramaHitCount_
const ProjectionParametersBase * GetParameters(unsigned int cam=0) const
const parameter access function
Definition: Projection.hh:194
This class hides the underlying projection model, like projection matrix, spherical camera...
Definition: Projection.hh:70
create and represent cylindric depth panorama
BIAS::Image< unsigned char > panoramaNonStaticTexture_
Create and represent a 3D triangle mesh.
Definition: TriangleMesh.hh:84
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
scales the src to dst using the downsampling factor from SetFactor()
Definition: Rescale.cpp:89
static std::string LeadingZeroString(const int &n, const unsigned int &digits=DEFAULT_LEADING_ZEROS)
Create a string with leading zeroes from number.
unsigned int GetHeight() const
Definition: ImageBase.hh:319
void FillImageWithConstValue(StorageType Value)
fill grey images
Definition: Image.cpp:456
static int Save(const std::string &filename, const ImageBase &img, const enum TFileFormat FileFormat=FF_auto, const bool sync=BIAS_DEFAULT_SYNC, const int c_jpeg_quality=BIAS_DEFAULT_IMAGE_QUALITY, const bool forceNewID=BIAS_DEFAULT_FORCENEWID, const bool &writeMetaData=true)
Export image as file using extrnal libs.
Definition: ImageIO.cpp:725
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::Vector2< double > UL
int GetDifferenceImage(BIAS::Image< unsigned char > &diff)
get image of detected scene changes.
static int Load(const std::string &FileName, ImageBase &img)
first tries a call to Read MIP image and if that fails, tries to Import Image with all other availabl...
Definition: ImageIO.cpp:141
int GetPanorama(BIAS::Image< float > &image, BIAS::Image< unsigned char > &texture)
int ProcessCylindricProjection(BIAS::Image< float > &depthMap, BIAS::Projection &p, BIAS::Image< unsigned char > *texture=NULL)
Call Process to update the measurement.
int SetROICorners(unsigned int UpperLeftX, unsigned int UpperLeftY, unsigned int LowerRightX, unsigned int LowerRightY)
Definition: ImageBase.cpp:1048
virtual const BIAS::Pose & GetPose() const
Return complete pose object.
int Apply(BIAS::Image< StorageType > &in)
update calculations with new image the image has to be formatted correctly, e.g for MoG on HSL images...
void SetFactor(double factor)
the downsampling factor
Definition: Rescale.hh:361
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153