コード例 #1
0
    /// <summary>
    /// Evaluate goodness of fit.
    /// </summary>
    /// <remarks>
    /// Calculates the average distance of all contour points to the ellipse. The distance of point to
    /// an ellipse is given by calculating the point on the ellipse that is closest to the query. This calculation
    /// is performed by transforming the point into a coordinate system where the ellipse is in main-pose
    /// (x-axis points toward a, y-axis points toward b, the origin is the center of the ellipse). Additionally,
    /// the coordinate system is crafted in such a way (non-uniform scaling) that the ellipse becomes a circle.
    /// Then, the closest point is simply the closest point on the circle. This point is transformed back into 
    /// the world coordinate system where the distance between the query and the returned point is computed.
    /// </remarks>
    /// <param name="e">Ellipse</param>
    /// <param name="c">Contour points</param>
    /// <returns>Goodness of fit</returns>
    private double GoodnessOfFit(Emgu.CV.Structure.Ellipse e, Emgu.CV.Contour<System.Drawing.Point> c) {
      Matrix m = EllipseDetector.GetAffineFrame(e);
      Matrix inv = m.Inverse();
      List<double> distances = new List<double>();

      double avg_distance = 0.0;
      foreach (System.Drawing.Point p in c) {
        // Bring the point into the ellipse coordinate frame
        Vector x = p.ToParsley().ToHomogeneous(1.0);
        Vector r = (inv.Multiply(x.ToColumnMatrix())).GetColumnVector(0);
        // Find the closest point on the circle to r
        // From the above scaling construction the resulting circle has radius b
        Vector closest = r.ToNonHomogeneous().Normalize().Scale(e.MCvBox2D.size.Height);
        // Transform the closest point back
        Vector closest_in_world = (m.Multiply(closest.ToHomogeneous(1.0).ToColumnMatrix())).GetColumnVector(0);
        // Calculate the squared distance between the query and the point.
        avg_distance += (closest_in_world - x).ToNonHomogeneous().SquaredNorm();
      }
      return Math.Sqrt(avg_distance / c.Count());
    }