contrib/oxl/mvl/ImageMetric.cxx
Go to the documentation of this file.
00001 // This is oxl/mvl/ImageMetric.cxx
00002 #ifdef VCL_NEEDS_PRAGMA_INTERFACE
00003 #pragma implementation
00004 #endif
00005 //:
00006 // \file
00007 
00008 #include "ImageMetric.h"
00009 
00010 #include <vcl_iostream.h>
00011 #include <vcl_cassert.h>
00012 #include <vnl/vnl_double_2.h>
00013 #include <vnl/vnl_double_3x3.h>
00014 #include <vnl/vnl_math.h>
00015 #include <vgl/vgl_point_2d.h>
00016 #include <vgl/vgl_homg_point_2d.h>
00017 #include <vgl/vgl_homg_line_2d.h>
00018 #include <vgl/algo/vgl_homg_operators_2d.h>
00019 #include <vgl/vgl_line_segment_2d.h>
00020 
00021 #include <mvl/HomgPoint2D.h>
00022 #include <mvl/HomgLineSeg2D.h>
00023 #include <mvl/HomgOperator2D.h>
00024 
00025 static vcl_ostream& warning(char const * fn)
00026 {
00027   return vcl_cerr << fn << " WARNING: ";
00028 }
00029 
00030 // TRANSFORMATIONS
00031 
00032 //: Condition the 2D point p.
00033 //  Default implementation is simply to return p in homogeneous coordinates
00034 vgl_homg_point_2d<double> ImageMetric::image_to_homg(vgl_point_2d<double> const& p) const
00035 {
00036   assert(!"ImageMetric::image_to_homg should be implemented for efficiency");
00037   return vgl_homg_point_2d<double>(p.x(), p.y(), 1.0);
00038 }
00039 
00040 //: Condition the 2D point p.
00041 //  Default implementation is simply to return p in homogeneous coordinates
00042 HomgPoint2D ImageMetric::image_to_homg(const vnl_double_2& p) const
00043 {
00044   assert(!"ImageMetric::image_to_homg should be implemented for efficiency");
00045   return HomgPoint2D(p[0], p[1], 1.0);
00046 }
00047 
00048 //: Condition 2D point (x,y)
00049 HomgPoint2D ImageMetric::image_to_homg(double x, double y) const
00050 {
00051   assert(!"ImageMetric::image_to_homg should be implemented for efficiency");
00052   return HomgPoint2D(x, y, 1.0);
00053 }
00054 
00055 //: Convert conditioned point p to image coordinates
00056 vgl_point_2d<double> ImageMetric::homg_to_image(vgl_homg_point_2d<double> const& p) const
00057 {
00058   assert(!"ImageMetric::homg_to_image should be implemented for efficiency");
00059   return p;
00060 }
00061 
00062 vnl_double_2 ImageMetric::homg_to_image(const HomgPoint2D& p) const
00063 {
00064   assert(!"ImageMetric::homg_to_image should be implemented for efficiency");
00065   double x,y;
00066   p.get_nonhomogeneous(x, y);
00067   return vnl_double_2(x, y);
00068 }
00069 
00070 //: Convert homogeneous point in image coordinates to one in conditioned coordinates
00071 vgl_homg_point_2d<double> ImageMetric::imagehomg_to_homg(vgl_homg_point_2d<double> const& x) const
00072 {
00073   return x;
00074 }
00075 
00076 HomgPoint2D ImageMetric::imagehomg_to_homg(const HomgPoint2D& x) const
00077 {
00078   return x;
00079 }
00080 
00081 //: Convert homogeneous point in conditioned coordinates to one in image coordinates
00082 vgl_homg_point_2d<double> ImageMetric::homg_to_imagehomg(vgl_homg_point_2d<double> const& x) const
00083 {
00084   return x;
00085 }
00086 
00087 HomgPoint2D ImageMetric::homg_to_imagehomg(const HomgPoint2D& x) const
00088 {
00089   return x;
00090 }
00091 
00092 //: Convert homogeneous line in conditioned coordinates to one in image coordinates
00093 vgl_homg_line_2d<double> ImageMetric::homg_to_image_line(vgl_homg_line_2d<double> const& l) const
00094 {
00095   if (is_linear())
00096     return get_C_inverse().transpose() * l;
00097 
00098   // get points, decondition, and rejoin
00099   vgl_homg_point_2d<double> p1, p2;
00100   l.get_two_points(p1,p2);
00101   vgl_homg_point_2d<double> i1 = homg_to_imagehomg(p1);
00102   vgl_homg_point_2d<double> i2 = homg_to_imagehomg(p2);
00103   return vgl_homg_line_2d<double>(i1,i2);
00104 }
00105 
00106 HomgLine2D ImageMetric::homg_to_image_line(const HomgLine2D& l) const
00107 {
00108   if (is_linear())
00109     return HomgLine2D(get_C_inverse().transpose() * l.get_vector().as_ref());
00110 
00111   // get points, decondition, and rejoin
00112   HomgPoint2D p1, p2;
00113   l.get_2_points_on_line(&p1, &p2);
00114   HomgPoint2D i1 = homg_to_imagehomg(p1);
00115   HomgPoint2D i2 = homg_to_imagehomg(p2);
00116   return HomgOperator2D::join(i1, i2);
00117 }
00118 
00119 vgl_homg_line_2d<double> ImageMetric::image_to_homg_line(const vgl_homg_line_2d<double>& l) const
00120 {
00121   if (is_linear())
00122     return get_C().transpose() * l;
00123 
00124   // get points, condition, and rejoin
00125   vgl_homg_point_2d<double> p1, p2;
00126   l.get_two_points(p1,p2);
00127   vgl_homg_point_2d<double> i1 = imagehomg_to_homg(p1);
00128   vgl_homg_point_2d<double> i2 = imagehomg_to_homg(p2);
00129   return vgl_homg_line_2d<double>(i1,i2);
00130 }
00131 
00132 HomgLine2D ImageMetric::image_to_homg_line(const HomgLine2D& l) const
00133 {
00134   if (is_linear())
00135     return HomgLine2D(get_C().transpose() * l.get_vector().as_ref());
00136 
00137   // get points, condition, and rejoin
00138   HomgPoint2D p1, p2;
00139   l.get_2_points_on_line(&p1, &p2);
00140   HomgPoint2D i1 = imagehomg_to_homg(p1);
00141   HomgPoint2D i2 = imagehomg_to_homg(p2);
00142   return HomgOperator2D::join(i1, i2);
00143 }
00144 
00145 
00146 //: Convert homogeneous line segment in conditioned coordinates to one in image coordinates
00147 vgl_line_segment_2d<double> ImageMetric::homg_line_to_image(vgl_line_segment_2d<double> const& l) const
00148 {
00149   // get points, decondition, and rejoin
00150   vgl_homg_point_2d<double> i1 = homg_to_imagehomg(vgl_homg_point_2d<double>(l.point1()));
00151   vgl_homg_point_2d<double> i2 = homg_to_imagehomg(vgl_homg_point_2d<double>(l.point2()));
00152   return vgl_line_segment_2d<double>(i1,i2);
00153 }
00154 
00155 HomgLineSeg2D ImageMetric::homg_line_to_image(const HomgLineSeg2D& l) const
00156 {
00157   // get points, decondition, and rejoin
00158   HomgPoint2D i1 = homg_to_imagehomg(l.get_point1());
00159   HomgPoint2D i2 = homg_to_imagehomg(l.get_point2());
00160   return HomgLineSeg2D(i1, i2);
00161 }
00162 
00163 vgl_line_segment_2d<double> ImageMetric::image_to_homg_line(vgl_line_segment_2d<double> const& l) const
00164 {
00165   vgl_homg_point_2d<double> i1 = imagehomg_to_homg(vgl_homg_point_2d<double>(l.point1()));
00166   vgl_homg_point_2d<double> i2 = imagehomg_to_homg(vgl_homg_point_2d<double>(l.point2()));
00167   return vgl_line_segment_2d<double>(i1,i2);
00168 }
00169 
00170 HomgLineSeg2D ImageMetric::image_to_homg_line(const HomgLineSeg2D& l) const
00171 {
00172   HomgPoint2D i1 = imagehomg_to_homg(l.get_point1());
00173   HomgPoint2D i2 = imagehomg_to_homg(l.get_point2());
00174   return HomgLineSeg2D(i1, i2);
00175 }
00176 
00177 // == MEASUREMENTS ==
00178 
00179 //: Compute perpendicular distance in image coordinates between point p and line l, expressed in conditioned coordinates.
00180 double ImageMetric::perp_dist_squared(vgl_homg_point_2d<double> const& p,
00181                                       vgl_homg_line_2d<double> const& l) const
00182 {
00183   return vgl_homg_operators_2d<double>::perp_dist_squared(homg_to_imagehomg(p), homg_to_image_line(l));
00184 }
00185 
00186 double ImageMetric::perp_dist_squared(const HomgPoint2D& p, const HomgLine2D& l) const
00187 {
00188   return HomgOperator2D::perp_dist_squared(homg_to_imagehomg(p), homg_to_image_line(l));
00189 }
00190 
00191 //: Project point onto line.
00192 vgl_homg_point_2d<double> ImageMetric::perp_projection(vgl_homg_line_2d<double> const& l,
00193                                                        vgl_homg_point_2d<double> const& p) const
00194 {
00195   if (l.ideal())
00196     vcl_cerr << "ImageMetric::perp_projection -- line at infinity\n";
00197 
00198   return vgl_homg_operators_2d<double>::perp_projection(homg_to_image_line(l), homg_to_imagehomg(p));
00199 }
00200 
00201 HomgPoint2D ImageMetric::perp_projection(const HomgLine2D & l, const HomgPoint2D & p) const
00202 {
00203   if (p.ideal()) {
00204     vcl_cerr << "ImageMetric::perp_projection -- point at infinity\n";
00205   }
00206 
00207   if (l.ideal()) {
00208     vcl_cerr << "ImageMetric::perp_projection -- line at infinity\n";
00209   }
00210 
00211   return HomgOperator2D::perp_projection(homg_to_image_line(l), homg_to_imagehomg(p));
00212 }
00213 
00214 //: Get perpendicular distance in image.
00215 double ImageMetric::distance_squared(vgl_homg_point_2d<double> const& p1,
00216                                      vgl_homg_point_2d<double> const& p2) const
00217 {
00218   return vgl_homg_operators_2d<double>::distance_squared(homg_to_imagehomg(p1), homg_to_imagehomg(p2));
00219 }
00220 
00221 double ImageMetric::distance_squared(const HomgPoint2D & p1, const HomgPoint2D & p2) const
00222 {
00223   return HomgOperator2D::distance_squared(homg_to_imagehomg(p1), homg_to_imagehomg(p2));
00224 }
00225 
00226 //: Get distance between a line segment and an infinite line.
00227 //  The metric used is the maximum of the two endpoint perp distances.
00228 double ImageMetric::distance_squared(vgl_line_segment_2d<double> const& segment,
00229                                      vgl_homg_line_2d<double> const& line) const
00230 {
00231   // ca_distance_squared_lineseg_to_line
00232   return vnl_math_max(this->perp_dist_squared(vgl_homg_point_2d<double>(segment.point1()), line),
00233                       this->perp_dist_squared(vgl_homg_point_2d<double>(segment.point2()), line));
00234 }
00235 
00236 double ImageMetric::distance_squared(const HomgLineSeg2D& segment, const HomgLine2D& line) const
00237 {
00238   // ca_distance_squared_lineseg_to_line
00239   return vnl_math_max(this->perp_dist_squared(segment.get_point1(), line),
00240                       this->perp_dist_squared(segment.get_point2(), line));
00241 }
00242 
00243 bool ImageMetric::is_within_distance(vgl_homg_point_2d<double> const& p1,
00244                                      vgl_homg_point_2d<double> const& p2,
00245                                      double distance) const
00246 {
00247   return distance_squared(p1, p2) < distance*distance;
00248 }
00249 
00250 bool ImageMetric::is_within_distance(const HomgPoint2D& p1, const HomgPoint2D& p2, double distance) const
00251 {
00252   return distance_squared(p1, p2) < distance*distance;
00253 }
00254 
00255 //: Convert a distance in image coordinates to one in conditioned coordinates.
00256 // This is only possible for similarity transformations, but where it does make
00257 // sense it can mean significant increases in speed.
00258 double ImageMetric::homg_to_image_distance(double image_distance) const
00259 {
00260   warning("ImageMetric::invert_distance()") << "returning 0\n";
00261   return image_distance;
00262 }
00263 
00264 //: Convert a distance in image coordinates to one in conditioned coordinates.
00265 // This is only possible for similarity transformations, but where it does make
00266 // sense it can mean significant increases in speed.
00267 double ImageMetric::image_to_homg_distance(double image_distance) const
00268 {
00269   warning("ImageMetric::invert_distance()") << "returning 0\n";
00270   return image_distance;
00271 }
00272 
00273 //: Return true if the invert_distance function makes sense.
00274 bool ImageMetric::can_invert_distance() const
00275 {
00276   return false;
00277 }
00278 
00279 // == MATRIX REPRESENTATION ==
00280 
00281 //: Return true if the action of the conditioner can be represented as a planar homography.
00282 bool ImageMetric::is_linear() const
00283 {
00284   return false;
00285 }
00286 
00287 #include <vnl/vnl_identity_3x3.h>
00288 
00289 //: Return conditioning matrix C that converts homogeneous image points to homogeneous conditioned points.
00290 //  If the ImageMetric used is nonlinear, then we'll have to make other arrangements...
00291 vnl_double_3x3 ImageMetric::get_C() const
00292 {
00293   static vnl_identity_3x3 I;
00294   warning("ImageMetric::get_C()") << "returning identity\n";
00295   return I;
00296 }
00297 
00298 //: Return conditioning matrix C that converts homogeneous conditioned points to image coordinates.
00299 vnl_double_3x3 ImageMetric::get_C_inverse() const
00300 {
00301   static vnl_identity_3x3 I;
00302   warning("ImageMetric::get_C_inverse()") << "returning identity\n";
00303   return I;
00304 }
00305 
00306 #include <mvl/FMatrix.h>
00307 
00308 FMatrix ImageMetric::decondition(const FMatrix& F, const ImageMetric* c1, const ImageMetric* c2)
00309 {
00310   if (!c1->is_linear())
00311     warning("ImageMetric::decondition(FMatrix...)") << "ImageMetric for image 1 is nonlinear\n";
00312 
00313   if (!c2->is_linear())
00314     warning("ImageMetric::decondition(FMatrix...)") << "ImageMetric for image 2 is nonlinear\n";
00315 
00316   vnl_double_3x3 C1inv = c1->get_C_inverse();
00317   vnl_double_3x3 C2inv = c2->get_C_inverse();
00318   return FMatrix( C1inv.transpose() * F.get_matrix() * C2inv );
00319 }
00320 
00321 vcl_ostream & ImageMetric::print(vcl_ostream& s) const
00322 {
00323   return s << "Empty ImageMetric";
00324 }