コード例 #1
0
        public GeneralMatrix QuantizeScreen(int grid_x, int grid_y)
        {
            // create a general matrix full of 0s
            GeneralMatrix mesh = new GeneralMatrix(grid_x, grid_y, 0.0);

            // Find the bounding box of the points.
            System.Drawing.Rectangle bBox = BoundingBox();

            if (_points.Count == 0)
            {
                return(mesh);
            }

            // find the step we want
            // Note: this is an intentional deviation from the original paper.
            //      We do not maintain the original aspect ratio of the shape.
            double stepX = bBox.Width / (double)(grid_x - 1);
            double stepY = bBox.Height / (double)(grid_y - 1);

            // find the center of the image
            double cx = (double)(bBox.Left + bBox.Right) / 2.0;
            double cy = (double)(bBox.Top + bBox.Bottom) / 2.0;

            foreach (GenericPoint pt in _points)
            {
                // normalize the point's coordinates
                int x_index = (int)Math.Floor(((pt.X - cx) / stepX) + grid_x / 2);
                int y_index = (int)Math.Floor(((pt.Y - cy) / stepY) + grid_y / 2);

                if (x_index < grid_x && y_index < grid_y)
                {
                    mesh.SetElement(y_index, x_index, 1.0);
                }
            }

#if JESSI
            Console.WriteLine("Quantized screen");
            Console.Write(mesh.ToString());
#endif

            return(mesh);
        }
コード例 #2
0
        /// <summary>
        /// Calculates and saves the distance transform map for the polar coordinates.
        /// Uses _pMesh and saves to _pDTM.
        /// A distance transform map is a matrix in which every entry represents the
        /// distance from that point to the nearest point with ink.
        /// </summary>
        private void PolarDistanceTransform()
        {
            List <Coord> indices = IndexList(_pMesh);

            for (int i = 0; i < GRID_Y_SIZE; i++)
            {
                for (int j = 0; j < GRID_X_SIZE; j++)
                {
                    Coord cp = new Coord(j, i);

                    double mindist = double.PositiveInfinity;

                    foreach (Coord pt in indices)
                    {
                        // the straight distance between current point and current index
                        double dx           = Math.Abs(cp.X - pt.X);
                        double dy           = Math.Abs(cp.Y - pt.Y);
                        double straightDist = Math.Sqrt(dx * dx + dy * dy);

                        dx = (double)GRID_X_SIZE - dx;
                        double wrapDist = Math.Sqrt(dx * dx + dy * dy);

                        double distan = Math.Min(straightDist, wrapDist);

                        if (distan < mindist)
                        {
                            mindist = distan;
                        }
                    }
                    _pDTM.SetElement(i, j, mindist);
                }
            }

#if FALSE
            Console.WriteLine("Your polar distance transform map:");
            Console.Write(_pDTM.ToString())
#endif
        }
コード例 #3
0
        /// <summary>
        /// Calculates the dissimilarity between the calling BitmapSymbol and
        /// BitmapSymbol S in terms of their polar coordinates using the
        /// modified Hausdorff distance (aka the mean distance).
        /// </summary>
        private SymbolRank Polar_Mod_Hausdorff(BitmapSymbol S)
        {
            int lower_rot_index = (int)Math.Floor(ALLOWED_ROTATION_AMOUNT * GRID_X_SIZE / 720.0);
            int upper_rot_index = GRID_X_SIZE - lower_rot_index; //trick

            List <Coord> A = new List <Coord>(_polarCoords);
            List <Coord> B = new List <Coord>(S._polarCoords);

            if (A.Count == 0 || B.Count == 0)
            {
                return(new SymbolRank());
            }

            double minA2B = double.PositiveInfinity;
            double distan = 0.0;
            int    besti  = 0; // the best translation in theta

#if FALSE
            Console.WriteLine("Your gate: ");
            Console.Write(_pMesh.ToString());

            Console.WriteLine("Your template: ");
            Console.Write(S._pMesh.ToString());
#endif

            // rotations in screen coordinates are the same as translations in polar coords
            // we have polar coords, so translate in X (theta) until you get the best orientation
            for (int i = 0; i < GRID_X_SIZE; i++)
            {
                if (i > lower_rot_index && i < upper_rot_index)
                {
                    continue;
                }

                distan = 0.0;
                // find the distance from each point in A to the nearest point in B using B_DTM
                foreach (Coord a in A)
                {
                    int y_ind = (int)a.Y;
                    int x_ind = (int)a.X - i; // translate by i on the theta (X) axis
                    if (x_ind < 0)
                    {
                        x_ind += GRID_X_SIZE;            // make sure we're still on the graph
                    }
                    //putting less weight on points that have small rel dist - y
                    double weight = Math.Pow((double)y_ind, POLAR_WEIGHT_DECAY_RATE);
                    distan += S._pDTM.GetElement(y_ind, x_ind) * weight;
                }

                // this is the best orientation if the total distance is the smallest
                if (distan < minA2B)
                {
                    minA2B = distan;
                    besti  = i;
                }
            }

            // set the best rotation angle (in radians)
            double bestRotAngle = besti * 2.0 * Math.PI / (double)GRID_X_SIZE;

            // we've already found the best orientation
            // find the distance from each point in B to the nearest point in A using A_DTM
            double minB2A = 0.0;
            foreach (Coord b in B)
            {
                int y_ind = (int)b.Y;
                int x_ind = (int)b.X - besti; // slide B back by besti
                if (x_ind < 0)
                {
                    x_ind += GRID_X_SIZE;
                }
                double weight = Math.Pow((double)y_ind, POLAR_WEIGHT_DECAY_RATE);
                minB2A += _pDTM.GetElement(y_ind, x_ind) * weight;
            }

            minA2B /= (double)A.Count;
            minB2A /= (double)B.Count;

#if FALSE
            Console.WriteLine("Finding best orientation match of your gate and " + S._name);
            Console.WriteLine("The best translation is " + besti + " which is " + bestRotAngle + " radians.");
            Console.WriteLine("A2B distance: " + minA2B + ", B2A distance: " + minB2A);
            string templateName = S._name;
#endif

            return(new SymbolRank(Math.Max(minA2B, minB2A), S, bestRotAngle));
        }