GSLAM  3.0.0
Undistorter.h
1 // GSLAM - A general SLAM framework and benchmark
2 // Copyright 2018 PILAB Inc. All rights reserved.
3 // https://github.com/zdzhaoyong/GSLAM
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are met:
7 //
8 // * Redistributions of source code must retain the above copyright notice,
9 // this list of conditions and the following disclaimer.
10 // * Redistributions in binary form must reproduce the above copyright notice,
11 // this list of conditions and the following disclaimer in the documentation
12 // and/or other materials provided with the distribution.
13 // * Neither the name of Google Inc. nor the names of its contributors may be
14 // used to endorse or promote products derived from this software without
15 // specific prior written permission.
16 //
17 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 // POSSIBILITY OF SUCH DAMAGE.
28 //
29 // Author: zd5945@126.com (Yong Zhao)
30 //
31 // Undistorter is used to remap a image between camera models
32 #ifndef GSLAM_UNDISTORTER_H
33 #define GSLAM_UNDISTORTER_H
34 
35 #include <memory>
36 #include "GImage.h"
37 #include "Camera.h"
38 
39 namespace GSLAM{
40 
42 {
43 public:
44  template <int Size>
45  struct Byte
46  {
47  unsigned char data[Size];
48  };
49 
50  typedef Byte<3> rgb;
51 
53  : camera_in(in),camera_out(out),remapX(NULL),remapY(NULL),remapFast(NULL),
54  remapIdx(NULL),remapCoef(NULL),valid(true)
55  {
56  prepareReMap();
57  }
58 
60  {
61  if( remapX != NULL ) delete[] remapX;
62  if( remapY != NULL ) delete[] remapY;
63  if( remapFast != NULL ) delete[] remapFast;
64 
65  if( remapIdx != NULL ) delete[] remapIdx;
66  if( remapCoef != NULL) delete[] remapCoef;
67  }
68 
69  bool undistort(const GImage& image, GImage& result);
70  bool undistortFast(const GImage& image, GImage& result);
71 
72  bool prepareReMap();
73 
74 public:
75  Camera camera_in;
76  Camera camera_out;
77 
78  float* remapX;
79  float* remapY;
80  int* remapFast;
81 
82  int *remapIdx;
83  float *remapCoef;
84 
85  /// Is true if the undistorter object is valid (has been initialized with
86  /// a valid configuration)
87  bool valid;
88 };
89 
91 {
92 public:
93  Undistorter(Camera in=Camera(), Camera out=Camera());
94 
95  bool undistort(const GImage& image, GImage& result);
96  //Undistorting fast, no interpolate (bilinear) is used
97  bool undistortFast(const GImage& image, GImage& result);
98 
99  GImage undistort(const GImage& image){
100  GImage result;
101  if(!undistort(image,result)) return GImage();
102  return result;
103  }
104 
105  GImage undistortFast(const GImage& image){
106  GImage result;
107  if(!undistortFast(image,result)) return GImage();
108  return result;
109  }
110 
111  Camera cameraIn();
112  Camera cameraOut();
113 
114  bool prepareReMap();
115  bool valid();
116 private:
117  std::shared_ptr<UndistorterImpl> impl;
118 };
119 
120 inline bool UndistorterImpl::prepareReMap()
121 {
122  using namespace std;
123  // check camera model
124  if( !(camera_in.isValid() && camera_out.isValid()) )
125  {
126  valid = false;
127 // cout<<("Undistorter does not get vallid camera.");
128  return false;
129  }
130  // Prepare remap
131  cout << "Undistorter:\n";
132  cout << " Camera IN : " << camera_in.info() << endl;
133  cout << " Camera OUT: " << camera_out.info() << endl << endl;
134  int size=camera_out.width() * camera_out.height();
135  remapX = new float[size];
136  remapY = new float[size];
137  remapFast = new int[size];
138 
139  remapIdx = new int [size*4];
140  remapCoef = new float[size*4];
141  Point3d world_pose;Point2d im_pose;
142  int w_in=camera_in.width(),h_in=camera_in.height();
143  for(int y=0,yend=camera_out.height(); y<yend; y++)
144  for(int x=0,xend=camera_out.width(); x<xend; x++)
145  {
146  int i = y*xend+x;
147 
148  world_pose=camera_out.UnProject(Point2d(x,y));
149  im_pose = camera_in.Project(world_pose);
150 
151  if(im_pose.x<0 || im_pose.y<0 ||
152  im_pose.x>=w_in||im_pose.y>=h_in)
153  {
154  remapX[i] = -1;
155  remapY[i] = -1;
156  remapFast[i] = -1;
157 
158  remapIdx[i*4+0] = 0;
159  remapIdx[i*4+1] = 0;
160  remapIdx[i*4+2] = 0;
161  remapIdx[i*4+3] = 0;
162 
163  remapCoef[i*4+0] = 0;
164  remapCoef[i*4+1] = 0;
165  remapCoef[i*4+2] = 0;
166  remapCoef[i*4+3] = 0;
167  continue;
168  }
169 
170  {
171  remapX[i] = im_pose.x;
172  remapY[i] = im_pose.y;
173  remapFast[i] = (int)im_pose.x+w_in*(int)im_pose.y;
174  }
175 
176  // calculate fast bi-linear interpolation indices & coefficients
177  {
178  float xx = remapX[i];
179  float yy = remapY[i];
180 
181  if( xx < 0.0 ) continue;
182 
183  // get integer and rational parts
184  int xxi = xx;
185  int yyi = yy;
186  xx -= xxi;
187  yy -= yyi;
188  float xxyy = xx*yy;
189 
190  remapIdx[i*4+0] = yyi*w_in + xxi;
191  remapIdx[i*4+1] = yyi*w_in + xxi + 1;
192  remapIdx[i*4+2] = (yyi+1)*w_in + xxi;
193  remapIdx[i*4+3] = (yyi+1)*w_in + xxi + 1;
194 
195  remapCoef[i*4+0] = 1-xx-yy+xxyy;
196  remapCoef[i*4+1] = xx-xxyy;
197  remapCoef[i*4+2] = yy-xxyy;
198  remapCoef[i*4+3] = xxyy;
199  }
200  }
201  valid=true;
202  return true;
203 }
204 
205 //Undistorting fast, no interpolate (bilinear) is used
206 inline bool UndistorterImpl::undistortFast(const GImage& image, GImage& result)
207 {
208  using namespace std;
209  if (!valid)
210  {
211  result = image;
212  return false;
213  }
214  int width_out=camera_out.width();
215  int height_out=camera_out.height();
216 
217  if (image.rows != camera_in.height() || image.cols != camera_in.width())
218  {
219  cerr<<("input image size differs from expected input size! Not undistorting.\n");
220  result = image;
221  return false;
222  }
223 
224  int wh=width_out*height_out;
225  int c=image.channels();
226 
227  result=GImage(height_out,width_out,image.type());
228 
229  if(c==1)
230  {
231  Byte<1>* p_out=(Byte<1>*)result.data;
232  Byte<1>* p_img=(Byte<1>*)image.data;
233 // #pragma omp parallel for
234  for(int i=0;i<wh;i++)
235  {
236  if(remapFast[i]>0)
237  {
238  p_out[i] = p_img[remapFast[i]];
239  }
240  }
241  }
242  else if(c==3)
243  {
244  Byte<3>* p_out=(Byte<3>*)result.data;
245  Byte<3>* p_img=(Byte<3>*)image.data;
246 // #pragma omp parallel for
247  for(int i=0;i<wh;i++)
248  {
249  p_out[i] = p_img[remapFast[i]];
250  }
251  }
252  else
253  {
254  int eleSize=image.elemSize();
255  Byte<1>* p_out=(Byte<1>*)result.data;
256  Byte<1>* p_img=(Byte<1>*)image.data;
257 // #pragma omp parallel for
258  for(int i=0;i<wh;i++)
259  {
260  if(remapX[i]>0)
261  {
262  memcpy(p_out+eleSize*i,p_img+eleSize*remapFast[i],eleSize);
263  }
264  }
265  }
266 
267  return true;
268 }
269 
270 //Undistorting bilinear interpolation
271 inline bool UndistorterImpl::undistort(const GImage& image, GImage& result)
272 {
273  using namespace std;
274  if (!valid)
275  {
276  result = image;
277  return false;
278  }
279  int width_out=camera_out.width();
280  int height_out=camera_out.height();
281 
282  if (image.rows != camera_in.height() || image.cols != camera_in.width())
283  {
284  cerr<<("input image size differs from expected input size! Not undistorting.\n");
285  result = image;
286  return false;
287  }
288 
289  int wh=width_out*height_out;
290  int c=image.channels();
291 
292  result=GImage(height_out,width_out,image.type());
293 
294  if(c==1)
295  {
296  uchar* p_out=(uchar*)result.data;
297  uchar* p_img=(uchar*)image.data;
298 
299  int *pIdx = remapIdx;
300  float *pCoef = remapCoef;
301 
302 // #pragma omp parallel for
303  for(int i = 0; i<wh; i++)
304  {
305  // get interp. values
306  float xx = remapX[i];
307 
308  if(xx<0)
309  p_out[i] = 0;
310  else
311  {
312  p_out[i] = p_img[pIdx[0]]*pCoef[0] +
313  p_img[pIdx[1]]*pCoef[1] +
314  p_img[pIdx[2]]*pCoef[2] +
315  p_img[pIdx[3]]*pCoef[3];
316  }
317 
318  pIdx += 4;
319  pCoef += 4;
320  }
321  }
322  else
323  {
324  uchar* p_out = (uchar*)result.data;
325  uchar* p_img = (uchar*)image.data;
326 
327  int *pIdx = remapIdx;
328  float *pCoef = remapCoef;
329 
330 // #pragma omp parallel for
331  for(int i=0; i<wh; i++)
332  {
333  if(remapX[i]>0)
334  {
335  for(int j=0; j<c; j++)
336  p_out[i*3+j] = p_img[pIdx[0]*c+j]*pCoef[0] +
337  p_img[pIdx[1]*c+j]*pCoef[1] +
338  p_img[pIdx[2]*c+j]*pCoef[2] +
339  p_img[pIdx[3]*c+j]*pCoef[3];
340  }
341 
342  pIdx += 4;
343  pCoef += 4;
344  }
345  }
346 
347  return true;
348 }
349 
350 inline Undistorter::Undistorter(Camera in, Camera out)
351  :impl(new UndistorterImpl(in,out))
352 {
353 }
354 
355 inline bool Undistorter::undistort(const GImage& image, GImage& result)
356 {
357  return impl->undistort(image,result);
358 }
359 
360 inline bool Undistorter::undistortFast(const GImage& image, GImage& result)
361 {
362  return impl->undistortFast(image,result);
363 }
364 
365 inline Camera Undistorter::cameraIn(){return impl->camera_in;}
366 inline Camera Undistorter::cameraOut(){return impl->camera_out;}
367 
368 inline bool Undistorter::prepareReMap()
369 {
370  return impl->prepareReMap();
371 }
372 
373 inline bool Undistorter::valid()
374 {
375  return impl->valid;
376 }
377 
378 }
379 #endif
bool valid
Is true if the undistorter object is valid (has been initialized with a valid configuration) ...
Definition: Undistorter.h:87
Definition: Undistorter.h:90
The GImage class is a tiny implementation of image for removing dependency of opencv.
Definition: GImage.h:160
Definition: Undistorter.h:41
Definition: Point.h:48
Definition: Point.h:162
Definition: Camera.h:175
Definition: Undistorter.h:45
Definition: Camera.h:45