Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
CylindricDepthPanorama.cpp
1 #include <Image/CylindricDepthPanorama.hh>
2 #include <Base/Image/ImageConvert.hh>
3 #include <Base/Image/ImageIO.hh>
4 #include <Utils/ThreeDOut.hh>
5 #include <Image/ForwardMappingNearestNeighbour.hh>
6 #include <Base/Common/FileHandling.hh>
7 
8 using namespace BIAS;
9 using namespace std;
10 
11 static int imageCount=0;
12 
15  inited_ = false;
16  fillArea_ = 10;
17  bCostImageCreated_=false;
18 }
19 
20 /** Constructor */
22 CylindricDepthPanorama(const BIAS::Projection& initialProjection,
23  unsigned int channels)
24 {
25  inited_ = false;
26  fillArea_ = 10;
27  bCostImageCreated_=false;
28  Init(initialProjection,channels);
29 }
30 
33  unsigned int channels)
34 {
35  inited_ = false;
36  fillArea_ = 10;
37  bCostImageCreated_=false;
38  Init(iP,channels);
39 }
40 
43  unsigned int channels)
44 {
45  Projection p(iP);
46  return Init(p,channels);
47 }
48 
50 Init(const Projection& iP, unsigned int channels){
51  if((dynamic_cast<const ProjectionParametersCylindric*>(iP.GetParameters()))== NULL){
52  BIASERR("Not a cylindric projection.");
53  return -1;
54  }
55 
56  bTextureFilled_ = false;
57  bFirstPoseSet_ = false;
58  dTexChannels_ = channels;
59  initialProjection_ = iP;
60  pCylinderProj_ = (ProjectionParametersCylindric*)(initialProjection_.GetParameters());
61  pCylinderProj_->GetImageSize(panoramaWidth_,panoramaHeight_);
62 
63  panorama_.Init(panoramaWidth_,panoramaHeight_,1);
64  panoramaHitCount_.Init(panoramaWidth_,panoramaHeight_,1);
65  panoramaHitCount_.FillImageWithConstValue(0.0);
66  panoramaTexture_.Init(panoramaWidth_,panoramaHeight_,dTexChannels_);
67 
68  initialProjection_.GetParameters()->SetPose(iP.GetParameters()->GetPose());
69  pCylinderProj_->SetPose(iP.GetParameters()->GetPose());
70  bFirstPoseSet_ = true;
71  inited_= true;
72 
73  return 0;
74 }
75 
76 /** Destructor */
78 }
79 
81 SetFillArea(int area){
82  fillArea_ = area;
83 }
84 
87  BIAS::Projection & p,
89  bool useProjection){
90 
91  int ret =0;
92  if(!bFirstPoseSet_){
93  //contruct cylindrical projection
94  initialProjection_ = BIAS::Projection(p);
95  pCylinderProj_->SetQC(initialProjection_.GetQ(),initialProjection_.GetC());
96  bFirstPoseSet_ = true;
97  }
98 
99  if(!bCostImageCreated_){
100  float w=(float)depthMap.GetWidth();
101  float h=(float)depthMap.GetHeight();
102  float wh =(float)(w/2.0);
103  float hh =(float)(h/2.0);
104 
105  costIm_.Init((unsigned)rint(w),(unsigned)rint(h),3);
106  float ** ida = costIm_.GetImageDataArray();
107  double radius=0.0;
108  double maxradius = sqrt((wh)*(wh) + (hh)*(hh));
109 
110  for(unsigned x=0;x<(unsigned)w;x++){
111  for(unsigned y=0;y<(unsigned)h;y++){
112  radius=sqrt((x-wh)*(x-wh) + (y-hh)*(y-hh));
113 
114  if(radius <=0) radius=1e-10;
115  ida[y][x*3]= float((maxradius-radius)/maxradius)*255.0f;
116  ida[y][x*3+1]= float((maxradius-radius)/maxradius)*255.0f;
117  ida[y][x*3+2]= float((maxradius-radius)/maxradius)*255.0f;
118  }
119  }
120  bCostImageCreated_=true;
121  }
122 
124  Projection pDest(*pCylinderProj_);
125  BIAS::Image<float> textureImage;
126  BIAS::Image<float> tmpTex,tmpCost;
127  stringstream file,file1,file2;//file3;
128  //forward map images to cylinder
129  fm.SetSourceCam(p);
130  fm.SetSinkCam(pDest,3);
131  fm.SetFillAreaWindowSize(fillArea_);
132  BIAS::ImageConvert::ConvertST(*texture,textureImage,ImageBase::ST_float);
133  fm.Map(&depthMap,destDepth_,&textureImage,tmpTex);
135 
136  fm.Map(&depthMap,destDepth_,&costIm_,tmpCost);
137 
138  file<<"TexturePanorama-"<<FileHandling::LeadingZeroString(imageCount,5)
139  <<".mip";
140  file1<<"DepthPanorama-"<<FileHandling::LeadingZeroString(imageCount,5)
141  <<".mip";
142  file2<<"CostPanorama-"<<FileHandling::LeadingZeroString(imageCount,5)
143  <<".mip";
144  // file3<<"Cost-"<<FileHandling::LeadingZeroString(imageCount,5)
145  // <<".mip";
146  //BIAS::ImageIO::Save(file.str(),destTex_);
147  //BIAS::ImageIO::Save(file1.str(),destDepth_);
148  //BIAS::ImageIO::Save(file2.str(),tmpCost);
149  BIAS::ImageIO::Save(file.str(),destTex_);
150  BIAS::ImageIO::Save(file1.str(),destDepth_);
151  BIAS::ImageIO::Save(file2.str(),tmpCost);
152  // BIAS::ImageIO::Save(file3.str(),costIm_);
153 
154  float **ida = destDepth_.GetImageDataArray();
155  unsigned char **idaDestTex = destTex_.GetImageDataArray();
156  float **idaP = panorama_.GetImageDataArray();
157  float **idaPHC = panoramaHitCount_.GetImageDataArray();
158  unsigned char** idaTex = panoramaTexture_.GetImageDataArray();
159 
160  int width = destDepth_.GetWidth();
161  int height = destDepth_.GetHeight();
162 
163  float depthValue=0.0;
164  BIAS::HomgPoint3D point3D;
165  BIAS::HomgPoint2D point2D,cylPoint;
166 
167  unsigned channels = destTex_.GetChannelCount();
168 
169  if (!useProjection) {
170  for(int x=0;x<width;x++){
171  for(int y=0;y<height;y++){
172  depthValue = ida[y][x];
173  if (depthValue > 0.0) {
174  //fill texture panorama with values
175  if(texture != NULL){
176  for (unsigned int i=0;i<channels;i++) {
177  unsigned char val = idaDestTex[y][x*channels+i];
178  if (val != 0)
179  idaTex[y][x*channels+i] = val;
180 
181  }
182  bTextureFilled_ = true;
183  }
184  if(idaPHC[y][x] == 0.0){
185  idaP[y][x]=depthValue;
186  idaPHC[y][x]=1.0;
187  }
188  else{
189  idaP[y][x]=
190  (idaP[y][x] * idaPHC[y][x]+depthValue)/(idaPHC[y][x]+1);
191  idaPHC[y][x]+=1.0;
192  }
193  }
194  }
195  }
196  } else {
197  unsigned int x1,y1;
198  for(int x=0;x<width;x++){
199  for(int y=0;y<height;y++){
200  point2D[0]=x;
201  point2D[1]=y;
202  point2D[2]=1;
203  depthValue = ida[y][x];
204  if (depthValue != 0.0) {
205  // Unproject to a 3Dpoint
206  point3D = p.UnProjectToPoint(point2D,depthValue);
207  cylPoint = pCylinderProj_->Project(point3D);
208  cylPoint.Homogenize();
209  x1 = (unsigned int)cylPoint[0];
210  y1 = (unsigned int)cylPoint[1];
211 
212  // cout<<"3DPoint: "<<point3D<<" Cylindercoords: "<<cylPoint<<endl;
213 
214  if(x1>=0.0 && x1<panoramaWidth_ &&
215  y1>=0.0 && y1<panoramaHeight_ ) {
216  //fill texture panorama with values
217  if(texture != NULL){
218  for (unsigned int c=0;c<dTexChannels_;c++)
219  idaTex[y1][x1*dTexChannels_+c] = texture->GetImageDataArray()[y][x*dTexChannels_+c];
220  bTextureFilled_ = true;
221  }
222  if(idaPHC[y1][x1] == 0.0){
223  idaP[y1][x1]=depthValue;
224  idaPHC[y1][x1]=1.0;
225  }
226  else{
227  idaP[y1][x1]=
228  (idaP[y1][x1] * idaPHC[y1][x1]+depthValue)/(idaPHC[y1][x1]+1);
229  idaPHC[y1][x1]+=1.0;
230  }
231  }
232  }
233  }
234  }
235  }
236 
237  imageCount++;
238  return ret;
239 }
240 
243  BIAS::Image<unsigned char> &texture){
244  if(!inited_) return -1;
245  image = destDepth_;
246  texture = destTex_;
247  return 0;
248 }
249 
252  BIAS::Image<unsigned char> &texture){
253  if(!inited_) return -1;
254 
255  image = panorama_;
256  if(bTextureFilled_){
257  texture = panoramaTexture_;
258  }
259  else{
260  BIAS::ImageConvert::ConvertST(panorama_,texture,
262  texture.ScaleShiftBetween(0,255);
263  }
264  return 0;
265 }
266 
267 
270  if(!inited_) return -1;
271  int ret =-1;
273  Projection outProj (initialProjection_);
274  if(bTextureFilled_){
275 
276  int factor = 4;
277  outProj.Rescale((float)factor);
278  BIAS::Image<float> depthDownSampled_(panoramaWidth_ / factor, panoramaHeight_ / factor);
279  BIAS::Image<unsigned char> textureDownSampled_(panoramaWidth_ / factor, panoramaHeight_ / factor);
280  Rescale<float, float> pRescaleFilter_;
281  Rescale<unsigned char,unsigned char> pRescaleFilterUC_;
282  pRescaleFilter_.SetFactor((float)factor);
283  pRescaleFilter_.SetLowPassType(LPT_Gauss);
284  pRescaleFilter_.Filter(panorama_, depthDownSampled_);
285  pRescaleFilterUC_.SetFactor((float)factor);
286  pRescaleFilterUC_.SetLowPassType(LPT_Gauss);
287  pRescaleFilterUC_.Filter(panoramaTexture_, textureDownSampled_);
288 
289  int width = depthDownSampled_.GetWidth();
290  int height = depthDownSampled_.GetHeight();
291  // remove low depth values resulting from downsampling on 0.0 edges
292  BIAS::Image<float> filteredDepthMap_(width, height);
293  filteredDepthMap_.FillImageWithConstValue(0.0);
294 
295  // anti bubblegum: delete points of high variance
296  float **idaF = filteredDepthMap_.GetImageDataArray();
297  float **idaD = depthDownSampled_.GetImageDataArray();
298  for (int x=0;x<width;x++) {
299  for (int y=0;y<height;y++) {
300  if (idaD[y][x] < 10.0)
301  continue;
302  float minDepth_ = idaD[y][x];
303  float maxDepth_ = idaD[y][x];
304  for (int xw=x-1;xw<=x+1;xw+=1) {
305  for (int yw=y-1;yw<=y+1;yw+=1) {
306  if (xw >= 0 && yw >= 0 && xw < width && yw < height) {
307  if (idaD[yw][xw] > maxDepth_)
308  maxDepth_ = idaD[yw][xw];
309  if (idaD[yw][xw] < minDepth_)
310  minDepth_ = idaD[yw][xw];
311  }
312  }
313  }
314  if (maxDepth_ - minDepth_ < 1000.0)
315  idaF[y][x] = idaD[y][x];
316  }
317  }
318  depthDownSampled_ = filteredDepthMap_;
319 
320 #ifdef BIAS_DEBUG
321  BIAS::ImageIO::Save("Panorama_DepthMap.mip", panorama_);
322  BIAS::ImageIO::Save("Panorama_DepthMap_Downsampled.mip", depthDownSampled_);
323  BIAS::ImageIO::Save("Panorama_Texture.mip", panoramaTexture_);
324 #endif
325  mesh.GenerateDenseMesh(depthDownSampled_, outProj,textureDownSampled_,
326  0,0, depthDownSampled_.GetWidth() ,depthDownSampled_.GetHeight());
327  // mesh.GenerateDenseMesh(panorama_,outProj,panoramaTexture_,0,0,
328  // panoramaWidth_,panoramaHeight_);
329 
330  // mesh.GenerateSimplifiedMesh(panorama_,
331  // outProj,panoramaTexture_,0,0,
332  // panoramaWidth_,panoramaHeight_);
333 
334  return 0;
335 
336  }
337  else{
338  BIAS::ImageConvert::ConvertST(panorama_,tmpUC,
340  tmpUC.ScaleShiftBetween(0,255);
341  if(pCylinderProj_ != NULL){
342  BIAS::Projection proj(*pCylinderProj_);
343  mesh.GenerateDenseMesh(panorama_,proj,tmpUC,0,0,
344  panoramaWidth_,panoramaHeight_);
345  // mesh.GenerateSimplifiedMesh(panorama_,
346  // proj,panoramaTexture_,0,0,
347  // panoramaWidth_,panoramaHeight_);
348 
349  return 0;
350  }
351  else
352  return ret;
353 
354  }
355 }
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
int ScaleShiftBetween(double Min, double Max)
scales and shifts image so afterwards every pixel has a value between Min and Max ...
Definition: Image.cpp:1118
HomgPoint2D & Homogenize()
homogenize class data member elements to W==1 by divison by W
Definition: HomgPoint2D.hh:215
int ProcessCylindricProjection(BIAS::Image< float > &depthMap, BIAS::Projection &p, BIAS::Image< unsigned char > *texture=NULL, bool useProjection=true)
Call Process to update the measurement.
void SetLowPassType(int lpt)
Sets the lowpass filter by a lowpass filter type.
Definition: Rescale.cpp:2060
float image storage type
Definition: ImageBase.hh:118
int GetMappedImages(BIAS::Image< float > &image, BIAS::Image< unsigned char > &texture)
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
virtual void SetPose(const BIAS::Pose pose)
Set pose from pose object.
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
static int ConvertST(const BIAS::ImageBase &source, BIAS::ImageBase &dest, ImageBase::EStorageType targetST)
Function to convert the storage type of images e.g.
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
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)
Camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
Vector3< double > UnProjectToPoint(const HomgPoint2D &pos, double depth, unsigned int cam=0, bool IgnoreDistortion=false) const
calculates a 3D point in the global (not the rig) coordinate system, which belongs to the image posit...
Definition: Projection.cpp:349
int GetPanorama(BIAS::Image< float > &image, BIAS::Image< unsigned char > &texture)
(8bit) unsigned char image storage type
Definition: ImageBase.hh:112
int GetTriangleMesh(BIAS::TriangleMesh &mesh)
void SetSinkCam(const Projection &P, const unsigned int dTexChannels=1)
int Init(const Projection &iP, unsigned int channels)
virtual const BIAS::Pose & GetPose() const
Return complete pose object.
void SetFactor(double factor)
the downsampling factor
Definition: Rescale.hh:361
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153