Basic Image AlgorithmS Library  2.8.0
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
biasdepthwarp.cpp
1 
2 /*
3  This file is part of the BIAS library (Basic ImageAlgorithmS).
4 
5  Copyright (C) 2003-2009 (see file CONTACT for details)
6  Multimediale Systeme der Informationsverarbeitung
7  Institut fuer Informatik
8  Christian-Albrechts-Universitaet Kiel
9 
10 
11  BIAS is free software; you can redistribute it and/or modify
12  it under the terms of the GNU Lesser General Public License as published by
13  the Free Software Foundation; either version 2.1 of the License, or
14  (at your option) any later version.
15 
16  BIAS is distributed in the hope that it will be useful,
17  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  GNU Lesser General Public License for more details.
20 
21  You should have received a copy of the GNU Lesser General Public License
22  along with BIAS; if not, write to the Free Software
23  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  */
25 
26 #include <bias_config.h>
27 #include <Base/Image/Image.hh>
28 #include <Base/Image/ImageConvert.hh>
29 #include <Image/Camera.hh>
30 #include <Image/PMDImageProc.hh>
31 #include <Utils/Param.hh>
32 #include <Utils/IOUtils.hh>
33 #include <Base/Image/ImageIO.hh>
34 #include <Filter/Median.hh>
35 #include <Filter/Bilateral.hh>
36 #ifdef BIAS_HAVE_OPENGL
37 #include <OpenGLFramework/RenderingContext/glfPBuffer.hh>
38 #include <OpenGLFramework/SpecializedBatches/PMDWarp.hh>
39 #include <OpenGLFramework/Base/glfException.hh>
40 #include <OpenGLFramework/Base/glfFramebufferObject.hh>
41 #include <Gui/biasgl.h>
42 #endif
43 
44 using namespace std;
45 using namespace BIAS;
46 
47 /**
48  @file
49  @relates PMDWarp,glfFramebufferObject,glfPBuffer
50  @brief Example for using the PMDWarp class. This example creates a glfPBuffer
51  and warps a depth map into the perspective of another camera using meshing on the GPU
52  see biasdepthwarp.cpp
53  @ingroup g_tools
54  @ingroup g_openglframework
55  @author Bogomil Bartzcak
56  @date 2009
57 */
58 int main(int argc, char* argv[])
59 {
60  Param params(true);
61 
62  string* tofImageName =
63  params.AddParamString("tofImage", "image of tof camera", "", 'i');
64  string* ampImageName =
65  params.AddParamString("ampImage", "amplitude image of tof camera [optional]", "", 'a');
66 
67  string* targetImageName =
68  params.AddParamString("targetImage", "target image name", "result.mip", 'o');
69 
70  string* sourceProjName =
71  params.AddParamString("sourceProj", "projection with params of source tof cam, ATTENTION Distortion parameters are NOT IGNORED", "", 's');
72  string* targetProjName =
73  params.AddParamString("targetProj", "projection with params of target perspective cam, ATTENTION Distortion parameters are IGNORED", "", 't');
74  bool* translateToDepth =
75  params.AddParamBool("depth", "output depth instead of z image", false, 'd');
76  bool* bUndist =
77  params.AddParamBool("undistort", "undistort depth", false, 'u');
78  bool* bBilateral =
79  params.AddParamBool("filterBilateral", "filter image with bilateral filter", false, 'b');
80  bool* bMedian =
81  params.AddParamBool("filterMedian", "filter image with median filter", false, 'm');
82  bool* bSimple =
83  params.AddParamBool("simpleProjectAndFill", "use simple point projection and dilation instead of GPU warping", false, 'S');
84 
85  int *kernelsize = params.AddParamInt("kernelsize","optional kernelsize for dilation in simple projection case",10,1,1000,'k');
86  double* zNear = params.AddParamDouble("zNear","",0.1);
87  double* zFar = params.AddParamDouble("zFar","",10000);
88 
89  if(!IOUtils::ParseCommandLineEvalHelp(params, argc, argv) )
90  return 0;
91 
92  //members
93  Image<float> tofImage,targetImage,ampImage;
94  Image<unsigned char> texImage;
95  Image<float> resultImg;
96 
97  Projection tofProj, targetProj;
98  ProjectionParametersPerspectiveDepth* tofParam = NULL;
99  ProjectionParametersPerspective* tofParamPersp = NULL;
100  ProjectionParametersPerspective* targetParam = NULL;
101 
102  bool tofIsPersp = false;
103  bool hasTexture = false;
104  //load tof depth image
105  if(BIAS::ImageIO::Load(*tofImageName,tofImage)!=0) {
106  BIASERR("Could not load tof image:"<<*tofImageName);
107  return -1;
108  }
109 
110  // scale depth image
111  // if(tofImage.GetChannelCount() != 1)
112  // ImageConvert::IP_ToGrey(tofImage);
113  //
114  // tofImage *=1000;
115 
116  //load tof amp image
117  if(*ampImageName != ""){
118  if(BIAS::ImageIO::Load(*ampImageName,ampImage)!=0) {
119  BIASERR("Could not load tof image:"<<*ampImageName);
120  return -1;
121  }
122  else{
123  BIAS::ImageConvert::ConvertST(ampImage,texImage,ImageBase::ST_unsignedchar);
124  hasTexture=true;
125  }
126  }
127 
128  //load projections
129  if(tofProj.Load(*sourceProjName)!=0) {
130  BIASERR("Could not load source tof projection: "<<*sourceProjName);
131  return -1;
132  }
133  if(targetProj.Load(*targetProjName)!=0) {
134  BIASERR("Could not load target tof projection:"<<*targetProjName);
135  return -1;
136  }
137 
138 
139  //source tof parameters
140  if(!IOUtils::CheckType<ProjectionParametersPerspectiveDepth,
141  ProjectionParametersBase>(tofProj.GetParameters(), tofParam)) {
142  if(!IOUtils::CheckType<ProjectionParametersPerspective,
143  ProjectionParametersBase>(tofProj.GetParameters(), tofParamPersp)) {
144  BIASERR("wrong type dynamic cast failed!");
145  return -1;
146  } else {
147  tofIsPersp = true;
148  }
149  }
150  //target parameters
151  if(!IOUtils::CheckType<ProjectionParametersPerspective,
152  ProjectionParametersBase>(targetProj.GetParameters(), targetParam)) {
153  BIASERR("wrong type dynamic cast failed!");
154  return -1;
155  }
156 
157 // cout<<"Deleting high variance values\n";
158 // PMDImageProc::DeleteHighVarianceValues(tofImage,400,1);
159 
160  //fill holes from range ambiguity wrap
161  cout<<"Setting all values below 500 to 10 000\n";
162  tofImage.BelowThresholdToValue(500,10000);
163 
164  //undistort depth image
165  if (*bUndist){
166  cout<<"Undistorting depth image\n";
167  tofParam->UnDistortDepthMapIP(tofImage);
168  }
169 
170  //bilateral or mean filter image
171  if (*bBilateral) {
172  cout<<"Bilateral filtering image\n";
173  Image<float> filterTmp;
174  // take bilateral filter...
175  Bilateral<float, float> bilateral;
176  // set parameters
177  bilateral.SetSigma(0.7);
178  bilateral.SetBilateralSigma(150.0);
179  bilateral.SetSize(3, 3);
180  bilateral.SetIgnoreValue(0.0);
181 
182  for (unsigned int i = 0; i < 5; i++) {
183  if(*ampImageName != "")
184  bilateral.Filter(tofImage, ampImage, filterTmp);
185  else
186  bilateral.Filter(tofImage, filterTmp);
187  }
188  }
189 
190  if(*bMedian) {
191  cout<<"Median filtering image\n";
192  Image<float> filterTmp;
193  Median<float, float> median;
194  median.SetSize(3, 3);
195  median.Filter(tofImage, filterTmp);
196  tofImage = filterTmp;
197  }
198 
199 
200  //delete if out of range zNear , zFar
201  float **ida = tofImage.GetImageDataArray();
202  for (unsigned int y=0; y<tofImage.GetHeight(); y++) {
203  for (unsigned int x=0; x<tofImage.GetWidth(); x++) {
204  if (ida[y][x] < *zNear || ida[y][x] > *zFar) {
205  ida[y][x] = 0;
206  }
207  }
208  }
209 
210 
211 
212  //either use simple point projection and hole filling with dilation (bSimple)
213  //or use PMDWarp with warping on GPU (else case)
214  if(*bSimple){
215  PMDImageProc::FitDepthTo2DImage(tofImage,targetProj,tofProj,*kernelsize);
216  resultImg = tofImage;
217  }
218  else
219  {
220 #ifdef BIAS_HAVE_OPENGL
221  //calculate relative params
222  Pose relativePose;
223  if(!tofIsPersp) {
224  relativePose.BecomeRelativeTransform(targetParam->GetPose(), tofParam->GetPose());
225  } else {
226  relativePose.BecomeRelativeTransform(targetParam->GetPose(), tofParamPersp->GetPose());
227  }
228  targetParam->SetPose(relativePose);
229 
230  unsigned int width, height;
231  targetParam->GetImageSize(width, height);
232 
233  glfPBuffer pbuffer;
234  PMDWarp gpuDepthWarp;
235  try {
236 
238  cfg.width = 5;
239  cfg.height = 5;
240  cfg.doubleBuffer = 0;
241  cfg.redSize = 8;
242  cfg.greenSize = 8;
243  cfg.blueSize = 8;
244  cfg.alphaSize = 0;
245  cfg.depthSize = 24;
246  cfg.stencilSize = 0;
247 
248  pbuffer.Init(cfg);
249 
250  glfTexture2D resultTexture;
251  resultTexture.Create();
252  resultTexture.SetMagFilter(GL_NEAREST);
253  resultTexture.SetMinFilter(GL_NEAREST);
254  resultTexture.SetWrapS(GL_CLAMP);
255  resultTexture.SetWrapT(GL_CLAMP);
256  resultTexture.Allocate(width, height, GL_RGB);
257 
258  glfTexture2D depthTexture;
259  depthTexture.Create();
260  depthTexture.SetMagFilter(GL_NEAREST);
261  depthTexture.SetMinFilter(GL_NEAREST);
262  depthTexture.SetWrapS(GL_CLAMP);
263  depthTexture.SetWrapT(GL_CLAMP);
264  depthTexture.Allocate(width, height, GL_DEPTH_COMPONENT);
265 
266  glfTexture2D dispTexture;
267  dispTexture.Create();
268  dispTexture.SetMagFilter(GL_NEAREST);
269  dispTexture.SetMinFilter(GL_NEAREST);
270  dispTexture.SetWrapS(GL_CLAMP);
271  dispTexture.SetWrapT(GL_CLAMP);
272  dispTexture.Allocate(width, height, GL_LUMINANCE32F_ARB);
273 
275  fbo.Create();
276  fbo.AttachTexture(resultTexture, GL_COLOR_ATTACHMENT0_EXT);
277  fbo.AttachTexture(dispTexture, GL_COLOR_ATTACHMENT1_EXT);
278  fbo.AttachTexture(depthTexture, GL_DEPTH_ATTACHMENT_EXT);
279  fbo.CheckComplete();
280  vector<GLenum> drawbuffers(2);
281  drawbuffers[0] = GL_COLOR_ATTACHMENT0_EXT;
282  drawbuffers[1] = GL_COLOR_ATTACHMENT1_EXT;
283  fbo.SetDrawBuffers(drawbuffers);
284 
285  bool useDists = true;
286  if(!tofIsPersp) {
287  gpuDepthWarp.Init(*tofParam, useDists);
288  } else {
289  gpuDepthWarp.Init(*tofParamPersp, useDists);
290  }
291 
292  gpuDepthWarp.SetRenderTarget(&fbo);
293  gpuDepthWarp.SetTargetCameraParameters(*targetParam, *zNear, *zFar);
294 
295  if(hasTexture){
296  if(tofParam != NULL)
297  gpuDepthWarp.UseProjectiveTexturing(*tofParam);
298  else if(tofParamPersp != NULL)
299  gpuDepthWarp.UseProjectiveTexturing(*tofParamPersp);
300  else return -1;
301  gpuDepthWarp.UploadProjectiveTexture(texImage);
302  }
303  gpuDepthWarp.UploadDepthMap(tofImage);
304  gpuDepthWarp.Draw();
305 
306  // Camera<float> dispImg;
307  // dispTexture.CopyToImage(dispImg);
308  // dispImg.Flip();
309  // ImageIO::Save("disparity.mip",dispImg);
310 
311  depthTexture.CopyToImage(resultImg);
312  resultImg.Flip();
313 
314  if (*translateToDepth) {
315  float** z = resultImg.GetImageDataArray();
316  Vector3<double> ray, p;
317  double zNear_ = *zNear;
318  double zFar_ = *zFar;
319  for (unsigned int y=0; y<resultImg.GetHeight(); y++) {
320  for (unsigned int x=0; x<resultImg.GetWidth(); x++) {
321  if (z[y][x] >= 1.0) z[y][x] = 0.0;
322  else if(z[y][x] != 0.0){
323  z[y][x] = zNear_*zFar_ / (zFar_ - (z[y][x])*(zFar_-zNear_));
324  targetProj.UnProjectToRayLocal(HomgPoint2D(x,y,1.0), p, ray);
325  ray = (z[y][x] / ray[2])*ray;
326  z[y][x] = ray.NormL2();
327  }
328  }
329  }
330  }
331 
332  // Camera<unsigned char> resultImage;
333  // resultTexture.CopyToImage(resultImage);
334  // resultImage.Flip();
335  // IOUtils::SaveCamera("texture.mip",resultImage);
336  } catch (glfException& e) {
337  std::cout << "Error: " << e.GetMessageString() << std::endl;
338  pbuffer.Destroy();
339  return -1;
340  }
341 
342 
343 
344  pbuffer.Destroy();
345 #else
346  BIASERR("Recompile BIAS with OpenGL to use GPU warping!");
347 #endif
348  }//end else (*bSimple)
349 
350  ImageIO::Save(*targetImageName, resultImg);
351 }
352 
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
virtual function for interface definition
Definition: Median.cpp:69
void BecomeRelativeTransform(const CoordinateTransform3D &newLocal, const CoordinateTransform3D &newGlobal)
Changes this coordinate transformation so that parameter newLocal becomes the local coordinate frame ...
void Allocate(int width, int height, GLenum internalFormat, int mipmap=0)
Creates a texture with undefined content.
void AttachTexture(const glfTexture &texture, GLenum attachmentPoint, int attachedMipMapLevel=0, int zSlice=0, GLenum cubeMapSide=0)
Attaches a texture to an attachment point which can be.
class HomgPoint2D describes a point with 2 degrees of freedom in projective coordinates.
Definition: HomgPoint2D.hh:67
virtual int Load(const std::string &filename)
convenience wrapper which tries to read different formats
Definition: Projection.cpp:62
void SetSize(int newsize, int secondsize=-1)
Definition: Bilateral.cpp:72
additional depth calibration parameters for a perspective depth camera to be used for ToF-(PMD) camer...
void SetRenderTarget(const BIAS::glfRenderTarget *renderTarget)
Definition: PMDWarp.cpp:129
A 2D texture.
Definition: glfTexture2D.hh:40
void Create()
Creates the texture but does not upload any data yet.
Definition: glfTexture.cpp:80
camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
int BelowThresholdToValue(StorageType Threshold, StorageType Value)
sets alls pixels with values below Threshold to Value
Definition: Image.cpp:1013
bool * AddParamBool(const std::string &name, const std::string &help, bool deflt=false, char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:305
double * AddParamDouble(const std::string &name, const std::string &help, double deflt=0.0, double min=-DBL_MAX, double max=DBL_MAX, char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:351
void SetWrapS(GLenum wrapS)
Sets the wrapping mode for the 1st texture coordinate.
Definition: glfTexture.cpp:105
void SetSigma(const double si)
Definition: Bilateral.hh:83
void SetDrawBuffers(const std::vector< GLenum > &drawbuffers)
void UploadProjectiveTexture(const BIAS::Image< unsigned char > &projectiveTexture)
Upload the color image to the graphics card.
Definition: PMDWarp.cpp:123
void CopyToImage(ImageBase &image, int mipmap=0)
Copies the pixels of a mipmap of the texture to a BIAS::ImageBase.
Exception class used for run-time errors in the OpenGLFramework.
Definition: glfException.hh:79
unsigned int GetWidth() const
Definition: ImageBase.hh:312
void Draw()
Definition: PMDWarp.cpp:213
virtual int Filter(const Image< InputStorageType > &src, Image< OutputStorageType > &dst)
Bilateral filtering with given filter size (5x5 as standard)
Definition: Bilateral.cpp:115
virtual void Destroy()
Uninitializes the rendering context.
const std::string & GetMessageString() const
Returns the description of the error including the file name and line number where the error occured...
void SetMinFilter(GLenum minFilter)
Sets the minifying function.
Definition: glfTexture.cpp:89
virtual void SetPose(const BIAS::Pose pose)
Set pose from pose object.
void UnProjectToRayLocal(const HomgPoint2D &pos, Vector3< double > &origin, Vector3< double > &rayDir, unsigned int camSystem=0, unsigned int cam=0, bool IgnoreDistortion=false) const
calculates a 3D ray in a local camera coordinate system specified by camSystem, which belongs to the ...
Definition: Projection.cpp:419
Represents 3d pose transformations, parametrized as Euclidean translation and unit quaternion orienta...
Definition: Pose.hh:73
const ProjectionParametersBase * GetParameters(unsigned int cam=0) const
const parameter access function
Definition: Projection.hh:194
Implements a 2D median filter for images.
Definition: Median.hh:39
This class hides the underlying projection model, like projection matrix, spherical camera...
Definition: Projection.hh:70
void CheckComplete() const
Checks whether the framebuffer object is supported in its current state.
static int ConvertST(const BIAS::ImageBase &source, BIAS::ImageBase &dest, ImageBase::EStorageType targetST)
Function to convert the storage type of images e.g.
void Init(const BIAS::ProjectionParametersPerspective &pppd, bool targetParametersHaveDistortion=false)
Initializes all neccessary data in order to render using a batch.
Definition: PMDWarp.cpp:36
void SetWrapT(GLenum wrapT)
Sets the wrapping mode for the 2nd texture coordinate.
Definition: glfTexture.cpp:113
unsigned int GetHeight() const
Definition: ImageBase.hh:319
GLX pbuffer rendering context.
2D bilateral filter
Definition: Bilateral.hh:35
void SetSize(int newsize, int secondsize=-1)
Definition: Median.hh:140
virtual int GetImageSize(unsigned int &Width, unsigned int &Height) const
Obtain image dimensions.
virtual void Init(const glfRenderingContextConfig &config)
Initializes the rendering context with the given configuration.
This class Param provides generic support for parameters.
Definition: Param.hh:231
void SetIgnoreValue(InputStorageType ignore)
Definition: Bilateral.hh:87
void SetBilateralSigma(const double si)
Definition: Bilateral.hh:85
int UnDistortDepthMapIP(BIAS::Image< float > &depthMap, bool bIsInCartesianCoords=false)
Undistorts the passed depth map in place.
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
void SetTargetCameraParameters(const BIAS::ProjectionParametersPerspective &relativePpp, double zNear, double zFar)
is also used to determine viewport
Definition: PMDWarp.cpp:143
int * AddParamInt(const std::string &name, const std::string &help, int deflt=0, int min=std::numeric_limits< int >::min(), int max=std::numeric_limits< int >::max(), char cmdshort=0, int Group=GRP_NOSHOW)
For all adding routines:
Definition: Param.cpp:276
void UseProjectiveTexturing(const BIAS::ProjectionParametersPerspective &ppp)
ppp extrinsicis have to be in global coordinates of pppd of Init call! projective texturing cannot d...
Definition: PMDWarp.cpp:95
int Flip()
flips the image vertically (row order is inverted) In place function return 0 in case of success...
Definition: ImageBase.cpp:834
Camera parameters which define the mapping between rays in the camera coordinate system and pixels in...
virtual const BIAS::Pose & GetPose() const
Return complete pose object.
void UploadDepthMap(const BIAS::Image< float > &pmdDepthImage)
Upload the pmd depth image to the graphics card.
Definition: PMDWarp.cpp:83
std::string * AddParamString(const std::string &name, const std::string &help, std::string deflt="", char cmdshort=0, int Group=GRP_NOSHOW)
Definition: Param.cpp:327
Configuration for a rendering context.
class can be used to warp sequences of pmd depth images into a second view with different parameters...
Definition: PMDWarp.hh:61
double NormL2() const
the L2 norm sqrt(a^2 + b^2 + c^2)
Definition: Vector3.hh:633
void Create()
Creates the framebuffer object.
void SetMagFilter(GLenum magFilter)
Sets the magnification function.
Definition: glfTexture.cpp:97
const StorageType ** GetImageDataArray() const
overloaded GetImageDataArray() from ImageBase
Definition: Image.hh:153