Exemplo n.º 1
0
        public static List<List<int>> GetGroups(List<int>edges,
                                                int img_width, int img_height,
                                                int image_border,
                                                int minimum_size_percent,
                                                bool squares_only,
                                                int max_search_depth,
                                                bool ignore_periphery,
                                                int grouping_radius_percent)
        {
#if SHOW_TIMINGS
                stopwatch timer_grouping = new stopwatch();
                timer_grouping.Start();
#endif
            const int compression = 4;
            
            int grouping_radius = grouping_radius_percent * img_width / (100 * compression);
            List<List<int>> groups = new List<List<int>>();            
                        
            // find line segments of significant length
            List<float> centres = null;
            List<float> bounding_boxes = null;
            List<List<int>> line_segments = 
                DetectLongestPerimeters(edges, 
                                        img_width, img_height, 
                                        image_border, 
                                        minimum_size_percent, 
                                        squares_only,
                                        max_search_depth,
                                        ignore_periphery,
                                        ref centres,
                                        ref bounding_boxes);

            bool[][] grouping_matrix = new bool[line_segments.Count][];
            for (int i = 0; i < line_segments.Count; i++)
                grouping_matrix[i] = new bool[line_segments.Count];
                        
            // map out the line segments
            const int step_size = 4;
            int ty = img_height-1;
            int by = 0;
            int tx = img_width-1;
            int bx = 0;
            int[,] line_segment_map = new int[(img_width/compression)+2, (img_height/compression)+2];
            for (int i = 0; i < line_segments.Count; i++)
            {
                List<int> line_segment = line_segments[i];
                for (int j = 0; j < line_segment.Count; j += step_size)
                {
                    int x = line_segment[j]/compression;
                    int y = line_segment[j+1]/compression;
                    if (line_segment_map[x, y] > 0)
                    {
                        if (line_segment_map[x, y] != i + 1)
                        {
                            int segment_index1 = line_segment_map[x, y]-1; 
                            int segment_index2 = i;
                            
                            // link the two segments
                            grouping_matrix[segment_index1][segment_index2] = true;
                            grouping_matrix[segment_index2][segment_index1] = true;
                        }
                    }
                    line_segment_map[x, y] = i + 1;
                    if (x < tx) tx = x;
                    if (x > bx) bx = x;
                    if (y < ty) ty = y;
                    if (y > by) by = y;
                }
            }
            
            // horizontal grouping
            for (int y = ty; y <= by; y++)
            {
                int prev_segment_index = -1;
                int prev_segment_x = -1;
                for (int x = tx; x <= bx; x++)
                {
                    int segment_index = line_segment_map[x, y];
                    if (segment_index > 0)
                    {
                        if (prev_segment_x > -1)
                        {
                            int dx = x - prev_segment_x;
                            if (dx < grouping_radius)
                            {
                                if (!grouping_matrix[segment_index-1][prev_segment_index])
                                {
                                    // get the line segment indexes
                                    segment_index--;                                    
                                    
                                    if (segment_index != prev_segment_index)
                                    {                                
                                        // link the two segments
                                        grouping_matrix[segment_index][prev_segment_index] = true;
                                        grouping_matrix[prev_segment_index][segment_index] = true;
                                    }
                                }
                            }
                        }
                        prev_segment_x = x;
                        prev_segment_index = line_segment_map[x, y]-1;
                    }
                }
            }

            // horizontal grouping
            for (int x = tx; x <= bx; x++)
            {
                int prev_segment_y = -1;
                int prev_segment_index = -1;
                for (int y = ty; y <= by; y++)
                {
                    int segment_index = line_segment_map[x, y];
                    if (segment_index > 0)
                    {
                        if (prev_segment_y > -1)
                        {
                            int dy = y - prev_segment_y;
                            if (dy < grouping_radius)
                            {
                                if (!grouping_matrix[segment_index-1][prev_segment_index])
                                {
                                    // get the line segment indexes
                                    segment_index--;
                                    
                                    if (segment_index != prev_segment_index)
                                    {                                
                                        // link the two segments
                                        grouping_matrix[segment_index][prev_segment_index] = true;
                                        grouping_matrix[prev_segment_index][segment_index] = true;
                                    }
                                }
                            }                            
                        }
                        prev_segment_y = y;
                        prev_segment_index = line_segment_map[x, y]-1;                        
                    }
                }
            }
                        
            // turn grouping matrix into a hypergraph
            hypergraph graph = new hypergraph(grouping_matrix.Length, 1);
            for (int i = 0; i < grouping_matrix.Length; i++)
            {
                for (int j = 0; j < grouping_matrix[i].Length; j++)
                {
                    if (grouping_matrix[i][j])
                        graph.LinkByIndex(j, i);
                }
            }
            
            // detect connected sets within the hypergraph
            for (int i = 0; i < graph.Nodes.Count; i++)
            {
                bool already_grouped = graph.GetFlagByIndex(i, 0);
                if (!already_grouped)
                {
                    List<hypergraph_node> connected_set = new List<hypergraph_node>();
                    graph.PropogateFlagFromIndex(i, 0, connected_set);
                    
                    List<hypergraph_node> members = new List<hypergraph_node>();
                    for (int j = 0; j < connected_set.Count; j++)
                    {
                        if (!members.Contains(connected_set[j])) members.Add(connected_set[j]);
                    }

                    List<int> group_members = new List<int>();
                    for (int j = 0; j < members.Count; j++)
                    {
                        int line_segment_index = members[j].ID;
                        List<int> perim = line_segments[line_segment_index];
                        for (int k = 0; k < perim.Count; k++)
                            group_members.Add(perim[k]);
                    }
                    groups.Add(group_members);
                    
                }
            }
            
#if SHOW_TIMINGS
            timer_grouping.Stop();
            //if (timer_grouping.time_elapsed_mS > 20)
                Console.WriteLine("GetGroups: " + timer_grouping.time_elapsed_mS.ToString() );
#endif                
            
            return(groups);
        }