Points&Forces (survey)
Software tools facilitating the task of surveying architecture
unwarp.cxx
Go to the documentation of this file.
1 /*
2  Copyright 2008-2022 Pierre SMARS (smars@yuntech.edu.tw)
3  This program is free software: you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation, either version 2 of the License, or
6  (at your option) any later version.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16 #include "a_image_defo.h"
17 #include "SimpleOpt.h"
18 #include <cmath>
19 #include <iostream>
20 #include <sstream>
22 
23 CSimpleOpt::SOption g_rgOptions[] = {
24  { OPT_XC, _T("-xc"), SO_REQ_SEP },
25  { OPT_YC, _T("-yc"), SO_REQ_SEP },
26  { OPT_K1, _T("-k1"), SO_REQ_SEP },
27  { OPT_K2, _T("-k2"), SO_REQ_SEP },
28  { OPT_K3, _T("-k3"), SO_REQ_SEP },
29  { OPT_SCALE, _T("-s"), SO_NONE },
30  { OPT_SCALE, _T("--scaled"), SO_NONE },
31  { OPT_POINTS, _T("-r"), SO_NONE },
32  { OPT_POINTS, _T("--reference-points"), SO_NONE },
33  { OPT_HELP, _T("-?"), SO_NONE },
34  { OPT_HELP, _T("-h"), SO_NONE },
35  { OPT_HELP, _T("--help"), SO_NONE },
36  SO_END_OF_OPTIONS
37 };
38 
39 //----------------------------------------------------------------------------
40 // k1, k2... : radial distorsion parametre(s)
41 // xo, yo : point in the original image
42 // cx, cy : centre of deformation
43 // xn, yn : point in the new image
44 //
45 
47 {
48  public:
49  void read(const std::string& name) {a_image_defo::read(name); r_max_=this->diag();}
50  void box_out();
51  double diag() const {return sqrt(box_in_[1]*box_in_[1]+box_in_[3]*box_in_[3])/2.;}
52  void centre() {xc_=(box_in_[1]-box_in_[0])/2.; yc_=(box_in_[3]-box_in_[2])/2.;}
53  void centre(double xc, double yc) {xc_=yc; yc_=yc;}
54  void k(double k1, double k2, double k3) {k1_=k1; k2_=k2; k3_=k3;}
55  void xc(double xc) {xc_=xc;}
56  void yc(double yc) {yc_=yc;}
57  void new_coordinates(double xo, double yo, double& xn, double& yn);
58  bool old_coordinates(double xn, double yn, double& xo, double& yo);
59  double rdefo(double rexact);
60  protected:
61  double r_max_;
62  double xc_;
63  double yc_;
64  double k0_;
65  double k1_;
66  double k2_;
67  double k3_;
68 };
69 
70 //---------------------------------------------------------------------------
72 {
73  k0_=1.-k1_-k2_-k3_;
75 }
76 //---------------------------------------------------------------------------
77 double a_radial_distorsion::rdefo(double rexact)
78 {
79  const int n_max = 50;
80  double rest = rexact;
81  double rn;
82  int n = 0;
83  do
84  {
85  n++;
86  rn = k0_*rest+k1_*rest*rest+k2_*rest*rest*rest+k3_*rest*rest*rest*rest;
87  double rnd = k0_+2*k1_*rest+3*k2_*rest*rest+4*k3_*rest*rest*rest;
88  double dr = (rexact-rn)/rnd;
89  rest += dr;
90  } while ((fabs(rexact-rn)>1.e-5)&&(n<n_max));
91  if (n>=n_max)
92  {
93  std::cerr << "convergence problem!" << std::endl;
94  std::cerr << "are the factors large? check result carefully." << std::endl;
95  std::cerr << "rest: " << fabs(rexact-rn) << std::endl;
96  return -1.;
97  }
98  return rest;
99 }
100 //---------------------------------------------------------------------------
101 void a_radial_distorsion::new_coordinates(double xo, double yo, double& xn, double& yn)
102 {
103  double dx = xo-xc_;
104  double dy = yo-yc_;
105  double r = sqrt(dx*dx+dy*dy)/r_max_;
106  double L = k0_+k1_*r+k2_*r*r+k3_*r*r*r;
107  xn = xc_+L*dx;
108  yn = yc_+L*dy;
109 }
110 //---------------------------------------------------------------------------
111 bool a_radial_distorsion::old_coordinates(double xn, double yn, double& xo, double& yo)
112 {
113  double dx = xn-xc_;
114  double dy = yn-yc_;
115  double r = sqrt(dx*dx+dy*dy)/r_max_;
116  double L;
117  if (r != 0.)
118  {
119  L = this->rdefo(r);
120  if (L == -1.) return false;
121  L /= r;
122  }
123  else
124  L = 0.;
125  xo = xc_+L*dx;
126  yo = yc_+L*dy;
127  if (xo<(double)box_in_[0]) return false;
128  if (xo>(double)box_in_[1]) return false;
129  if (yo<(double)box_in_[2]) return false;
130  if (yo>(double)box_in_[3]) return false;
131  return true;
132 }
133 //---------------------------------------------------------------------------
134 int error(int val)
135 {
136 #include "unwarp.help"
137  return val;
138 }
139 //---------------------------------------------------------------------------
140 int main(int argc, char ** argv)
141 {
142  double k1 = 0;
143  double k2 = 0;
144  double k3 = 0;
145  double xc = 0;
146  double yc = 0;
147  bool is_scaled=false;
148  bool given_xc=false;
149  bool given_yc=false;
150  bool with_points = false;
151  CSimpleOpt args(argc, argv, g_rgOptions);
152  while (args.Next())
153  {
154  if (args.LastError() == SO_SUCCESS)
155  {
156  if (args.OptionId() == OPT_HELP)
157  return error(0);
158  else if (args.OptionId() == OPT_SCALE)
159  is_scaled = true;
160  else if (args.OptionId() == OPT_POINTS)
161  with_points = true;
162  else if (args.OptionId() == OPT_XC)
163  {
164  std::ostringstream o;
165  o << args.OptionArg();
166  std::istringstream in(o.str().c_str());
167  in >> xc;
168  given_xc = true;
169  } else if (args.OptionId() == OPT_YC)
170  {
171  std::ostringstream o;
172  o << args.OptionArg();
173  std::istringstream in(o.str().c_str());
174  in >> yc;
175  given_yc = true;
176  } else if (args.OptionId() == OPT_K1)
177  {
178  std::ostringstream o;
179  o << args.OptionArg();
180  std::istringstream in(o.str().c_str());
181  in >> k1;
182  } else if (args.OptionId() == OPT_K2)
183  {
184  std::ostringstream o;
185  o << args.OptionArg();
186  std::istringstream in(o.str().c_str());
187  in >> k2;
188  } else if (args.OptionId() == OPT_K3)
189  {
190  std::ostringstream o;
191  o << args.OptionArg();
192  std::istringstream in(o.str().c_str());
193  in >> k3;
194  } else
195  return error(-1);
196  // handle option, using OptionId(), OptionText() and OptionArg()
197  } else {
198  std::cerr << "Invalid argument: " << args.OptionText() << std::endl;
199  return error(args.LastError());
200  // handle error, one of: SO_OPT_INVALID, SO_OPT_MULTIPLE,
201  // SO_ARG_INVALID, SO_ARG_INVALID_TYPE, SO_ARG_MISSING
202  }
203  }
204  if (args.FileCount() != 2) return error(-2);
205  std::ifstream in(args.File(0));
206  if (!in)
207  {
208  std::cerr << "cannot open file: '" << args.File(0) << "'" << std::endl;
209  return error(-3);
210  }
211  in.close();
212  a_radial_distorsion disto;
213  disto.read(args.File(0));
214  if (!is_scaled)
215  {
216  double d = disto.diag();
217  k1 *= d;
218  k2 *= d*d;
219  k3 *= d*d*d;
220  }
221  disto.centre();
222  if (given_xc) disto.xc(xc);
223  if (given_yc) disto.yc(yc);
224  disto.k(k1,k2,k3);
225  disto.box_out();
226  disto.deform();
227  disto.write(args.File(1));
228  if (with_points)
229  {
230  unsigned int npts;
231  std::cin >> npts;
232  std::cout << npts << std::endl;
233  for (unsigned int i=0; i<npts; i++)
234  {
235  double u,v;
236  double un,vn;
237  std::cin >> u >> v;
238  disto.new_coordinates(u,v,un,vn);
239  std::cout << un << " " << vn << std::endl;
240  }
241  }
242  return 0;
243 }
a unit to deform an image. The transformation function needs to be defined in a children class.
Definition: a_image_defo.h:29
void write(const std::string &name)
write the processed image to a file
void deform()
deform the image
virtual void read(const std::string &name)
read the image to be processed
virtual void box_out()
compute the bounding box of the new image
int box_in_[6]
Definition: a_image_defo.h:61
void centre(double xc, double yc)
Definition: unwarp.cxx:53
void box_out()
compute the bounding box of the new image
Definition: unwarp.cxx:71
void new_coordinates(double xo, double yo, double &xn, double &yn)
gives the pixel coordinates in the output image in function of the pixel coordinates in the input ima...
Definition: unwarp.cxx:101
double rdefo(double rexact)
Definition: unwarp.cxx:77
void xc(double xc)
Definition: unwarp.cxx:55
double diag() const
Definition: unwarp.cxx:51
bool old_coordinates(double xn, double yn, double &xo, double &yo)
gives the pixel coordinates in the input image in function of the pixel coordinates in the output ima...
Definition: unwarp.cxx:111
void yc(double yc)
Definition: unwarp.cxx:56
void k(double k1, double k2, double k3)
Definition: unwarp.cxx:54
void read(const std::string &name)
read the image to be processed
Definition: unwarp.cxx:49
double v(const uint32_t step, const uint32_t n)
Definition: generate.cxx:42
uint32_t n[]
Definition: generate.cxx:34
std::string name
Definition: pixelpos.cxx:77
std::istringstream in
Definition: ply2tri.cxx:32
int error(int val)
Definition: unwarp.cxx:134
CSimpleOpt::SOption g_rgOptions[]
Definition: unwarp.cxx:23
int main(int argc, char **argv)
Definition: unwarp.cxx:140
@ OPT_POINTS
Definition: unwarp.cxx:21
@ OPT_K1
Definition: unwarp.cxx:21
@ OPT_HELP
Definition: unwarp.cxx:21
@ OPT_K3
Definition: unwarp.cxx:21
@ OPT_YC
Definition: unwarp.cxx:21
@ OPT_SCALE
Definition: unwarp.cxx:21
@ OPT_K2
Definition: unwarp.cxx:21
@ OPT_XC
Definition: unwarp.cxx:21