示例#1
0
        /// <summary>
        /// detect regions within the given image
        /// </summary>
        /// <param name="bmp">image data</param>
        /// <param name="image_width">width of the image</param>
        /// <param name="image_height">height of the image</param>
        /// <param name="min_region_volume_percent">ignore regions which are smaller than this threshold</param>
        /// <param name="min_aspect_ratio">minimum aspect ratio</param>
        /// <param name="max_aspect_ratio">maxiumum aspect ratio</param>
        /// <param name="vertex_inflation"></param>
        /// <param name="vertex_angular_offset"></param>
        /// <param name="segmentation_threshold">thresholds to use for segmentation</param>
        /// <param name="segmented">segmentation map</param>
        /// <param name="corner_features">returns detected corner features as a list of integers, suitable for use by other functions</param>
        /// <param name="downsampling_factor">factor by which to reduce the original image size</param>
        /// <param name="border_percent">defines a border within which the centres of detected regions must be</param>
        /// <param name="rectangle_classification">the classification to be applied to shapes having a rectangular aspect ratio</param>
        /// <param name="square_classification">the classification to be applied to shapes having a square aspect ratio</param>
        /// <returns>list of regions detected</returns>
        public static regionCollection DetectRegions(
                           byte[] bmp, int image_width, int image_height,
                           int min_region_volume_percent,
                           float min_aspect_ratio, float max_aspect_ratio,
                           float vertex_inflation,
                           float vertex_angular_offset,
                           int[] segmentation_threshold,
                           int[,] segmented, ArrayList corner_features,
                           int downsampling_factor,
                           int border_percent,
                           byte[] bmp_mono,
                           String rectangle_classification,
                           String square_classification)
        {
            // dimensions of the downsampled image
            int small_image_width = image_width / downsampling_factor;
            int small_image_height = image_height / downsampling_factor;

            // the centre of detected regions must be inside this region
            // in order to be considered as candidates
            int min_x = small_image_width * border_percent / 100;
            int max_x = small_image_width - min_x;
            int min_y = small_image_height * border_percent / 100;
            int max_y = small_image_height - min_y;

            // stack used by the flood fill algorithm
            // allocating space here just saves the time needed to create the
            // array for each flood fill routine call
            int[] flood_fill_stack = new int[small_image_width *
                                             small_image_height * 5];

            // this object stores the detected regions
            regionCollection regions = new regionCollection();

            if (bmp != null)
            {
                // min region volume in pixels
                int min_region_volume = (image_width / downsampling_factor) *
                                        (image_height / downsampling_factor) *
                                        min_region_volume_percent / 1000;

                // create arrays which will be used for flood fill operations
                bool[,] filled = new bool[small_image_width, small_image_height];
                bool[,] region_image = new bool[small_image_width, small_image_height];

                for (int threshold_level = 0; threshold_level < segmentation_threshold.Length; threshold_level++)
                {
                    // clear the filled array
                    if (threshold_level > 0)
                        for (int clear_x = 0; clear_x < small_image_width; clear_x++)
                            for (int clear_y = 0; clear_y < small_image_height; clear_y++)
                                filled[clear_x, clear_y] = false;

                    int tx, ty, bx, by;
                    for (int y = 0; y < small_image_height; y++)
                    {
                        for (int x = 0; x < small_image_width; x++)
                        {
                            if (filled[x, y] == false)
                                if (segmented[x, y] > segmentation_threshold[threshold_level])
                                {
                                    tx = x; ty = y; bx = x; by = y;
                                    long pixels = 0;
                                    long av_intensity = 0;
                                    long av_x = 0, av_y = 0;

                                    // clear the region_image array
                                    for (int clear_x = 0; clear_x < small_image_width; clear_x++)
                                        for (int clear_y = 0; clear_y < small_image_height; clear_y++)
                                            region_image[clear_x, clear_y] = false;

                                    // using a linear flood fill avoids stack overflow exceptions
                                    sluggish.utilities.drawing.floodFillLinear(
                                        x, y, segmentation_threshold[threshold_level],
                                        flood_fill_stack,
                                        ref tx, ref ty, ref bx, ref by,
                                        ref pixels, ref av_intensity,
                                        segmented, filled, region_image, ref av_x, ref av_y,
                                        small_image_width, small_image_height);

                                    if (by > ty)
                                    {
                                        if (pixels > min_region_volume)
                                        {
                                            av_x = av_x / pixels;
                                            av_y = av_y / pixels;

                                            // is the centre of the region inside the border?
                                            if ((av_x > min_x) && (av_x < max_x) &&
                                                (av_y > min_y) && (av_y < max_y))
                                            {
                                                // convert values from region growing back into
                                                // the original image resolution
                                                if (downsampling_factor > 1)
                                                {
                                                    av_x *= downsampling_factor;
                                                    av_y *= downsampling_factor;
                                                    tx *= downsampling_factor;
                                                    ty *= downsampling_factor;
                                                    bx *= downsampling_factor;
                                                    by *= downsampling_factor;

                                                }

                                                // add an extra border		                                                
                                                int border = (bx - tx) / 20;
                                                int tx2 = tx - border;
                                                if (tx2 < 0) tx2 = 0;
                                                int ty2 = ty - border;
                                                if (ty2 < 0) ty2 = 0;
                                                int bx2 = bx + border;
                                                if (bx2 >= image_width) bx2 = image_width - 1;
                                                int by2 = by + border;
                                                if (by2 >= image_height) by2 = image_height - 1;

                                                // create a region object                                            
                                                int wdth = bx2 - tx2;
                                                int hght = by2 - ty2;
                                                sluggish.imageprocessing.region new_region =
                                                    new sluggish.imageprocessing.region(tx2, ty2, wdth, hght,
                                                                                        region_image, segmented, (int)av_x, (int)av_y,
                                                                                        corner_features,
                                                                                        bmp_mono, image_width, image_height,
                                                                                        vertex_inflation,
                                                                                        vertex_angular_offset,
                                                                                        downsampling_factor);

                                                if (new_region.aspect_ratio > max_aspect_ratio) new_region.classification = "text";

                                                // add this region to the collection
                                                regions.Add(new_region);
                                                new_region.classification = rectangle_classification;

                                                if ((new_region.aspect_ratio >= min_aspect_ratio) &&
                                                    (new_region.aspect_ratio <= max_aspect_ratio))
                                                {
                                                    new_region.classification = square_classification;
                                                }

                                            }
                                        }
                                    }
                                }
                        }
                    }
                }

            }

            return (regions);
        }
        /// <summary>
        /// detect regions within the given image
        /// </summary>
        /// <param name="bmp">image data</param>
        /// <param name="image_width">width of the image</param>
        /// <param name="image_height">height of the image</param>
        /// <param name="min_region_volume_percent">ignore regions which are smaller than this threshold</param>
        /// <param name="min_aspect_ratio">minimum aspect ratio</param>
        /// <param name="max_aspect_ratio">maxiumum aspect ratio</param>
        /// <param name="vertex_inflation"></param>
        /// <param name="vertex_angular_offset"></param>
        /// <param name="segmentation_threshold">thresholds to use for segmentation</param>
        /// <param name="segmented">segmentation map</param>
        /// <param name="corner_features">returns detected corner features as a list of integers, suitable for use by other functions</param>
        /// <param name="downsampling_factor">factor by which to reduce the original image size</param>
        /// <param name="border_percent">defines a border within which the centres of detected regions must be</param>
        /// <param name="rectangle_classification">the classification to be applied to shapes having a rectangular aspect ratio</param>
        /// <param name="square_classification">the classification to be applied to shapes having a square aspect ratio</param>
        /// <returns>list of regions detected</returns>
        public static regionCollection DetectRegions(
            byte[] bmp, int image_width, int image_height,
            int min_region_volume_percent,
            float min_aspect_ratio, float max_aspect_ratio,
            float vertex_inflation,
            float vertex_angular_offset,
            int[] segmentation_threshold,
            int[,] segmented, ArrayList corner_features,
            int downsampling_factor,
            int border_percent,
            byte[] bmp_mono,
            String rectangle_classification,
            String square_classification)
        {
            // dimensions of the downsampled image
            int small_image_width  = image_width / downsampling_factor;
            int small_image_height = image_height / downsampling_factor;

            // the centre of detected regions must be inside this region
            // in order to be considered as candidates
            int min_x = small_image_width * border_percent / 100;
            int max_x = small_image_width - min_x;
            int min_y = small_image_height * border_percent / 100;
            int max_y = small_image_height - min_y;

            // stack used by the flood fill algorithm
            // allocating space here just saves the time needed to create the
            // array for each flood fill routine call
            int[] flood_fill_stack = new int[small_image_width *
                                             small_image_height * 5];

            // this object stores the detected regions
            regionCollection regions = new regionCollection();

            if (bmp != null)
            {
                // min region volume in pixels
                int min_region_volume = (image_width / downsampling_factor) *
                                        (image_height / downsampling_factor) *
                                        min_region_volume_percent / 1000;

                // create arrays which will be used for flood fill operations
                bool[,] filled       = new bool[small_image_width, small_image_height];
                bool[,] region_image = new bool[small_image_width, small_image_height];

                for (int threshold_level = 0; threshold_level < segmentation_threshold.Length; threshold_level++)
                {
                    // clear the filled array
                    if (threshold_level > 0)
                    {
                        for (int clear_x = 0; clear_x < small_image_width; clear_x++)
                        {
                            for (int clear_y = 0; clear_y < small_image_height; clear_y++)
                            {
                                filled[clear_x, clear_y] = false;
                            }
                        }
                    }

                    int tx, ty, bx, by;
                    for (int y = 0; y < small_image_height; y++)
                    {
                        for (int x = 0; x < small_image_width; x++)
                        {
                            if (filled[x, y] == false)
                            {
                                if (segmented[x, y] > segmentation_threshold[threshold_level])
                                {
                                    tx = x; ty = y; bx = x; by = y;
                                    long pixels = 0;
                                    long av_intensity = 0;
                                    long av_x = 0, av_y = 0;

                                    // clear the region_image array
                                    for (int clear_x = 0; clear_x < small_image_width; clear_x++)
                                    {
                                        for (int clear_y = 0; clear_y < small_image_height; clear_y++)
                                        {
                                            region_image[clear_x, clear_y] = false;
                                        }
                                    }

                                    // using a linear flood fill avoids stack overflow exceptions
                                    sluggish.utilities.drawing.floodFillLinear(
                                        x, y, segmentation_threshold[threshold_level],
                                        flood_fill_stack,
                                        ref tx, ref ty, ref bx, ref by,
                                        ref pixels, ref av_intensity,
                                        segmented, filled, region_image, ref av_x, ref av_y,
                                        small_image_width, small_image_height);

                                    if (by > ty)
                                    {
                                        if (pixels > min_region_volume)
                                        {
                                            av_x = av_x / pixels;
                                            av_y = av_y / pixels;

                                            // is the centre of the region inside the border?
                                            if ((av_x > min_x) && (av_x < max_x) &&
                                                (av_y > min_y) && (av_y < max_y))
                                            {
                                                // convert values from region growing back into
                                                // the original image resolution
                                                if (downsampling_factor > 1)
                                                {
                                                    av_x *= downsampling_factor;
                                                    av_y *= downsampling_factor;
                                                    tx   *= downsampling_factor;
                                                    ty   *= downsampling_factor;
                                                    bx   *= downsampling_factor;
                                                    by   *= downsampling_factor;
                                                }

                                                // add an extra border
                                                int border = (bx - tx) / 20;
                                                int tx2    = tx - border;
                                                if (tx2 < 0)
                                                {
                                                    tx2 = 0;
                                                }
                                                int ty2 = ty - border;
                                                if (ty2 < 0)
                                                {
                                                    ty2 = 0;
                                                }
                                                int bx2 = bx + border;
                                                if (bx2 >= image_width)
                                                {
                                                    bx2 = image_width - 1;
                                                }
                                                int by2 = by + border;
                                                if (by2 >= image_height)
                                                {
                                                    by2 = image_height - 1;
                                                }

                                                // create a region object
                                                int wdth = bx2 - tx2;
                                                int hght = by2 - ty2;
                                                sluggish.imageprocessing.region new_region =
                                                    new sluggish.imageprocessing.region(tx2, ty2, wdth, hght,
                                                                                        region_image, segmented, (int)av_x, (int)av_y,
                                                                                        corner_features,
                                                                                        bmp_mono, image_width, image_height,
                                                                                        vertex_inflation,
                                                                                        vertex_angular_offset,
                                                                                        downsampling_factor);

                                                if (new_region.aspect_ratio > max_aspect_ratio)
                                                {
                                                    new_region.classification = "text";
                                                }

                                                // add this region to the collection
                                                regions.Add(new_region);
                                                new_region.classification = rectangle_classification;

                                                if ((new_region.aspect_ratio >= min_aspect_ratio) &&
                                                    (new_region.aspect_ratio <= max_aspect_ratio))
                                                {
                                                    new_region.classification = square_classification;
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(regions);
        }