Пример #1
0
        /// <summary>
        /// links line features together
        /// It is assumed that all lines under consideration are of a similar orientation
        /// </summary>
        /// <param name="lines">list of line features to be joined</param>
        /// <param name="join_radius">the start or end points of the lines must be within this radius to be joined</param>
        public static ArrayList joinLines(ArrayList lines,  float join_radius)
        {
            for (int i = 0; i < lines.Count-1; i++)
            {
                linefeature line1 = (linefeature)lines[i];
                float min_start_start_separation = 9999;
                float min_start_end_separation = 9999;
                float min_end_start_separation = 9999;
                float min_end_end_separation = 9999;
                for (int j= i + 1; j < lines.Count; j++)
                {
                    linefeature line2 = (linefeature)lines[j];

                    // start to start
                    float dx = line2.x0 - line1.x0;
                    if (dx < 0) dx = -dx;
                    if (dx < join_radius)
                    {
                        float dy = line2.y0 - line1.y0;
                        if (dy < 0) dy = -dy;
                        if (dy < join_radius)
                        {
                            float separation = dx + dy;
                            if (separation < min_start_start_separation)
                            {
                                min_start_start_separation = separation;
                                line1.join_start = line2;
                                line2.join_start = line1;
                            }
                        }
                    }

                    // start to end
                    dx = line2.x1 - line1.x0;
                    if (dx < 0) dx = -dx;
                    if (dx < join_radius)
                    {
                        float dy = line2.y1 - line1.y0;
                        if (dy < 0) dy = -dy;
                        if (dy < join_radius)
                        {
                            float separation = dx + dy;
                            if (separation < min_start_end_separation)
                            {
                                min_start_end_separation = separation;
                                line1.join_start = line2;
                                line2.join_end = line1;
                            }
                        }
                    }

                    // end to start
                    dx = line2.x0 - line1.x1;
                    if (dx < 0) dx = -dx;
                    if (dx < join_radius)
                    {
                        float dy = line2.y0 - line1.y1;
                        if (dy < 0) dy = -dy;
                        if (dy < join_radius)
                        {
                            float separation = dx + dy;
                            if (separation < min_end_start_separation)
                            {
                                min_end_start_separation = separation;
                                line1.join_end = line2;
                                line2.join_start = line1;
                            }
                        }
                    }

                    // end to end
                    dx = line2.x1 - line1.x1;
                    if (dx < 0) dx = -dx;
                    if (dx < join_radius)
                    {
                        float dy = line2.y0 - line1.y1;
                        if (dy < 0) dy = -dy;
                        if (dy < join_radius)
                        {
                            float separation = dx + dy;
                            if (separation < min_end_end_separation)
                            {
                                min_end_end_separation = separation;
                                line1.join_end = line2;
                                line2.join_end = line1;
                            }
                        }
                    }
                }
            }

            ArrayList joined_lines = new ArrayList();
            int max_joins = 10;
            for (int i = 0; i < lines.Count; i++)
            {
                linefeature line1 = (linefeature)lines[i];

                if ((line1.join_start == null) && (line1.join_end == null))
                {
                    linefeature new_line = new linefeature(line1.x0, line1.y0, line1.x1, line1.y1);
                    joined_lines.Add(new_line);
                }

                // note that we limit the number of itterations
                // to avoid getting trapped in circular joins

                linefeature current_line = line1;
                int l = 0;
                if (line1.join_start == null)
                {
                    while ((l < max_joins) && (current_line.join_end != null))
                    {
                        current_line = current_line.join_end;
                        l++;
                    }
                    if (current_line != line1)
                    {
                        // make a new line which combines these
                        linefeature new_line = new linefeature(line1.x0, line1.y0, current_line.x1, current_line.y1);
                        joined_lines.Add(new_line);
                    }
                }

                current_line = line1;
                l = 0;
                if (line1.join_end == null)
                {
                    while ((l < max_joins) && (current_line.join_start != null))
                    {
                        current_line = current_line.join_start;
                        l++;
                    }
                    if (current_line != line1)
                    {
                        // make a new line which combines these
                        linefeature new_line = new linefeature(current_line.x0, current_line.y0, line1.x1, line1.y1);
                        joined_lines.Add(new_line);
                    }
                }
            }

            return(joined_lines);
        }
Пример #2
0
        /// <summary>
        /// trace along vertical edges
        /// </summary>
        /// <param name="vertical_edges">a list of vertical edge features</param>
        /// <param name="image_width">width of the image</param>
        /// <param name="min_length">the minimum length of line features to be extracted</param>
        /// <param name="search_depth">depth of search used to join edges</param>
        /// <returns>a list of line features</returns>
        public static ArrayList traceVerticalLines(ArrayList[] vertical_edges, 
                                                   int image_width,
                                                   int min_length,
                                                   int search_depth)
        {
            ArrayList lines = new ArrayList();

            // arrays to store edge positions
            bool[] previous_edges4 = new bool[image_width];
            bool[] previous_edges3 = new bool[image_width];
            bool[] previous_edges2 = new bool[image_width];
            bool[] previous_edges = new bool[image_width];
            bool[] current_edges = new bool[image_width];
            ArrayList[] current_lines = new ArrayList[image_width];

            for (int y = 0; y < vertical_edges.Length; y++)
            {
                // clear the array of current edge positions
                for (int x = 0; x < image_width; x++)
                    current_edges[x] = false;

                ArrayList edges = vertical_edges[y];
                for (int i = 0; i < edges.Count; i++)
                {
                    int x = (int)edges[i];

                    int prev_x = -1;

                    if ((x > -1) && (x < image_width))
                    {
                        if ((previous_edges[x]) || (previous_edges2[x]) || (previous_edges3[x]) || (previous_edges4[x]))
                            prev_x = x;
                        else
                        {
                            if (x > 0)
                                if (previous_edges[x-1]) prev_x = x-1;
                            if (x < image_width-1)
                                if (previous_edges[x+1]) prev_x = x+1;

                            if (search_depth > 1)
                            {
                                if (prev_x == -1)
                                {
                                    if (x > 1)
                                        if (previous_edges[x - 2]) prev_x = x - 2;
                                    if (x < image_width - 2)
                                        if (previous_edges[x + 2]) prev_x = x + 2;
                                }

                                if (prev_x == -1)
                                {
                                    if (x > 0)
                                        if (previous_edges2[x - 1]) prev_x = x - 1;
                                    if (x < image_width - 1)
                                        if (previous_edges2[x + 1]) prev_x = x + 1;
                                }

                                if (prev_x == -1)
                                {
                                    if (x > 1)
                                        if (previous_edges2[x - 2]) prev_x = x - 2;
                                    if (x < image_width - 2)
                                        if (previous_edges2[x + 2]) prev_x = x + 2;
                                }

                                if (search_depth > 2)
                                {

                                    if (prev_x == -1)
                                    {
                                        if (x > 0)
                                            if (previous_edges3[x - 1]) prev_x = x - 1;
                                        if (x < image_width - 1)
                                            if (previous_edges3[x + 1]) prev_x = x + 1;
                                    }

                                    if (prev_x == -1)
                                    {
                                        if (x > 1)
                                            if (previous_edges3[x - 2]) prev_x = x - 2;
                                        if (x < image_width - 2)
                                            if (previous_edges3[x + 2]) prev_x = x + 2;
                                    }

                                    if (search_depth > 3)
                                    {
                                        if (prev_x == -1)
                                        {
                                            if (x > 0)
                                                if (previous_edges4[x - 1]) prev_x = x - 1;
                                            if (x < image_width - 1)
                                                if (previous_edges4[x + 1]) prev_x = x + 1;
                                        }

                                        if (prev_x == -1)
                                        {
                                            if (x > 1)
                                                if (previous_edges4[x - 2]) prev_x = x - 2;
                                            if (x < image_width - 2)
                                                if (previous_edges4[x + 2]) prev_x = x + 2;
                                        }

                                        if (prev_x == -1)
                                        {
                                            if (x > 2)
                                                if (previous_edges4[x - 3]) prev_x = x - 3;
                                            if (x < image_width - 3)
                                                if (previous_edges4[x + 3]) prev_x = x + 3;
                                        }

                                        if (prev_x == -1)
                                        {
                                            if (x > 3)
                                                if (previous_edges4[x - 4]) prev_x = x - 4;
                                            if (x < image_width - 4)
                                                if (previous_edges4[x + 4]) prev_x = x + 4;
                                        }
                                    }
                                }
                            }
                        }
                        if (prev_x > -1)
                        {
                            if (current_lines[prev_x] == null)
                                current_lines[prev_x] = new ArrayList();

                            current_lines[prev_x].Add(x);
                            current_lines[prev_x].Add(y);

                            if (prev_x != x)
                            {
                                current_lines[x] = current_lines[prev_x];
                                current_lines[prev_x] = null;
                            }
                        }

                        current_edges[x] = true;
                    }
                }

                // which lines are broken?
                for (int x = 1; x < image_width-1; x++)
                {
                    ArrayList line = current_lines[x];
                    if ((line != null) && ((!current_edges[x]) || (y == vertical_edges.Length-1)))
                    {
                        int line_length = line.Count/2;
                        if (line_length > min_length)
                        {
                            // calc centre of the line
                            float av_start_x = 0;
                            float av_start_y = 0;
                            float av_end_x = 0;
                            float av_end_y = 0;
                            float av_x = 0;
                            float av_y = 0;
                            int hits_start = 0;
                            int hits_end = 0;
                            for (int j = 0; j < line.Count; j += 2)
                            {
                                int xx = (int)line[j];
                                int yy = (int)line[j + 1];
                                av_x += xx;
                                av_y += yy;
                                if (j < line_length)
                                {
                                    av_start_x += xx;
                                    av_start_y += yy;
                                    hits_start++;
                                }
                                else
                                {
                                    av_end_x += xx;
                                    av_end_y += yy;
                                    hits_end++;
                                }
                            }
                            av_x /= line_length;
                            av_y /= line_length;
                            av_start_x /= hits_start;
                            av_start_y /= hits_start;
                            av_end_x /= hits_end;
                            av_end_y /= hits_end;

                            float dx = av_start_x - av_x;
                            float dy = av_start_y - av_y;
                            av_start_x = av_x + (dx*2);
                            av_start_y = av_y + (dy*2);

                            dx = av_end_x - av_x;
                            dy = av_end_y - av_y;
                            av_end_x = av_x + (dx*2);
                            av_end_y = av_y + (dy*2);

                            linefeature new_line = new linefeature(av_start_x, av_start_y, av_end_x, av_end_y);
                            lines.Add(new_line);
                        }
                        current_lines[x] = null;
                    }
                }

                // swap arrays
                bool[] temp = previous_edges4;
                previous_edges4 = previous_edges3;
                previous_edges3 = previous_edges2;
                previous_edges2 = previous_edges;
                previous_edges = current_edges;
                current_edges = temp;
            }
            return(lines);
        }