Esempio n. 1
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;
                    }
                }
            }
        }
Esempio n. 2
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>
        /// <param name="average_spacing_horizontal"></param>
        /// <param name="average_spacing_vertical"></param>
        /// <param name="output_img"></param>
        /// <param name="output_img_width"></param>
        /// <param name="output_img_height"></param>
        /// <param name="output_img_type"></param>
        /// <param name="ideal_grid_colour">colour used to draw the ideal grid</param>
        /// <param name="detected_grid_colour">colour used to draw the detected grid</param>
        /// <param name="simple_orientation"></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_width, int output_img_height,
                                        int output_img_type,
                                        byte[] ideal_grid_colour, byte[] detected_grid_colour,
                                        bool simple_orientation)
        {
            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, output_img_width, output_img_height, output_img_type,
                           ideal_grid_colour, detected_grid_colour);
            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, output_img_width, output_img_height, output_img_type,
                           ideal_grid_colour, detected_grid_colour);

            
            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, simple_orientation);

            return (detectedGrid);
        }
Esempio n. 3
0
        /// <summary>
        /// returns a grey scale histogram for the given image within the given perimeter region
        /// </summary>
        /// <param name="bmp">image data</param>
        /// <param name="wdth">width of the image</param>
        /// <param name="hght">height of the image</param>
        /// <param name="bytes_per_pixel">number of bytes per pixel</param>
        /// <param name="levels">histogram levels</param>
        /// <param name="perimeter">perimeter region inside which to calculate the histogram</param>
        /// <returns></returns>
        public static float[] GetGreyHistogram(byte[] bmp,
                                int wdth, int hght,
                                int bytes_per_pixel,
                                int levels,
                                polygon2D perimeter)
        {
            float[] hist = new float[levels];

            int tx = (int)perimeter.left();
            int ty = (int)perimeter.top();
            int bx = (int)perimeter.right();
            int by = (int)perimeter.bottom();

            for (int y = ty; y <= by; y++)
            {
                if ((y > -1) && (y < hght))
                {
                    for (int x = tx; x <= bx; x++)
                    {
                        if ((x > -1) && (x < wdth))
                        {
                            if (perimeter.isInside(x, y))
                            {
                                int n = ((y * wdth) + x) * bytes_per_pixel;
                                float intensity = 0;
                                for (int col = 0; col < bytes_per_pixel; col++)
                                    intensity += bmp[n + col];
                                intensity /= bytes_per_pixel;

                                int bucket = (int)Math.Round(intensity * levels / 255);
                                if (bucket >= levels) bucket = levels - 1;
                                hist[bucket]++;
                            }
                        }
                    }
                }
            }

            // normalise the histogram
            float max = 1;
            for (int level = 0; level < levels; level++)
                if (hist[level] > max) max = hist[level];

            for (int level = 0; level < levels; level++)
                hist[level] = hist[level] / max;

            return (hist);
        }