00001
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005
00006
00007
00008 #include "SimilarityMetric.h"
00009
00010 #include <vcl_iostream.h>
00011 #include <vnl/vnl_math.h>
00012
00013 #include <vnl/vnl_double_2.h>
00014 #include <vgl/vgl_point_2d.h>
00015 #include <vgl/vgl_homg_point_2d.h>
00016 #include <vgl/vgl_homg_line_2d.h>
00017 #include <vgl/vgl_line_segment_2d.h>
00018 #include <vgl/algo/vgl_homg_operators_2d.h>
00019
00020 #include <mvl/HomgPoint2D.h>
00021 #include <mvl/HomgLine2D.h>
00022 #include <mvl/HomgLineSeg2D.h>
00023 #include <mvl/HomgOperator2D.h>
00024
00025
00026 SimilarityMetric::SimilarityMetric()
00027 {
00028 centre_x_ = 0;
00029 centre_y_ = 0;
00030 inv_scale_ = 1;
00031 scale_ = 1;
00032
00033 make_matrices();
00034 }
00035
00036
00037 SimilarityMetric::SimilarityMetric(double cx, double cy, double scale)
00038 {
00039 centre_x_ = cx;
00040 centre_y_ = cy;
00041 inv_scale_ = 1 / scale;
00042 scale_ = scale;
00043
00044 make_matrices();
00045 }
00046
00047
00048 SimilarityMetric::SimilarityMetric(int xsize, int ysize)
00049 {
00050 set_from_rectangle(xsize, ysize);
00051 }
00052
00053
00054 void SimilarityMetric::set_from_rectangle(int xsize, int ysize)
00055 {
00056 centre_x_ = xsize * 0.5;
00057 centre_y_ = ysize * 0.5;
00058 inv_scale_ = (xsize + ysize) * 0.5;
00059 scale_ = 1.0 / inv_scale_;
00060
00061 make_matrices();
00062 }
00063
00064
00065
00066 void SimilarityMetric::set_center_and_scale(double cx, double cy, double scale)
00067 {
00068 centre_x_ = cx;
00069 centre_y_ = cy;
00070 inv_scale_ = 1 / scale;
00071 scale_ = scale;
00072
00073 make_matrices();
00074 }
00075
00076 void SimilarityMetric::make_matrices()
00077 {
00078 cond_matrix (0, 0) = inv_scale_;
00079 cond_matrix (0, 1) = 0;
00080 cond_matrix (0, 2) = centre_x_;
00081
00082 cond_matrix (1, 0) = 0;
00083 cond_matrix (1, 1) = inv_scale_;
00084 cond_matrix (1, 2) = centre_y_;
00085
00086 cond_matrix (2, 0) = 0;
00087 cond_matrix (2, 1) = 0;
00088 cond_matrix (2, 2) = 1.0;
00089
00090 inv_cond_matrix (0, 0) = scale_;
00091 inv_cond_matrix (0, 1) = 0;
00092 inv_cond_matrix (0, 2) = -centre_x_ * scale_;
00093
00094 inv_cond_matrix (1, 0) = 0;
00095 inv_cond_matrix (1, 1) = scale_;
00096 inv_cond_matrix (1, 2) = -centre_y_ * scale_;
00097
00098 inv_cond_matrix (2, 0) = 0;
00099 inv_cond_matrix (2, 1) = 0;
00100 inv_cond_matrix (2, 2) = 1.0;
00101 }
00102
00103
00104 SimilarityMetric::~SimilarityMetric()
00105 {
00106 }
00107
00108
00109 void SimilarityMetric::print(char* msg) const
00110 {
00111 vcl_cerr<<msg<<": SimilarityMetric ("<<centre_x_<<','<<centre_y_<<", "<<inv_scale_<<")\n";
00112 }
00113
00114
00115 vcl_ostream& SimilarityMetric::print(vcl_ostream& s) const
00116 {
00117 return s<<"[SimilarityMetric ("<<centre_x_<<','<<centre_y_<<"), "<<inv_scale_ << ']';
00118 }
00119
00120
00121
00122
00123
00124 vgl_homg_point_2d<double> SimilarityMetric::image_to_homg(vgl_point_2d<double> const& p) const
00125 {
00126 double nx = p.x();
00127 double ny = p.y();
00128
00129
00130 return vgl_homg_point_2d<double>(nx - centre_x_, ny - centre_y_, inv_scale_);
00131 }
00132
00133
00134
00135
00136 HomgPoint2D SimilarityMetric::image_to_homg(double x, double y) const
00137 {
00138 double nx = x;
00139 double ny = y;
00140
00141
00142 return HomgPoint2D(nx - centre_x_, ny - centre_y_, inv_scale_);
00143 }
00144
00145
00146 vgl_point_2d<double> SimilarityMetric::homg_to_image(vgl_homg_point_2d<double> const& p) const
00147 {
00148 return vgl_point_2d<double>(p.x()/p.w()*inv_scale_+centre_x_, p.y()/p.w()*inv_scale_+centre_y_);
00149 }
00150
00151
00152 vnl_double_2 SimilarityMetric::homg_to_image(const HomgPoint2D& p) const
00153 {
00154 double x,y;
00155 p.get_nonhomogeneous(x, y);
00156 x = x * inv_scale_;
00157 y = y * inv_scale_;
00158
00159 return vnl_double_2(x + centre_x_, y + centre_y_);
00160 }
00161
00162
00163 HomgPoint2D SimilarityMetric::image_to_homg(const vnl_double_2& p) const
00164 {
00165 return image_to_homg(p[0], p[1]);
00166 }
00167
00168
00169 vgl_homg_point_2d<double> SimilarityMetric::homg_to_imagehomg(vgl_homg_point_2d<double> const& x) const
00170 {
00171 return cond_matrix * x;
00172 }
00173
00174
00175 HomgPoint2D SimilarityMetric::homg_to_imagehomg(const HomgPoint2D& x) const
00176 {
00177
00178 return HomgPoint2D(cond_matrix * x.get_vector());
00179 }
00180
00181
00182 vgl_homg_point_2d<double> SimilarityMetric::imagehomg_to_homg(vgl_homg_point_2d<double> const& x) const
00183 {
00184
00185 return inv_cond_matrix * x;
00186 }
00187 HomgPoint2D SimilarityMetric::imagehomg_to_homg(const HomgPoint2D& x) const
00188 {
00189
00190 return HomgPoint2D(inv_cond_matrix * x.get_vector());
00191 }
00192
00193
00194 double SimilarityMetric::distance_squared(vgl_homg_point_2d<double> const& p1,
00195 vgl_homg_point_2d<double> const& p2) const
00196 {
00197 double x1 = p1.x() / p1.w();
00198 double y1 = p1.y() / p1.w();
00199
00200 double x2 = p2.x() / p2.w();
00201 double y2 = p2.y() / p2.w();
00202
00203 return vnl_math_sqr (inv_scale_) * (vnl_math_sqr (x1 - x2) + vnl_math_sqr (y1 - y2));
00204 }
00205
00206 double SimilarityMetric::distance_squared(HomgPoint2D const& p1, HomgPoint2D const& p2) const
00207 {
00208
00209 double x1 = p1.x() / p1.w();
00210 double y1 = p1.y() / p1.w();
00211
00212 double x2 = p2.x() / p2.w();
00213 double y2 = p2.y() / p2.w();
00214
00215 return vnl_math_sqr (inv_scale_) * (vnl_math_sqr (x1 - x2) + vnl_math_sqr (y1 - y2));
00216 }
00217
00218
00219
00220 double SimilarityMetric::distance_squared(vgl_line_segment_2d<double> const& segment,
00221 vgl_homg_line_2d<double> const& line) const
00222 {
00223 return vnl_math_max(this->perp_dist_squared(vgl_homg_point_2d<double>(segment.point1()), line),
00224 this->perp_dist_squared(vgl_homg_point_2d<double>(segment.point2()), line));
00225 }
00226
00227
00228 double SimilarityMetric::distance_squared(const HomgLineSeg2D& segment, const HomgLine2D& line) const
00229 {
00230 return vnl_math_max(this->perp_dist_squared(segment.get_point1(), line),
00231 this->perp_dist_squared(segment.get_point2(), line));
00232 }
00233
00234
00235 double SimilarityMetric::perp_dist_squared(vgl_homg_point_2d<double> const& p,
00236 vgl_homg_line_2d<double> const& l) const
00237 {
00238 if (p.ideal()) {
00239 vcl_cerr << "SimilarityMetric::perp_dist_squared -- point at infinity\n";
00240 return Homg::infinity;
00241 }
00242
00243 if (l.ideal()) {
00244 vcl_cerr << "SimilarityMetric::perp_dist_squared -- line at infinity\n";
00245 return Homg::infinity;
00246 }
00247
00248 double numerator = vnl_math_sqr(p.x()*l.a()+p.y()*l.b()+p.w()*l.c());
00249 double denominator = (vnl_math_sqr(l.a()) + vnl_math_sqr(l.b())) * vnl_math_sqr(p.w() * scale_);
00250
00251 return numerator / denominator;
00252 }
00253 double SimilarityMetric::perp_dist_squared(HomgPoint2D const & p, HomgLine2D const & l) const
00254 {
00255
00256
00257
00258 if (p.ideal()) {
00259 vcl_cerr << "SimilarityMetric::perp_dist_squared -- point at infinity\n";
00260 return Homg::infinity;
00261 }
00262
00263 if (l.ideal()) {
00264 vcl_cerr << "SimilarityMetric::perp_dist_squared -- line at infinity\n";
00265 return Homg::infinity;
00266 }
00267
00268 double numerator = vnl_math_sqr(HomgOperator2D::dot(l, p));
00269 double denominator = (vnl_math_sqr(l.x()) + vnl_math_sqr(l.y()))
00270 * vnl_math_sqr(p.w() * scale_);
00271
00272 return numerator / denominator;
00273 }
00274
00275
00276
00277
00278 void SimilarityMetric::scale_matrices(double s)
00279 {
00280 cond_matrix *= s;
00281 inv_cond_matrix *= (1/s);
00282 }
00283
00284 bool SimilarityMetric::can_invert_distance() const
00285 {
00286 return true;
00287 }
00288
00289 double SimilarityMetric::image_to_homg_distance(double image_distance) const
00290 {
00291 return image_distance * scale_;
00292 }
00293
00294 double SimilarityMetric::homg_to_image_distance(double image_distance) const
00295 {
00296 return image_distance * inv_scale_;
00297 }