Пример #1
0
        private void Snake(bool[,] binary_image, bool BlackOnWhite,
                           int max_itterations,
                           Random rnd)
        {
            bool SnakeComplete = false;

            //set the initial parameters for the snake
            prevSnakeStationaryPoints = 0;
            snakeStationary           = 0;

            // itterate until the snake can get no smaller
            int i = 0;

            while ((!SnakeComplete) && (i < max_itterations))
            {
                SnakeComplete = Update(binary_image, BlackOnWhite, elasticity, gravity, rnd);
                i++;
            }

            // create a new polygon shape
            shape = new polygon2D();
            for (i = 0; i < no_of_points; i++)
            {
                shape.Add((int)SnakePoint[i, SNAKE_X], (int)SnakePoint[i, SNAKE_Y]);
            }
        }
Пример #2
0
        /// <summary>
        /// simple function used to test grid creation
        /// </summary>
        /// <param name="filename">filename of the test image to be created</param>
        public static void Test(string filename)
        {
            int image_width  = 640;
            int image_height = 480;
            int dimension_x  = 10;
            int dimension_y  = 10;

            Bitmap bmp = new Bitmap(image_width, image_height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);

            byte[] img = new byte[image_width * image_height * 3];

            polygon2D test_poly;
            grid2D    grid;

            test_poly = new polygon2D();
            test_poly.Add(image_width * 15 / 100, image_height * 20 / 100);
            test_poly.Add(image_width * 40 / 100, image_height * 20 / 100);
            test_poly.Add(image_width * 40 / 100, image_height * 40 / 100);
            test_poly.Add(image_width * 15 / 100, image_height * 40 / 100);
            grid = new grid2D(dimension_x, dimension_y, test_poly, 0, false);
            grid.ShowLines(img, image_width, image_height, 0, 255, 0, 0);

            int half_width = image_width / 2;

            test_poly = new polygon2D();
            test_poly.Add(half_width + (image_width * 20 / 100), image_height * 20 / 100);
            test_poly.Add(half_width + (image_width * 35 / 100), image_height * 20 / 100);
            test_poly.Add(half_width + (image_width * 40 / 100), image_height * 40 / 100);
            test_poly.Add(half_width + (image_width * 15 / 100), image_height * 40 / 100);
            grid = new grid2D(dimension_x, dimension_y, test_poly, 0, false);
            grid.ShowLines(img, image_width, image_height, 0, 255, 0, 0);

            int half_height = image_height / 2;

            test_poly = new polygon2D();
            test_poly.Add(image_width * 15 / 100, half_height + (image_height * 24 / 100));
            test_poly.Add(image_width * 40 / 100, half_height + (image_height * 20 / 100));
            test_poly.Add(image_width * 40 / 100, half_height + (image_height * 40 / 100));
            test_poly.Add(image_width * 15 / 100, half_height + (image_height * 36 / 100));
            grid = new grid2D(dimension_x, dimension_y, test_poly, 0, false);
            grid.ShowLines(img, image_width, image_height, 0, 255, 0, 0);

            test_poly = new polygon2D();
            test_poly.Add(half_width + (image_width * 20 / 100), half_height + (image_height * 24 / 100));
            test_poly.Add(half_width + (image_width * 35 / 100), half_height + (image_height * 20 / 100));
            test_poly.Add(half_width + (image_width * 40 / 100), half_height + (image_height * 40 / 100));
            test_poly.Add(half_width + (image_width * 15 / 100), half_height + (image_height * 36 / 100));
            grid = new grid2D(dimension_x, dimension_y, test_poly, 0, false);
            grid.ShowLines(img, image_width, image_height, 0, 255, 0, 0);

            BitmapArrayConversions.updatebitmap_unsafe(img, bmp);
            bmp.Save(filename);
        }
Пример #3
0
        /// <summary>
        /// finds the interception points between grid lines
        /// </summary>
        private void poltLineIntercepts()
        {
            if (line != null)
            {
                // create an array to store the line intercepts
                int intercepts_x = line[0].Count / 4;
                int intercepts_y = line[1].Count / 4;
                line_intercepts = new float[intercepts_x, intercepts_y, 2];

                for (int i = 0; i < line[0].Count; i += 4)
                {
                    // get the first line coordinates
                    ArrayList lines0 = line[0];
                    float     x0     = (float)lines0[i];
                    float     y0     = (float)lines0[i + 1];
                    float     x1     = (float)lines0[i + 2];
                    float     y1     = (float)lines0[i + 3];

                    for (int j = 0; j < line[1].Count; j += 4)
                    {
                        // get the second line coordinates
                        ArrayList lines1 = line[1];
                        float     x2     = (float)lines1[j];
                        float     y2     = (float)lines1[j + 1];
                        float     x3     = (float)lines1[j + 2];
                        float     y3     = (float)lines1[j + 3];

                        // find the interception between the two lines
                        float ix = 0, iy = 0;
                        geometry.intersection(x0, y0, x1, y1, x2, y2, x3, y3, ref ix, ref iy);

                        // store the intercept position
                        line_intercepts[i / 4, j / 4, 0] = ix;
                        line_intercepts[i / 4, j / 4, 1] = iy;
                    }
                }

                // update the perimeter
                border_perimeter = new polygon2D();
                float xx = line_intercepts[0, 0, 0];
                float yy = line_intercepts[0, 0, 1];
                border_perimeter.Add(xx, yy);
                xx = line_intercepts[intercepts_x - 1, 0, 0];
                yy = line_intercepts[intercepts_x - 1, 0, 1];
                border_perimeter.Add(xx, yy);
                xx = line_intercepts[intercepts_x - 1, intercepts_y - 1, 0];
                yy = line_intercepts[intercepts_x - 1, intercepts_y - 1, 1];
                border_perimeter.Add(xx, yy);
                xx = line_intercepts[0, intercepts_y - 1, 0];
                yy = line_intercepts[0, intercepts_y - 1, 1];
                border_perimeter.Add(xx, yy);
            }
        }
Пример #4
0
 /// <summary>
 /// creates a circle shape
 /// </summary>
 /// <param name="centre_x">
 /// centre x coordinate of the circle <see cref="System.Single"/>
 /// </param>
 /// <param name="centre_y">
 /// centre y coordinate of the circle <see cref="System.Single"/>
 /// </param>
 /// <param name="radius">
 /// radius of the circle <see cref="System.Single"/>
 /// </param>
 /// <param name="circumference_steps">
 /// number of steps to use when drawing the circle <see cref="System.Int32"/>
 /// </param>
 /// <returns>
 /// polygon representing a circle <see cref="polygon2D"/>
 /// </returns>
 public static polygon2D CreateCircle(float centre_x, float centre_y,
                                      float radius, int circumference_steps)
 {
     polygon2D circle = new polygon2D();
     for (int i = 0; i < circumference_steps; i++)
     {
         float angle = i * (float)Math.PI * 2 / circumference_steps;
         float x = centre_x + (radius * (float)Math.Sin(angle));
         float y = centre_y + (radius * (float)Math.Cos(angle));
         circle.Add(x, y);
     }
     return(circle);
 }
Пример #5
0
        /// <summary>
        /// initialise the snake based upon a polygon shape
        /// </summary>
        /// <param name="binary_image"></param>
        /// <param name="BlackOnWhite"></param>
        /// <param name="initial_points"></param>
        /// <param name="max_itterations"></param>
        /// <param name="rnd"></param>
        public void Snake(bool[,] binary_image, bool BlackOnWhite,
                          polygon2D initial_points,
                          int max_itterations,
                          Random rnd)
        {
            if (initial_points.x_points.Count > 1)
            {
                // get the perimeter length of the initial shape
                float perimeter_length = initial_points.getPerimeterLength();

                // distribute points evenly along the perimeter
                int   side_index        = 0;
                float side_length_total = 0;
                for (int i = 0; i < no_of_points; i++)
                {
                    // position of this point along the perimeter
                    float perimeter_position = i * perimeter_length / no_of_points;

                    float total = side_length_total;
                    while (total < perimeter_position)
                    {
                        side_length_total = total;
                        total            += initial_points.getSideLength(side_index);
                        if (total < perimeter_position)
                        {
                            side_index++;
                        }
                    }

                    float side_length = initial_points.getSideLength(side_index);
                    if (side_length > 0)
                    {
                        float perimeter_diff = perimeter_position - side_length_total;
                        float fraction = perimeter_diff / side_length;
                        float tx = 0, ty = 0, bx = 0, by = 0;
                        initial_points.getSidePositions(side_index, ref tx, ref ty, ref bx, ref by);
                        float dx = bx - tx;
                        float dy = by - ty;
                        SnakePoint[i, SNAKE_X] = tx + (dx * fraction);
                        SnakePoint[i, SNAKE_Y] = ty + (dy * fraction);
                    }
                }

                Snake(binary_image, BlackOnWhite, max_itterations, rnd);
            }
        }
Пример #6
0
        /// <summary>
        /// returns a copy of the polygon
        /// </summary>
        /// <returns></returns>
        public polygon2D Copy()
        {
            polygon2D new_poly = new polygon2D();
            new_poly.name = name;
            new_poly.type = type;
            new_poly.occupied = occupied;

            if (x_points != null)
            {
                for (int i = 0; i < x_points.Count; i++)
                {
                    float x = x_points[i];
                    float y = y_points[i];
                    new_poly.Add(x, y);
                }
            }
            return (new_poly);
        }
Пример #7
0
        /// <summary>
        /// rescales the grid to a larger or smaller image
        /// </summary>
        /// <param name="original_image_width"></param>
        /// <param name="original_image_height"></param>
        /// <param name="new_image_width"></param>
        /// <param name="new_image_height"></param>
        /// <returns></returns>
        public grid2D Scale(int original_image_width, int original_image_height,
                            int new_image_width, int new_image_height)
        {
            polygon2D new_perimeter = perimeter.Copy();

            for (int i = 0; i < new_perimeter.x_points.Count; i++)
            {
                float x = (float)new_perimeter.x_points[i] * new_image_width / original_image_width;
                float y = (float)new_perimeter.y_points[i] * new_image_height / original_image_height;
                new_perimeter.x_points[i] = x;
                new_perimeter.y_points[i] = y;
            }

            grid2D new_grid = new grid2D(cell.Length, cell[0].Length);

            new_grid.init(cell.Length, cell[0].Length,
                          new_perimeter, 0, false);
            return(new_grid);
        }
Пример #8
0
        /// <summary>
        /// initialise the grid
        /// </summary>
        /// <param name="dimension_x"></param>
        /// <param name="dimension_y"></param>
        /// <param name="perimeter"></param>
        /// <param name="border_cells"></param>
        /// <param name="simple_orientation"></param>
        public void init(int dimension_x, int dimension_y,
                         polygon2D perimeter, int border_cells,
                         bool simple_orientation)
        {
            this.border_cells = border_cells;
            this.perimeter    = perimeter;

            cell = new grid2Dcell[dimension_x][];
            for (int x = 0; x < dimension_x; x++)
            {
                cell[x] = new grid2Dcell[dimension_y];
            }

            line = new ArrayList[2];

            float length3, length4;
            int   index = 0;

            for (int i = 0; i < 2; i++)
            {
                line[i] = new ArrayList();

                int idx1 = index + i;
                if (idx1 >= 4)
                {
                    idx1 -= 4;
                }
                int idx2 = index + i + 1;
                if (idx2 >= 4)
                {
                    idx2 -= 4;
                }
                float x0 = (float)perimeter.x_points[idx1];
                float y0 = (float)perimeter.y_points[idx1];
                float x1 = (float)perimeter.x_points[idx2];
                float y1 = (float)perimeter.y_points[idx2];

                int next_idx1 = idx1 + 1;
                if (next_idx1 >= 4)
                {
                    next_idx1 -= 4;
                }
                length3 = perimeter.getSideLength(next_idx1);

                float w0 = Math.Abs(x1 - x0);
                float h0 = Math.Abs(y1 - y0);

                int idx3 = index + i + 2;
                if (idx3 >= 4)
                {
                    idx3 -= 4;
                }
                int idx4 = index + i + 3;
                if (idx4 >= 4)
                {
                    idx4 -= 4;
                }
                float x2 = (float)perimeter.x_points[idx3];
                float y2 = (float)perimeter.y_points[idx3];
                float x3 = (float)perimeter.x_points[idx4];
                float y3 = (float)perimeter.y_points[idx4];

                int next_idx3 = next_idx1 + 2;
                if (next_idx3 >= 4)
                {
                    next_idx3 -= 4;
                }
                length4 = perimeter.getSideLength(next_idx3);

                float w1 = Math.Abs(x3 - x2);
                float h1 = Math.Abs(y3 - y2);

                int dimension = dimension_x;
                if (!simple_orientation)
                {
                    if (i > 0)
                    {
                        dimension = dimension_y;
                    }
                }
                else
                {
                    if (h0 > w0)
                    {
                        dimension = dimension_y;
                    }
                }

                // how much shorter is one line than the other on the opposite axis?
                float shortening = 0;
                //if (h0 > w0)
                {
                    if (length3 > length4)
                    {
                        shortening = (length3 - length4) / length3;
                    }
                    else
                    {
                        shortening = (length4 - length3) / length4;
                    }
                }


                for (int j = -border_cells; j <= dimension + border_cells; j++)
                {
                    // locate the position along the first line
                    float xx0, yy0;  // position along the first line

                    float fraction = j / (float)dimension;

                    // modify for foreshortening
                    //if ((h0 > w0) && (shortening > 0))
                    if (shortening > 0)
                    {
                        fraction = (fraction * (1.0f - shortening)) + ((float)Math.Sin(fraction * (float)Math.PI / 2) * shortening);
                        if (length3 > length4)
                        {
                            fraction = 1.0f - fraction;
                        }
                    }

                    if (w0 > h0)
                    {
                        float grad = (y1 - y0) / (x1 - x0);
                        if (x1 > x0)
                        {
                            xx0 = x0 + (w0 * fraction);
                        }
                        else
                        {
                            xx0 = x0 - (w0 * fraction);
                        }
                        yy0 = y0 + ((xx0 - x0) * grad);
                    }
                    else
                    {
                        float grad = (x1 - x0) / (y1 - y0);
                        if (y1 > y0)
                        {
                            yy0 = y0 + (h0 * fraction);
                        }
                        else
                        {
                            yy0 = y0 - (h0 * fraction);
                        }
                        xx0 = x0 + ((yy0 - y0) * grad);
                    }

                    // locate the position along the second line
                    float xx1, yy1;  // position along the second line

                    if (w1 > h1)
                    {
                        float grad = (y2 - y3) / (x2 - x3);
                        if (x2 > x3)
                        {
                            xx1 = x3 + (w1 * fraction);
                        }
                        else
                        {
                            xx1 = x3 - (w1 * fraction);
                        }
                        yy1 = y3 + ((xx1 - x3) * grad);
                    }
                    else
                    {
                        float grad = (x2 - x3) / (y2 - y3);
                        if (y2 > y3)
                        {
                            yy1 = y3 + (h1 * fraction);
                        }
                        else
                        {
                            yy1 = y3 - (h1 * fraction);
                        }
                        xx1 = x3 + ((yy1 - y3) * grad);
                    }

                    // add the line to the list
                    line[i].Add(xx0);
                    line[i].Add(yy0);
                    line[i].Add(xx1);
                    line[i].Add(yy1);
                }
            }

            // find interceptions between lines
            poltLineIntercepts();

            // create grid cells
            initialiseCells();
        }
Пример #9
0
        /// <summary>
        /// shows the detected centre square
        /// </summary>
        /// <param name="filename">raw image filename</param>
        /// <param name="square">square to be displayed</param>
        /// <param name="output_filename">filename to save as</param>
        private static void ShowSquare(string filename, polygon2D square,
                                       string output_filename)
        {
            Bitmap bmp = (Bitmap)Bitmap.FromFile(filename);
            byte[] img = new byte[bmp.Width * bmp.Height * 3];
            BitmapArrayConversions.updatebitmap(bmp, img);
            square.show(img, bmp.Width, bmp.Height, 0, 255, 0, 0);

            Bitmap output_bmp = new Bitmap(bmp.Width, bmp.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            BitmapArrayConversions.updatebitmap_unsafe(img, output_bmp);
            if (output_filename.ToLower().EndsWith("jpg"))
                output_bmp.Save(output_filename, System.Drawing.Imaging.ImageFormat.Jpeg);
            if (output_filename.ToLower().EndsWith("bmp"))
                output_bmp.Save(output_filename, System.Drawing.Imaging.ImageFormat.Bmp);
        }
Пример #10
0
        /// <summary>
        /// simple function used to test grid creation
        /// </summary>
        /// <param name="filename">filename of the test image to be created</param>
        public static void Test(string filename)
        {
            int image_width = 640;
            int image_height = 480;
            int dimension_x = 10;
            int dimension_y = 10;

            Bitmap bmp = new Bitmap(image_width, image_height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            byte[] img = new byte[image_width * image_height * 3];

            polygon2D test_poly;
            grid2D grid;

            test_poly = new polygon2D();
            test_poly.Add(image_width * 15 / 100, image_height * 20 / 100);
            test_poly.Add(image_width * 40 / 100, image_height * 20 / 100);
            test_poly.Add(image_width * 40 / 100, image_height * 40 / 100);
            test_poly.Add(image_width * 15 / 100, image_height * 40 / 100);
            grid = new grid2D(dimension_x, dimension_y, test_poly, 0, false);
            grid.ShowLines(img, image_width, image_height, 0, 255, 0, 0);

            int half_width = image_width / 2;
            test_poly = new polygon2D();
            test_poly.Add(half_width + (image_width * 20 / 100), image_height * 20 / 100);
            test_poly.Add(half_width + (image_width * 35 / 100), image_height * 20 / 100);
            test_poly.Add(half_width + (image_width * 40 / 100), image_height * 40 / 100);
            test_poly.Add(half_width + (image_width * 15 / 100), image_height * 40 / 100);
            grid = new grid2D(dimension_x, dimension_y, test_poly, 0, false);
            grid.ShowLines(img, image_width, image_height, 0, 255, 0, 0);
            
            int half_height = image_height / 2;
            test_poly = new polygon2D();
            test_poly.Add(image_width * 15 / 100, half_height + (image_height * 24 / 100));
            test_poly.Add(image_width * 40 / 100, half_height + (image_height * 20 / 100));
            test_poly.Add(image_width * 40 / 100, half_height + (image_height * 40 / 100));
            test_poly.Add(image_width * 15 / 100, half_height + (image_height * 36 / 100));
            grid = new grid2D(dimension_x, dimension_y, test_poly, 0, false);
            grid.ShowLines(img, image_width, image_height, 0, 255, 0, 0);

            test_poly = new polygon2D();
            test_poly.Add(half_width + (image_width * 20 / 100), half_height + (image_height * 24 / 100));
            test_poly.Add(half_width + (image_width * 35 / 100), half_height + (image_height * 20 / 100));
            test_poly.Add(half_width + (image_width * 40 / 100), half_height + (image_height * 40 / 100));
            test_poly.Add(half_width + (image_width * 15 / 100), half_height + (image_height * 36 / 100));
            grid = new grid2D(dimension_x, dimension_y, test_poly, 0, false);
            grid.ShowLines(img, image_width, image_height, 0, 255, 0, 0);            

            BitmapArrayConversions.updatebitmap_unsafe(img, bmp);
            bmp.Save(filename);
        }
Пример #11
0
        /// <summary>
        /// locates the centre position of a spot
        /// </summary>
        /// <param name="raw_image_mono">mono image data</param>
        /// <param name="raw_image_width">image width</param>
        /// <param name="raw_image_height">image height</param>
        /// <param name="search_region">region within which to search</param>
        /// <param name="black_on_white">whether this image contains dark markings on a lighter background</param>
        /// <param name="centre_x">returned x centre position</param>
        /// <param name="centre_y">returned y centre position</param>
        private static unsafe void LocateSpotCentre(byte* raw_image_mono,
                                                    int raw_image_width, int raw_image_height,
                                                    polygon2D search_region,
                                                    bool black_on_white,
                                                    ref float centre_x, ref float centre_y)
        {
            centre_x = 0;
            centre_y = 0;

            // get dimensions of the region to be searched
            int tx = (int)search_region.left();
            //int ty = (int)search_region.top();
            int bx = (int)search_region.right();
            //int by = (int)search_region.bottom();

            int r = (bx - tx) / 3;
            if (r < 1) r = 1;
            int search_r = (bx - tx) / 4;
            if (search_r < 1) search_r = 1;

            // centre of the search region
            float search_centre_x = 0;
            float search_centre_y = 0;
            search_region.GetSquareCentre(ref search_centre_x, ref search_centre_y);
            //search_region.getCentreOfGravity(ref search_centre_x, ref search_centre_y);

            int image_pixels = raw_image_width * raw_image_height;
            float max = 0;
            float v;
            for (float offset_y = search_centre_y - search_r; offset_y <= search_centre_y + search_r; offset_y += 0.5f)
            {
                for (float offset_x = search_centre_x - search_r; offset_x <= search_centre_x + search_r; offset_x += 0.5f)
                {
                    float tot = 0;
                    for (int yy = (int)(offset_y - r); yy <= (int)(offset_y + r); yy += 2)
                    {
                        int n0 = yy * raw_image_width;
                        for (int xx = (int)(offset_x - r); xx <= (int)(offset_x + r); xx += 2)
                        {
                            int n1 = n0 + xx;
                            if ((n1 > -1) && (n1 < image_pixels))
                            {
                                if (black_on_white)
                                    v = 255 - raw_image_mono[n1];
                                else
                                    v = raw_image_mono[n1];
                                tot += v * v;
                            }
                        }
                    }
                    if (tot > max)
                    {
                        max = tot;
                        centre_x = offset_x;
                        centre_y = offset_y;
                    }
                }
            }
        }
Пример #12
0
 /// <summary>
 /// constructor
 /// </summary>
 /// <param name="dimension_x">number of cells across the grid</param>
 /// <param name="dimension_y">number of cells down the grid</param>
 /// <param name="perimeter">perimeter of the grid</param>
 /// <param name="border_cells">number of cells to use as a border around the grid</param>
 /// <param name="orientation_simple"></param>
 public grid2D(int dimension_x, int dimension_y,
               polygon2D perimeter, int border_cells,
               bool orientation_simple)
 {
     init(dimension_x, dimension_y, perimeter, border_cells, orientation_simple);
 }
Пример #13
0
        /// <summary>
        /// detect a grid within the given image using the given perimeter polygon
        /// </summary>
        /// <param name="img">image data</param>
        /// <param name="img_width">width of the image</param>
        /// <param name="img_height">height of the image</param>
        /// <param name="bytes_per_pixel">number of bytes per pixel</param>
        /// <param name="perimeter">bounding perimeter within which the grid exists</param>
        /// <param name="spot_centres">previously detected spot centres</param>
        /// <param name="minimum_dimension_horizontal">minimum number of cells across</param>
        /// <param name="maximum_dimension_horizontal">maximum number of cells across</param>
        /// <param name="minimum_dimension_vertical">minimum number of cells down</param>
        /// <param name="maximum_dimension_vertical">maximum number of cells down</param>
        /// <param name="known_grid_spacing">known grid spacing (cell diameter) value in pixels</param>
        /// <param name="known_even_dimension">set to true if it is known that the number of cells in horizontal and vertical axes is even</param>
        /// <param name="border_cells">extra cells to add as a buffer zone around the grid</param>
        /// <param name="horizontal_scale_spacings">description used on the spacings diagram</param>
        /// <param name="vertical_scale_spacings">description used on the spacings diagram</param>
        /// <returns>2D grid</returns>
        public static grid2D DetectGrid(byte[] img, int img_width, int img_height, int bytes_per_pixel,
                                        polygon2D perimeter, ArrayList spot_centres,
                                        int minimum_dimension_horizontal, int maximum_dimension_horizontal,
                                        int minimum_dimension_vertical, int maximum_dimension_vertical,
                                        float known_grid_spacing, bool known_even_dimension,
                                        int border_cells,
                                        String horizontal_scale_spacings, String vertical_scale_spacings,
                                        ref float average_spacing_horizontal, ref float average_spacing_vertical,
                                        ref byte[] output_img, int output_img_type)
        {
            int tx = (int)perimeter.left();
            int ty = (int)perimeter.top();
            int bx = (int)perimeter.right();
            int by = (int)perimeter.bottom();

            // adjust spot centre positions so that they're relative to the perimeter
            // top left position
            if (spot_centres != null)
            {
                for (int i = 0; i < spot_centres.Count; i += 2)
                {
                    spot_centres[i] = (float)spot_centres[i] - tx;
                    spot_centres[i + 1] = (float)spot_centres[i + 1] - ty;
                }
            }

            int wdth = bx - tx;
            int hght = by - ty;

            // create an image of the grid area
            byte[] grid_img = image.createSubImage(img, img_width, img_height, bytes_per_pixel,
                                                   tx, ty, bx, by);

            // get the orientation of the perimeter
            float dominant_orientation = perimeter.GetSquareOrientation();

            // find the horizontal and vertical dimensions of the grid perimeter
            float grid_horizontal = perimeter.GetSquareHorizontal();
            float grid_vertical = perimeter.GetSquareVertical();

            // detect grid within the perimeter
            int cells_horizontal = 0, cells_vertical = 0;
            float horizontal_phase_offset = 0;
            float vertical_phase_offset = 0;

            if (spot_centres == null)
                DetectGrid(grid_img, wdth, hght, bytes_per_pixel,
                           dominant_orientation, known_grid_spacing,
                           grid_horizontal, grid_vertical,
                           minimum_dimension_horizontal, maximum_dimension_horizontal,
                           minimum_dimension_vertical, maximum_dimension_vertical,
                           horizontal_scale_spacings, vertical_scale_spacings,
                           ref average_spacing_horizontal, ref average_spacing_vertical,
                           ref horizontal_phase_offset, ref vertical_phase_offset,
                           ref cells_horizontal, ref cells_vertical,
                           ref output_img, img_width, img_height, output_img_type);
            else
                DetectGrid(spot_centres, grid_img, wdth, hght, bytes_per_pixel,
                           dominant_orientation, known_grid_spacing,
                           grid_horizontal, grid_vertical,
                           minimum_dimension_horizontal, maximum_dimension_horizontal,
                           minimum_dimension_vertical, maximum_dimension_vertical,
                           horizontal_scale_spacings, vertical_scale_spacings,
                           ref average_spacing_horizontal, ref average_spacing_vertical,
                           ref horizontal_phase_offset, ref vertical_phase_offset,
                           ref cells_horizontal, ref cells_vertical,
                           ref output_img, img_width, img_height, output_img_type);


            grid2D detectedGrid = null;

            // apply some range limits
            bool range_limited = false;
            if (cells_horizontal < 3)
            {
                cells_horizontal = 3;
                range_limited = true;
            }
            if (cells_vertical < 3)
            {
                cells_vertical = 3;
                range_limited = true;
            }
            if (cells_horizontal > maximum_dimension_horizontal)
            {
                cells_horizontal = maximum_dimension_horizontal;
                range_limited = true;
            }
            if (cells_vertical > maximum_dimension_vertical)
            {
                cells_vertical = maximum_dimension_vertical;
                range_limited = true;
            }
            if (range_limited)
            {
                Console.WriteLine("WARNING: When detecting the grid the matrix dimension had to be artificially restricted.");
                Console.WriteLine("         This probably means that there is a problem with the original image");
            }

            // if we know the number of cells should be even correct any inaccuracies
            if (known_even_dimension)
            {
                cells_horizontal = (int)(cells_horizontal / 2) * 2;
                cells_vertical = (int)(cells_vertical / 2) * 2;
            }

            // get the centre of the region
            float cx = tx + ((bx - tx) / 2);
            float cy = ty + ((by - ty) / 2);

            detectedGrid = new grid2D(cells_horizontal, cells_vertical,
                                      cx, cy, dominant_orientation,
                                      average_spacing_horizontal, average_spacing_vertical,
                                      horizontal_phase_offset, vertical_phase_offset,
                                      border_cells);

            return (detectedGrid);
        }
Пример #14
0
        private void init(int dimension_x, int dimension_y,
                          polygon2D perimeter, int border_cells)
        {
            this.perimeter = perimeter;

            cell = new grid2Dcell[dimension_x, dimension_y];

            line = new ArrayList[2];

            int index = 0;
            for (int i = 0; i < 2; i++)
            {
                line[i] = new ArrayList();

                int idx1 = index + i;
                if (idx1 >= 4) idx1 -= 4;
                int idx2 = index + i + 1;
                if (idx2 >= 4) idx2 -= 4;
                float x0 = (float)perimeter.x_points[idx1];
                float y0 = (float)perimeter.y_points[idx1];
                float x1 = (float)perimeter.x_points[idx2];
                float y1 = (float)perimeter.y_points[idx2];

                float w0 = Math.Abs(x1 - x0);
                float h0 = Math.Abs(y1 - y0);

                int idx3 = index + i + 2;
                if (idx3 >= 4) idx3 -= 4;
                int idx4 = index + i + 3;
                if (idx4 >= 4) idx4 -= 4;
                float x2 = (float)perimeter.x_points[idx3];
                float y2 = (float)perimeter.y_points[idx3];
                float x3 = (float)perimeter.x_points[idx4];
                float y3 = (float)perimeter.y_points[idx4];

                float w1 = Math.Abs(x3 - x2);
                float h1 = Math.Abs(y3 - y2);

                int dimension = dimension_x;
                if (h0 > w0) dimension = dimension_y;

                for (int j = -border_cells; j <= dimension + border_cells; j++)
                {
                    // locate the position along the first line
                    float xx0, yy0;  // position along the first line

                    if (w0 > h0)
                    {
                        float grad = (y1 - y0) / (x1 - x0);
                        if (x1 > x0)
                            xx0 = x0 + (w0 * j / dimension);
                        else
                            xx0 = x0 - (w0 * j / dimension);
                        yy0 = y0 + ((xx0 - x0) * grad);
                    }
                    else
                    {
                        float grad = (x1 - x0) / (y1 - y0);
                        if (y1 > y0)
                            yy0 = y0 + (h0 * j / dimension);
                        else
                            yy0 = y0 - (h0 * j / dimension);
                        xx0 = x0 + ((yy0 - y0) * grad);
                    }

                    // locate the position along the second line
                    float xx1, yy1;  // position along the second line

                    if (w1 > h1)
                    {
                        float grad = (y2 - y3) / (x2 - x3);
                        if (x2 > x3)
                            xx1 = x3 + (w1 * j / dimension);
                        else
                            xx1 = x3 - (w1 * j / dimension);
                        yy1 = y3 + ((xx1 - x3) * grad);
                    }
                    else
                    {
                        float grad = (x2 - x3) / (y2 - y3);
                        if (y2 > y3)
                            yy1 = y3 + (h1 * j / dimension);
                        else
                            yy1 = y3 - (h1 * j / dimension);
                        xx1 = x3 + ((yy1 - y3) * grad);
                    }

                    // add the line to the list
                    line[i].Add(xx0);
                    line[i].Add(yy0);
                    line[i].Add(xx1);
                    line[i].Add(yy1);
                }
            }

            // find interceptions between lines
            poltLineIntercepts();

            // create grid cells
            initialiseCells();
        }
Пример #15
0
        /// <summary>
        /// locates the centre position of a spot
        /// </summary>
        /// <param name="raw_image_mono">mono image data</param>
        /// <param name="raw_image_width">image width</param>
        /// <param name="raw_image_height">image height</param>
        /// <param name="search_region">region within which to search</param>
        /// <param name="black_on_white">whether this image contains dark markings on a lighter background</param>
        /// <param name="centre_x">returned x centre position</param>
        /// <param name="centre_y">returned y centre position</param>
        private static unsafe void LocateSpotCentre(byte *raw_image_mono,
                                                    int raw_image_width, int raw_image_height,
                                                    polygon2D search_region,
                                                    bool black_on_white,
                                                    ref float centre_x, ref float centre_y)
        {
            centre_x = 0;
            centre_y = 0;

            // get dimensions of the region to be searched
            int tx = (int)search_region.left();
            //int ty = (int)search_region.top();
            int bx = (int)search_region.right();
            //int by = (int)search_region.bottom();

            int r = (bx - tx) / 3;

            if (r < 1)
            {
                r = 1;
            }
            int search_r = (bx - tx) / 4;

            if (search_r < 1)
            {
                search_r = 1;
            }

            // centre of the search region
            float search_centre_x = 0;
            float search_centre_y = 0;

            search_region.GetSquareCentre(ref search_centre_x, ref search_centre_y);
            //search_region.getCentreOfGravity(ref search_centre_x, ref search_centre_y);

            int   image_pixels = raw_image_width * raw_image_height;
            float max          = 0;
            float v;

            for (float offset_y = search_centre_y - search_r; offset_y <= search_centre_y + search_r; offset_y += 0.5f)
            {
                for (float offset_x = search_centre_x - search_r; offset_x <= search_centre_x + search_r; offset_x += 0.5f)
                {
                    float tot = 0;
                    for (int yy = (int)(offset_y - r); yy <= (int)(offset_y + r); yy += 2)
                    {
                        int n0 = yy * raw_image_width;
                        for (int xx = (int)(offset_x - r); xx <= (int)(offset_x + r); xx += 2)
                        {
                            int n1 = n0 + xx;
                            if ((n1 > -1) && (n1 < image_pixels))
                            {
                                if (black_on_white)
                                {
                                    v = 255 - raw_image_mono[n1];
                                }
                                else
                                {
                                    v = raw_image_mono[n1];
                                }
                                tot += v * v;
                            }
                        }
                    }
                    if (tot > max)
                    {
                        max      = tot;
                        centre_x = offset_x;
                        centre_y = offset_y;
                    }
                }
            }
        }
Пример #16
0
        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="dimension_x">number of cells across the grid</param>
        /// <param name="dimension_y">number of cells down the grid</param>
        /// <param name="cx">centre of the grid</param>
        /// <param name="cy">centre of the grid</param>
        /// <param name="orientation">orientation of the grid in radians</param>
        /// <param name="average_spacing_x">grid spacing in the x axis</param>
        /// <param name="average_spacing_y">grid spacing in the y axis</param>
        /// <param name="phase_offset_x">phase offset in the x axis</param>
        /// <param name="phase_offset_y">phase offset in the y axis</param>
        /// <param name="border_cells">number of cells to use as a border around the grid</param>
        public grid2D(int dimension_x, int dimension_y,
                      float cx, float cy,
                      float orientation,
                      float average_spacing_x, float average_spacing_y,
                      float phase_offset_x, float phase_offset_y,
                      int border_cells,
                      bool orientation_simple)
        {
            // create a perimeter region
            polygon2D perimeter = new polygon2D();

            float length_x      = average_spacing_x * dimension_x;
            float length_y      = average_spacing_y * dimension_y;
            float half_length_x = length_x / 2;
            float half_length_y = length_y / 2;

            // adjust for phase
            cx += (average_spacing_x * phase_offset_x / (2 * (float)Math.PI)) * (float)Math.Sin(orientation);
            cy -= (average_spacing_y * phase_offset_y / (2 * (float)Math.PI)) * (float)Math.Cos(orientation);

            // find the mid point of the top line
            float px1 = cx + (half_length_y * (float)Math.Sin(orientation));
            float py1 = cy + (half_length_y * (float)Math.Cos(orientation));

            // find the top left vertex
            float x0 = px1 + (half_length_x * (float)Math.Sin(orientation - (float)(Math.PI / 2)));
            float y0 = py1 + (half_length_x * (float)Math.Cos(orientation - (float)(Math.PI / 2)));

            // find the top right vertex
            float x1 = px1 + (half_length_x * (float)Math.Sin(orientation + (float)(Math.PI / 2)));
            float y1 = py1 + (half_length_x * (float)Math.Cos(orientation + (float)(Math.PI / 2)));

            // find the bottom vertices by mirroring around the centre
            float x2 = cx + (cx - x0);
            float y2 = cy + (cy - y0);
            float x3 = cx - (x1 - cx);
            float y3 = cy - (y1 - cy);

            // update polygon with the perimeter vertices
            perimeter.Add(x0, y0);
            perimeter.Add(x1, y1);
            perimeter.Add(x2, y2);
            perimeter.Add(x3, y3);

            int   dim_x              = dimension_x;
            int   dim_y              = dimension_y;
            float first_side_length  = perimeter.getSideLength(0);
            float second_side_length = perimeter.getSideLength(1);

            if (((dimension_x > dimension_y + 2) &&
                 (second_side_length > first_side_length)) ||
                ((dimension_y > dimension_x + 2) &&
                 (first_side_length > second_side_length)))
            {
                dim_x = dimension_y;
                dim_y = dimension_x;
            }

            // initialise using this perimeter
            init(dim_x, dim_y, perimeter, border_cells, orientation_simple);
        }
Пример #17
0
 /// <summary>
 /// constructor
 /// </summary>
 /// <param name="dimension_x">number of cells across the grid</param>
 /// <param name="dimension_y">number of cells down the grid</param>
 /// <param name="perimeter">perimeter of the grid</param>
 /// <param name="border_cells">number of cells to use as a border around the grid</param>
 /// <param name="orientation_simple"></param>
 public grid2D(int dimension_x, int dimension_y,
               polygon2D perimeter, int border_cells,
               bool orientation_simple)
 {
     init(dimension_x, dimension_y, perimeter, border_cells, orientation_simple);
 }
Пример #18
0
        /// <summary>
        /// returns an ideal grid with perfectly regular spacing
        /// </summary>
        /// <param name="grid"></param>
        /// <param name="image_width"></param>
        /// <param name="image_height"></param>
        /// <returns>
        /// </returns>
        private static grid2D GetIdealGrid(CalibrationDot[,] grid,
                                           int image_width, int image_height)
        {
            grid2D ideal_grid = null;
            float ideal_spacing = 0;
            double centre_x = image_width / 2;
            double centre_y = image_height / 2;            
            double min_dist = double.MaxValue;
            
            int grid_cx=0, grid_cy=0;
            
            for (int x = 0; x < grid.GetLength(0); x++)
            {
                for (int y = 0; y < grid.GetLength(1); y++)
                {
                    if (grid[x, y] != null)
                    {
                        double dx = grid[x, y].x - centre_x;
                        double dy = grid[x, y].y - centre_y;
                        double dist = dx*dx + dy*dy;
                        if (dist < min_dist)
                        {
                            min_dist = dist;
                            grid_cx = x;
                            grid_cy = y;
                        }
                    }
                }
            }
            
            if (grid_cx > 0)
            {
                int[] orientation_histogram = new int[361];
                List<double>[] orientations = new List<double>[361];
                double average_dist = 0;
                int hits = 0;
                
                int local_search = 2;
                for (int x = grid_cx - local_search; x <= grid_cx + local_search; x++)
                {
                    if ((x >= 0) && (x < grid.GetLength(0)-1))
                    {
                        for (int y = grid_cy - local_search; y <= grid_cy + local_search; y++)
                        {
                            if ((y >= 1) && (y < grid.GetLength(1)-1))
                            {
                                if (grid[x, y] != null)
                                {
                                    for (int i = 0; i < grid[x, y].Links.Count; i++)
                                    {
                                        CalibrationLink link = (CalibrationLink)grid[x, y].Links[i];
                                        CalibrationDot from_dot = (CalibrationDot)link.From;
                                        
                                        double dx = grid[x, y].x - from_dot.x;
                                        double dy = grid[x, y].y - from_dot.y;
                                        double dist = Math.Sqrt(dx*dx + dy*dy);
                                        
                                        if (dist > 0)
                                        {
                                            double orientation = Math.Asin(dx / dist);
                                            if (orientation < 0) orientation += Math.PI;
                                            if (dy < 0) orientation = (Math.PI * 2) - orientation;
                                            orientation = orientation / Math.PI * 180;
                                            int bucket = (int)orientation;
                                            orientation_histogram[bucket]++;
                                            if (orientations[bucket] == null) orientations[bucket] = new List<double>();
                                            orientations[bucket].Add(orientation);
                                        
                                            average_dist += Math.Sqrt(dx*dx + dy*dy);
                                            hits++;
                                        }
                                    }
                                    
                                }
                            }
                        }
                    }
                }
                if (hits > 0) average_dist = average_dist / hits;
                ideal_spacing = (float)average_dist;
                
                int max_orientation_response = 0;
                int best_ang = 0;
                for (int ang = 0; ang < 90; ang++)
                {
                    int response = orientation_histogram[ang] +
                                   orientation_histogram[ang + 90] + 
                                   orientation_histogram[ang + 180];
                    if (response > max_orientation_response)
                    {
                        max_orientation_response = response;
                        best_ang = ang;
                    }
                }
                double average_orientation = 0;
                hits = 0;
                for (int offset = 0; offset < 3; offset++)
                {
                    if (orientations[best_ang + offset] != null)
                    {
                        for (int ang = 0; ang < orientations[best_ang + offset].Count; ang++)
                        {
                            average_orientation += orientations[best_ang + offset][ang] - (Math.PI*offset/2);
                            hits++;
                        }
                    }
                }
                if (hits > 0)
                {
                    average_orientation /= hits;
                    float pattern_orientation = (float)average_orientation;
                    
                    float offset_x = (float)grid[grid_cx, grid_cy].x;
                    float offset_y = (float)grid[grid_cx, grid_cy].y;
                    float r = ideal_spacing * dots_across;
                    
                    polygon2D perimeter = new polygon2D();
                    perimeter.Add(-r + offset_x, -r + offset_y);
                    perimeter.Add(r + offset_x, -r + offset_y);
                    perimeter.Add(r + offset_x, r + offset_y);
                    perimeter.Add(-r + offset_x, r + offset_y);
                    perimeter.rotate((float)average_orientation / 180 * (float)Math.PI, offset_x, offset_y);
                    ideal_grid = new grid2D(dots_across*2, dots_across*2, perimeter, 0, false);
                    
                    int grid_width = grid.GetLength(0);
                    int grid_height = grid.GetLength(1);
                    int idx = 0;
                    int xx=0, yy=0;
                    float ideal_x, ideal_y;
       
                    for (int orient = 0; orient < 8; orient++)
                    {
                        for (int x = 0; x < grid_width; x++)
                        {
                            for (int y = 0; y < grid_height; y++)
                            {
                                if (grid[x, y] != null)
                                {
                                    switch(orient)
                                    {
                                        case 0:
                                        {
                                            xx = (x - grid_cx) + dots_across;
                                            yy = (y - grid_cy) + dots_across;
                                            break;
                                        }
                                        case 1:
                                        {
                                            xx = (x - grid_cx) + dots_across;
                                            yy = (grid_cy - y) + dots_across;
                                            break;
                                        }
                                        case 2:
                                        {
                                            xx = (grid_cx - x) + dots_across;
                                            yy = (y - grid_cy) + dots_across;
                                            break;
                                        }
                                        case 3:
                                        {
                                            xx = (grid_cx - x) + dots_across;
                                            yy = (grid_cy - y) + dots_across;
                                            break;
                                        }
                                        case 4:
                                        {
                                            xx = (y - grid_cy) + dots_across;
                                            yy = (x - grid_cx) + dots_across;
                                            break;
                                        }
                                        case 5:
                                        {
                                            xx = (y - grid_cy) + dots_across;
                                            yy = (grid_cx - x) + dots_across;
                                            break;
                                        }
                                        case 6:
                                        {
                                            xx = (grid_cy - y) + dots_across;
                                            yy = (x - grid_cx) + dots_across;
                                            break;
                                        }
                                        case 7:
                                        {
                                            xx = (grid_cy - y) + dots_across;
                                            yy = (grid_cx - x) + dots_across;
                                            break;
                                        }
                                    }
                                    
                                    if ((xx >= 0) && (xx < ideal_grid.cell.Length) &&
                                        (yy >= 0) && (yy < ideal_grid.cell[0].Length))
                                    {
                                        ideal_x = ideal_grid.cell[xx][yy].perimeter.x_points[idx];
                                        ideal_y = ideal_grid.cell[xx][yy].perimeter.y_points[idx];
                                    
                                        if (orient == 0)
                                        {
                                            grid[x, y].rectified_x = ideal_x;
                                            grid[x, y].rectified_y = ideal_y;
                                        }
                                        else
                                        {
                                            double diff_x1 = grid[x, y].rectified_x - grid[x, y].x;
                                            double diff_y1 = grid[x, y].rectified_y - grid[x, y].y;
                                            double dist1 = diff_x1*diff_x1 + diff_y1*diff_y1;

                                            double diff_x2 = ideal_x - grid[x, y].x;
                                            double diff_y2 = ideal_y - grid[x, y].y;
                                            double dist2 = diff_x2*diff_x2 + diff_y2*diff_y2;
                                            
                                            if (dist2 < dist1)
                                            {
                                                grid[x, y].rectified_x = ideal_x;
                                                grid[x, y].rectified_y = ideal_y;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                
            }
            
            return(ideal_grid);
        }
Пример #19
0
 /// <summary>
 /// returns a copy of this polygon with each vetex randomly perturbed
 /// </summary>
 /// <param name="max_displacement">
 /// maximum perturbation <see cref="System.Single"/>
 /// </param>
 /// <param name="rnd">
 /// random number generator <see cref="Random"/>
 /// </param>
 /// <returns>
 /// polygon object <see cref="polygon2D"/>
 /// </returns>
 public polygon2D Jiggle(float max_displacement, Random rnd)
 {
     polygon2D result = null;
     
     if (x_points != null)
     {
         result = new polygon2D();
         float max = max_displacement*2;
         for (int i = 0; i < x_points.Count; i++)
         {
             float jiggled_x = x_points[i] + ((float)rnd.NextDouble() * max) - max_displacement;
             float jiggled_y = x_points[i] + ((float)rnd.NextDouble() * max) - max_displacement;
             result.Add(jiggled_x, jiggled_y);
         }
     }
     return(result);
 }
Пример #20
0
 /// <summary>
 /// constructor
 /// </summary>
 /// <param name="dimension_x">number of cells across the grid</param>
 /// <param name="dimension_y">number of cells down the grid</param>
 /// <param name="perimeter">perimeter of the grid</param>
 /// <param name="border_cells">number of cells to use as a border around the grid</param>
 public grid2D(int dimension_x, int dimension_y,
               polygon2D perimeter, int border_cells)
 {
     init(dimension_x, dimension_y, perimeter, border_cells);
 }
Пример #21
0
        /// <summary>
        /// return true if this polygon overlaps with another
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public bool overlaps(polygon2D other)
        {
            int i;
            bool retval = false;

            i = 0;
            while ((i < x_points.Count) && (retval == false))
            {
                if (other.isInside(x_points[i],y_points[i])) retval=true;
                i++;
            }

            i = 0;
            while ((i < other.x_points.Count) && (retval == false))
            {
                if (isInside((float)other.x_points[i], (float)other.y_points[i])) retval = true;
                i++;
            }
            return (retval);
Пример #22
0
        /// <summary>
        /// initialise the grid
        /// </summary>
        /// <param name="dimension_x"></param>
        /// <param name="dimension_y"></param>
        /// <param name="perimeter"></param>
        /// <param name="border_cells"></param>
        /// <param name="simple_orientation"></param>
        public void init(int dimension_x, int dimension_y,
                         polygon2D perimeter, int border_cells, 
                         bool simple_orientation)
        {
            this.border_cells = border_cells;
            this.perimeter = perimeter;

            cell = new grid2Dcell[dimension_x][];
            for (int x = 0; x < dimension_x; x++)
                cell[x] = new grid2Dcell[dimension_y];

            line = new ArrayList[2];

            float length3, length4;
            int index = 0;
            for (int i = 0; i < 2; i++)
            {
                line[i] = new ArrayList();

                int idx1 = index + i;
                if (idx1 >= 4) idx1 -= 4;
                int idx2 = index + i + 1;
                if (idx2 >= 4) idx2 -= 4;
                float x0 = (float)perimeter.x_points[idx1];
                float y0 = (float)perimeter.y_points[idx1];
                float x1 = (float)perimeter.x_points[idx2];
                float y1 = (float)perimeter.y_points[idx2];

                int next_idx1 = idx1 + 1;
                if (next_idx1 >= 4) next_idx1 -= 4;
                length3 = perimeter.getSideLength(next_idx1);

                float w0 = Math.Abs(x1 - x0);
                float h0 = Math.Abs(y1 - y0);

                int idx3 = index + i + 2;
                if (idx3 >= 4) idx3 -= 4;
                int idx4 = index + i + 3;
                if (idx4 >= 4) idx4 -= 4;
                float x2 = (float)perimeter.x_points[idx3];
                float y2 = (float)perimeter.y_points[idx3];
                float x3 = (float)perimeter.x_points[idx4];
                float y3 = (float)perimeter.y_points[idx4];

                int next_idx3 = next_idx1 + 2;
                if (next_idx3 >= 4) next_idx3 -= 4;
                length4 = perimeter.getSideLength(next_idx3);

                float w1 = Math.Abs(x3 - x2);
                float h1 = Math.Abs(y3 - y2);

                int dimension = dimension_x;
                if (!simple_orientation)
                {
                    if (i > 0)
                        dimension = dimension_y;
                }
                else
                {
                    if (h0 > w0) dimension = dimension_y;
                }

                // how much shorter is one line than the other on the opposite axis?
                float shortening = 0;
                //if (h0 > w0)
                {
                    if (length3 > length4)
                        shortening = (length3 - length4) / length3;
                    else
                        shortening = (length4 - length3) / length4;
                }


                for (int j = -border_cells; j <= dimension + border_cells; j++)
                {
                    // locate the position along the first line
                    float xx0, yy0;  // position along the first line
                    
                    float fraction = j / (float)dimension;

                    // modify for foreshortening
                    //if ((h0 > w0) && (shortening > 0))
                    if (shortening > 0)
                    {
                        fraction = (fraction * (1.0f - shortening)) + ((float)Math.Sin(fraction * (float)Math.PI / 2) * shortening);
                        if (length3 > length4) fraction = 1.0f - fraction;
                    }

                    if (w0 > h0)
                    {
                        float grad = (y1 - y0) / (x1 - x0);
                        if (x1 > x0)
                            xx0 = x0 + (w0 * fraction);
                        else
                            xx0 = x0 - (w0 * fraction);
                        yy0 = y0 + ((xx0 - x0) * grad);
                    }
                    else
                    {
                        float grad = (x1 - x0) / (y1 - y0);
                        if (y1 > y0)
                            yy0 = y0 + (h0 * fraction);
                        else
                            yy0 = y0 - (h0 * fraction);
                        xx0 = x0 + ((yy0 - y0) * grad);
                    }

                    // locate the position along the second line
                    float xx1, yy1;  // position along the second line

                    if (w1 > h1)
                    {
                        float grad = (y2 - y3) / (x2 - x3);
                        if (x2 > x3)
                            xx1 = x3 + (w1 * fraction);
                        else
                            xx1 = x3 - (w1 * fraction);
                        yy1 = y3 + ((xx1 - x3) * grad);
                    }
                    else
                    {
                        float grad = (x2 - x3) / (y2 - y3);
                        if (y2 > y3)
                            yy1 = y3 + (h1 * fraction);
                        else
                            yy1 = y3 - (h1 * fraction);
                        xx1 = x3 + ((yy1 - y3) * grad);
                    }

                    // add the line to the list
                    line[i].Add(xx0);
                    line[i].Add(yy0);
                    line[i].Add(xx1);
                    line[i].Add(yy1);
                }
            }

            // find interceptions between lines
            poltLineIntercepts();

            // create grid cells
            initialiseCells();
        }
Пример #23
0
        /// <summary>
        /// does this polygon overlap with the other, within the given screen dimensions
        /// </summary>
        /// <param name="other">other polygon object</param>
        /// <param name="image_width">image width</param>
        /// <param name="image_height">image height</param>
        /// <returns></returns>
        public bool overlaps(polygon2D other, int image_width, int image_height)
        {
            int i;
            bool retval = false;

            i = 0;
            while ((i < x_points.Count) && (retval == false))
            {
                if (other.isInside(x_points[i] * 1000 / image_width, y_points[i] * 1000 / image_height)) retval = true;
                i++;
            }

            i = 0;
            while ((i < other.x_points.Count) && (retval == false))
            {
                if (isInside((float)other.x_points[i] * image_width / 1000, (float)other.y_points[i] * image_height / 1000)) retval = true;
                i++;
            }
            return (retval);
Пример #24
0
        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="dimension_x">number of cells across the grid</param>
        /// <param name="dimension_y">number of cells down the grid</param>
        /// <param name="cx">centre of the grid</param>
        /// <param name="cy">centre of the grid</param>
        /// <param name="orientation">orientation of the grid in radians</param>
        /// <param name="average_spacing_x">grid spacing in the x axis</param>
        /// <param name="average_spacing_y">grid spacing in the y axis</param>
        /// <param name="phase_offset_x">phase offset in the x axis</param>
        /// <param name="phase_offset_y">phase offset in the y axis</param>
        /// <param name="border_cells">number of cells to use as a border around the grid</param>
        public grid2D(int dimension_x, int dimension_y,
                      float cx, float cy,
                      float orientation,
                      float average_spacing_x, float average_spacing_y,
                      float phase_offset_x, float phase_offset_y,
                      int border_cells,
                      bool orientation_simple)
        {
            // create a perimeter region
            polygon2D perimeter = new polygon2D();

            float length_x = average_spacing_x * dimension_x;
            float length_y = average_spacing_y * dimension_y;
            float half_length_x = length_x / 2;
            float half_length_y = length_y / 2;

            // adjust for phase
            cx += (average_spacing_x * phase_offset_x / (2 * (float)Math.PI)) * (float)Math.Sin(orientation);
            cy -= (average_spacing_y * phase_offset_y / (2 * (float)Math.PI)) * (float)Math.Cos(orientation);

            // find the mid point of the top line
            float px1 = cx + (half_length_y * (float)Math.Sin(orientation));
            float py1 = cy + (half_length_y * (float)Math.Cos(orientation));

            // find the top left vertex
            float x0 = px1 + (half_length_x * (float)Math.Sin(orientation - (float)(Math.PI / 2)));
            float y0 = py1 + (half_length_x * (float)Math.Cos(orientation - (float)(Math.PI / 2)));

            // find the top right vertex
            float x1 = px1 + (half_length_x * (float)Math.Sin(orientation + (float)(Math.PI / 2)));
            float y1 = py1 + (half_length_x * (float)Math.Cos(orientation + (float)(Math.PI / 2)));

            // find the bottom vertices by mirroring around the centre
            float x2 = cx + (cx - x0);
            float y2 = cy + (cy - y0);
            float x3 = cx - (x1 - cx);
            float y3 = cy - (y1 - cy);

            // update polygon with the perimeter vertices
            perimeter.Add(x0, y0);
            perimeter.Add(x1, y1);
            perimeter.Add(x2, y2);
            perimeter.Add(x3, y3);

            int dim_x = dimension_x;
            int dim_y = dimension_y;
            float first_side_length = perimeter.getSideLength(0);
            float second_side_length = perimeter.getSideLength(1);
            if (((dimension_x > dimension_y + 2) &&
                 (second_side_length > first_side_length)) ||
                 ((dimension_y > dimension_x + 2) &&
                 (first_side_length > second_side_length)))
            {
                dim_x = dimension_y;
                dim_y = dimension_x;
            }

            // initialise using this perimeter
            init(dim_x, dim_y, perimeter, border_cells, orientation_simple);
        }
Пример #25
0
        /// <summary>
        /// returns the difference in the positions of vertices
        /// compared to another polygon
        /// </summary>
        /// <param name="other">the other polygon</param>
        /// <returns></returns>
        public float Compare(polygon2D other)
        {
            float difference = 0;

            // vertices exist
            if ((x_points != null) && (other.x_points != null))
            {
                // same number of vertices
                if (x_points.Count == other.x_points.Count)
                {
                    for (int i = 0; i < x_points.Count; i++)
                    {
                        float dx = Math.Abs(x_points[i] - other.x_points[i]);
                        float dy = Math.Abs(y_points[i] - other.y_points[i]);
                        difference += dx + dy;
                    }
                }
            }

            return (difference);
Пример #26
0
        /// <summary>
        /// finds the interception points between grid lines
        /// </summary>
        private void poltLineIntercepts()
        {
            if (line != null)
            {
                // create an array to store the line intercepts
                int intercepts_x = line[0].Count/4;
                int intercepts_y = line[1].Count/4;
                line_intercepts = new float[intercepts_x, intercepts_y, 2];

                for (int i = 0; i < line[0].Count; i += 4)
                {
                    // get the first line coordinates
                    ArrayList lines0 = line[0];
                    float x0 = (float)lines0[i];
                    float y0 = (float)lines0[i + 1];
                    float x1 = (float)lines0[i + 2];
                    float y1 = (float)lines0[i + 3];

                    for (int j = 0; j < line[1].Count; j += 4)
                    {
                        // get the second line coordinates
                        ArrayList lines1 = line[1];
                        float x2 = (float)lines1[j];
                        float y2 = (float)lines1[j + 1];
                        float x3 = (float)lines1[j + 2];
                        float y3 = (float)lines1[j + 3];

                        // find the interception between the two lines
                        float ix = 0, iy = 0;
                        geometry.intersection(x0, y0, x1, y1, x2, y2, x3, y3, ref ix, ref iy);

                        // store the intercept position
                        line_intercepts[i/4, j/4, 0] = ix;
                        line_intercepts[i/4, j/4, 1] = iy;
                    }
                }

                // update the perimeter
                border_perimeter = new polygon2D();
                float xx = line_intercepts[0, 0, 0];
                float yy = line_intercepts[0, 0, 1];
                border_perimeter.Add(xx, yy);
                xx = line_intercepts[intercepts_x - 1, 0, 0];
                yy = line_intercepts[intercepts_x - 1, 0, 1];
                border_perimeter.Add(xx, yy);
                xx = line_intercepts[intercepts_x - 1, intercepts_y - 1, 0];
                yy = line_intercepts[intercepts_x - 1, intercepts_y - 1, 1];
                border_perimeter.Add(xx, yy);
                xx = line_intercepts[0, intercepts_y - 1, 0];
                yy = line_intercepts[0, intercepts_y - 1, 1];
                border_perimeter.Add(xx, yy);
            }
        }
Пример #27
0
        /// <summary>
        /// snaps the vertices of the polygon to a grid having the given spacing
        /// </summary>
        /// <param name="grid_spacing">spacing of the grid</param>
        /// <returns>fitted polygon</returns>
        public polygon2D SnapToGrid(float grid_spacing)
        {
            polygon2D result = new polygon2D();
            if (x_points != null)
            {
                for (int i = 0; i < x_points.Count; i++)
                {
                    float x = x_points[i] / grid_spacing;
                    x = (float)Math.Round(x) * grid_spacing;
                    float y = y_points[i] / grid_spacing;
                    y = (float)Math.Round(y) * grid_spacing;
                    result.Add(x, y);
                }
            }
            return (result);
Пример #28
0
        /// <summary>
        /// returns an ideally spaced grid over the actual detected spots
        /// </summary>
        /// <param name="grid"></param>
        /// <returns></returns>
        private static grid2D OverlayIdealGrid(CalibrationDot[,] grid,
                                               List<CalibrationDot> corners,
                                               ref int grid_offset_x, ref int grid_offset_y,
                                               int random_seed)
        {
            grid2D overlay_grid = null;
            int grid_tx = -1;
            int grid_ty = -1;
            int grid_bx = -1;
            int grid_by = -1;

            int offset_x = 0;
            int offset_y = 0;

            bool found = false;
            int max_region_area = 0;

            // try searching horizontally and vertically
            // then pick the result with the greatest area
            for (int test_orientation = 0; test_orientation < 2; test_orientation++)
            {
                bool temp_found = false;

                int temp_grid_tx = -1;
                int temp_grid_ty = -1;
                int temp_grid_bx = -1;
                int temp_grid_by = -1;

                int temp_offset_x = 0;
                int temp_offset_y = 0;

                switch (test_orientation)
                {
                    case 0:
                        {
                            while ((temp_offset_y < 5) && (!temp_found))
                            {
                                temp_offset_x = 0;
                                while ((temp_offset_x < 3) && (!temp_found))
                                {
                                    temp_grid_tx = temp_offset_x;
                                    temp_grid_ty = temp_offset_y;
                                    temp_grid_bx = grid.GetLength(0) - 1 - temp_offset_x;
                                    temp_grid_by = grid.GetLength(1) - 1 - temp_offset_y;

                                    if ((temp_grid_bx < grid.GetLength(0)) &&
                                        (temp_grid_tx < grid.GetLength(0)) &&
                                        (temp_grid_by < grid.GetLength(1)) &&
                                        (temp_grid_ty < grid.GetLength(1)) &&
                                        (temp_grid_ty >= 0) &&
                                        (temp_grid_by >= 0) &&
                                        (temp_grid_tx >= 0) &&
                                        (temp_grid_bx >= 0))
                                    {
                                        if ((grid[temp_grid_tx, temp_grid_ty] != null) &&
                                            (grid[temp_grid_bx, temp_grid_ty] != null) &&
                                            (grid[temp_grid_bx, temp_grid_by] != null) &&
                                            (grid[temp_grid_tx, temp_grid_by] != null))
                                        {
                                            temp_found = true;
                                        }
                                    }

                                    temp_offset_x++;
                                }
                                temp_offset_y++;
                            }
                            break;
                        }
                    case 1:
                        {
                            while ((temp_offset_x < 3) && (!temp_found))
                            {
                                temp_offset_y = 0;
                                while ((temp_offset_y < 5) && (!temp_found))
                                {
                                    temp_grid_tx = temp_offset_x;
                                    temp_grid_ty = temp_offset_y;
                                    temp_grid_bx = grid.GetLength(0) - 1 - temp_offset_x;
                                    temp_grid_by = grid.GetLength(1) - 1 - temp_offset_y;

                                    if ((temp_grid_bx < grid.GetLength(0)) &&
                                        (temp_grid_tx < grid.GetLength(0)) &&
                                        (temp_grid_by < grid.GetLength(1)) &&
                                        (temp_grid_ty < grid.GetLength(1)) &&
                                        (temp_grid_ty >= 0) &&
                                        (temp_grid_by >= 0) &&
                                        (temp_grid_tx >= 0) &&
                                        (temp_grid_bx >= 0))
                                    {
                                        if ((grid[temp_grid_tx, temp_grid_ty] != null) &&
                                            (grid[temp_grid_bx, temp_grid_ty] != null) &&
                                            (grid[temp_grid_bx, temp_grid_by] != null) &&
                                            (grid[temp_grid_tx, temp_grid_by] != null))
                                        {
                                            temp_found = true;
                                        }
                                    }

                                    temp_offset_y++;
                                }
                                temp_offset_x++;
                            }
                            break;
                        }
                }

                temp_offset_y = temp_grid_ty - 1;
                while (temp_offset_y >= 0)
                {
                    if ((temp_offset_y < grid.GetLength(1)) &&
                        (temp_offset_y >= 0))
                    {
                        if ((grid[temp_grid_tx, temp_offset_y] != null) &&
                            (grid[temp_grid_bx, temp_offset_y] != null))
                        {
                            temp_grid_ty = temp_offset_y;
                            temp_offset_y--;
                        }
                        else break;
                    }
                    else break;
                }

                temp_offset_y = temp_grid_by + 1;
                while (temp_offset_y < grid.GetLength(1))
                {
                    if ((temp_offset_y < grid.GetLength(1)) &&
                        (temp_offset_y >= 0))
                    {
                        if ((grid[temp_grid_tx, temp_offset_y] != null) &&
                            (grid[temp_grid_bx, temp_offset_y] != null))
                        {
                            temp_grid_by = temp_offset_y;
                            temp_offset_y++;
                        }
                        else break;
                    }
                    else break;
                }

                if (temp_found)
                {
                    int region_area = (temp_grid_bx - temp_grid_tx) * (temp_grid_by - temp_grid_ty);
                    if (region_area > max_region_area)
                    {
                        max_region_area = region_area;
                        found = true;

                        grid_tx = temp_grid_tx;
                        grid_ty = temp_grid_ty;
                        grid_bx = temp_grid_bx;
                        grid_by = temp_grid_by;

                        offset_x = temp_offset_x;
                        offset_y = temp_offset_y;
                    }
                }
            }

            if (found)
            {
                // record the positions of the corners
                corners.Add(grid[grid_tx, grid_ty]);
                corners.Add(grid[grid_bx, grid_ty]);
                corners.Add(grid[grid_bx, grid_by]);
                corners.Add(grid[grid_tx, grid_by]);

                double dx, dy;

                double x0 = grid[grid_tx, grid_ty].x;
                double y0 = grid[grid_tx, grid_ty].y;
                double x1 = grid[grid_bx, grid_ty].x;
                double y1 = grid[grid_bx, grid_ty].y;
                double x2 = grid[grid_tx, grid_by].x;
                double y2 = grid[grid_tx, grid_by].y;
                double x3 = grid[grid_bx, grid_by].x;
                double y3 = grid[grid_bx, grid_by].y;

                polygon2D perimeter = new polygon2D();
                perimeter.Add((float)x0, (float)y0);
                perimeter.Add((float)x1, (float)y1);
                perimeter.Add((float)x3, (float)y3);
                perimeter.Add((float)x2, (float)y2);

                int grid_width = grid_bx - grid_tx;
                int grid_height = grid_by - grid_ty;

                int min_hits = 0;
                double min_dx = 0, min_dy = 0;

                // try various perimeter sizes
                double min_dist = double.MaxValue;
                int max_perim_size_tries = 100;
                polygon2D best_perimeter = perimeter;
                Random rnd = new Random(random_seed);
                for (int perim_size = 0; perim_size < max_perim_size_tries; perim_size++)
                {
                    // try a small range of translations
                    for (int nudge_x = -10; nudge_x <= 10; nudge_x++)
                    {
                        for (int nudge_y = -5; nudge_y <= 5; nudge_y++)
                        {
                            // create a perimeter at this scale and translation
                            polygon2D temp_perimeter = perimeter.Scale(1.0f + (perim_size * 0.1f / max_perim_size_tries));
                            temp_perimeter = temp_perimeter.ScaleSideLength(0, 0.95f + ((float)rnd.NextDouble() * 0.1f));
                            temp_perimeter = temp_perimeter.ScaleSideLength(2, 0.95f + ((float)rnd.NextDouble() * 0.1f));
                            for (int i = 0; i < temp_perimeter.x_points.Count; i++)
                            {
                                temp_perimeter.x_points[i] += nudge_x;
                                temp_perimeter.y_points[i] += nudge_y;
                            }

                            // create a grid based upon the perimeter
                            grid2D temp_overlay_grid = new grid2D(grid_width, grid_height, temp_perimeter, 0, false);

                            // how closely does the grid fit the actual observations ?
                            double temp_min_dist = min_dist;
                            BestFit(grid_tx, grid_ty, grid,
                                    temp_overlay_grid, ref min_dist,
                                    ref min_dx, ref min_dy, ref min_hits,
                                    ref grid_offset_x, ref grid_offset_y);

                            // record the closest fit
                            if (temp_min_dist < min_dist)
                            {
                                best_perimeter = temp_perimeter;
                                overlay_grid = temp_overlay_grid;
                            }
                        }
                    }
                }

                if (min_hits > 0)
                {
                    dx = min_dx;
                    dy = min_dy;

                    Console.WriteLine("dx: " + dx.ToString());
                    Console.WriteLine("dy: " + dy.ToString());

                    x0 += dx;
                    y0 += dy;
                    x1 += dx;
                    y1 += dy;
                    x2 += dx;
                    y2 += dy;
                    x3 += dx;
                    y3 += dy;

                    perimeter = new polygon2D();
                    perimeter.Add((float)x0, (float)y0);
                    perimeter.Add((float)x1, (float)y1);
                    perimeter.Add((float)x3, (float)y3);
                    perimeter.Add((float)x2, (float)y2);
                    overlay_grid = new grid2D(grid_width, grid_height, perimeter, 0, false);
                }
            }

            return (overlay_grid);
        }
Пример #29
0
        /// <summary>
        /// return a scaled version of the polygon
        /// </summary>
        /// <param name="factor"></param>
        /// <returns></returns>
        public polygon2D Scale(float factor)
        {
            polygon2D rescaled = new polygon2D();

            float centre_x = 0, centre_y = 0;
            getCentreOfGravity(ref centre_x, ref centre_y);

            for (int i = 0; i < x_points.Count; i++)
            {
                float dx = x_points[i] - centre_x;
                float dy = y_points[i] - centre_y;
                float x = (float)(centre_x + (dx * factor));
                float y = (float)(centre_y + (dy * factor));
                rescaled.Add(x, y);
            }
            return (rescaled);
        }
Пример #30
0
        /// <summary>
        /// detects a square around the centre dot on the calibration pattern
        /// </summary>
        /// <param name="dots">detected dots</param>
        /// <param name="centredots">returned dots belonging to the centre square</param>
        /// <returns>centre square</returns>
        private static polygon2D GetCentreSquare(hypergraph dots,
                                                 ref List<CalibrationDot> centredots)
        {
            centredots = new List<CalibrationDot>();

            // find the centre dot
            CalibrationDot centre = null;
            int i = 0;
            while ((i < dots.Nodes.Count) && (centre == null))
            {
                CalibrationDot dot = (CalibrationDot)dots.Nodes[i];
                if (dot.centre) centre = dot;
                i++;
            }

            // look for the four surrounding dots
            List<CalibrationDot> centre_dots = new List<CalibrationDot>();
            List<double> distances = new List<double>();
            i = 0;
            for (i = 0; i < dots.Nodes.Count; i++)
            {
                CalibrationDot dot = (CalibrationDot)dots.Nodes[i];
                if (!dot.centre)
                {
                    double dx = dot.x - centre.x;
                    double dy = dot.y - centre.y;
                    double dist = Math.Sqrt(dx * dx + dy * dy);
                    if (distances.Count == 4)
                    {
                        int index = -1;
                        double max_dist = 0;
                        for (int j = 0; j < 4; j++)
                        {
                            if (distances[j] > max_dist)
                            {
                                index = j;
                                max_dist = distances[j];
                            }
                        }
                        if (dist < max_dist)
                        {
                            distances[index] = dist;
                            centre_dots[index] = dot;
                        }
                    }
                    else
                    {
                        distances.Add(dist);
                        centre_dots.Add(dot);
                    }
                }
            }

            polygon2D centre_square = null;
            if (centre_dots.Count == 4)
            {
                centre_square = new polygon2D();
                for (i = 0; i < 4; i++)
                    centre_square.Add(0, 0);

                double xx = centre.x;
                double yy = centre.y;
                int index = 0;
                for (i = 0; i < 4; i++)
                {
                    if ((centre_dots[i].x < xx) &&
                        (centre_dots[i].y < yy))
                    {
                        xx = centre_dots[i].x;
                        yy = centre_dots[i].y;
                        centre_square.x_points[0] = (float)xx;
                        centre_square.y_points[0] = (float)yy;
                        index = i;
                    }
                }
                centredots.Add(centre_dots[index]);

                xx = centre.x;
                yy = centre.y;
                for (i = 0; i < 4; i++)
                {
                    if ((centre_dots[i].x > xx) &&
                        (centre_dots[i].y < yy))
                    {
                        xx = centre_dots[i].x;
                        yy = centre_dots[i].y;
                        centre_square.x_points[1] = (float)xx;
                        centre_square.y_points[1] = (float)yy;
                        index = i;
                    }
                }
                centredots.Add(centre_dots[index]);

                xx = centre.x;
                yy = centre.y;
                for (i = 0; i < 4; i++)
                {
                    if ((centre_dots[i].x > xx) &&
                        (centre_dots[i].y > yy))
                    {
                        xx = centre_dots[i].x;
                        yy = centre_dots[i].y;
                        centre_square.x_points[2] = (float)xx;
                        centre_square.y_points[2] = (float)yy;
                        index = i;
                    }
                }
                centredots.Add(centre_dots[index]);

                xx = centre.x;
                yy = centre.y;
                for (i = 0; i < 4; i++)
                {
                    if ((centre_dots[i].x < xx) &&
                        (centre_dots[i].y > yy))
                    {
                        xx = centre_dots[i].x;
                        yy = centre_dots[i].y;
                        centre_square.x_points[3] = (float)xx;
                        centre_square.y_points[3] = (float)yy;
                        index = i;
                    }
                }
                centredots.Add(centre_dots[index]);
            }
            return (centre_square);
        }
Пример #31
0
        /// <summary>
        /// scale the polygon to a new image size
        /// </summary>
        /// <param name="original_image_width"></param>
        /// <param name="original_image_height"></param>
        /// <param name="new_image_width"></param>
        /// <param name="new_image_height"></param>
        /// <returns></returns>
        public polygon2D Scale(int original_image_width, int original_image_height,
                               int new_image_width, int new_image_height)
        {
            polygon2D rescaled = new polygon2D();

            for (int i = 0; i < x_points.Count; i++)
            {
                float x = x_points[i] * new_image_width / original_image_width;
                float y = y_points[i] * new_image_height / original_image_height;
                rescaled.Add(x, y);
            }
            return (rescaled);
        }