Opencv 如何在二值骨架化图像中跟踪线段?

Opencv 如何在二值骨架化图像中跟踪线段?,opencv,image-processing,computer-vision,Opencv,Image Processing,Computer Vision,我有一个二值化和骨架化的图像。我使用了Zhang Suen算法进行骨骼化。现在我需要以两点格式从图像中获取线段(线段的起点和终点)。 到目前为止,我一直在使用OpenCV函数findContours,带有CV_CHAIN_APPROX_SIMPLE和CV_RETR_LIST选项。然而,出现了三个问题: 此方法返回重复的线段(方向相反) 由于“层次结构功能”,连接的结构有时会断开连接 线交叉点附近的混乱结果 有没有其他方法可以从图像中跟踪线段 我需要跟踪的图像放大部分: 那应该行得通。它对图像进行

我有一个二值化和骨架化的图像。我使用了Zhang Suen算法进行骨骼化。现在我需要以两点格式从图像中获取线段(线段的起点和终点)。 到目前为止,我一直在使用OpenCV函数findContours,带有CV_CHAIN_APPROX_SIMPLE和CV_RETR_LIST选项。然而,出现了三个问题:

  • 此方法返回重复的线段(方向相反)
  • 由于“层次结构功能”,连接的结构有时会断开连接
  • 线交叉点附近的混乱结果
  • 有没有其他方法可以从图像中跟踪线段

    我需要跟踪的图像放大部分:
    那应该行得通。它对图像进行4次扫描(您可能可以减少扫描次数,但逻辑将更加复杂)

    在每次扫描中,它跟踪水平线、垂直线、向下的对角线和向上的对角线

    行存储在
    向量中,其中每个
    Vec4i
    都是带有
    Xstart、Ystart、Xend、Yend的行

    让我知道这是否适合你

    #include <opencv2/opencv.hpp>
    
    using namespace std;
    using namespace cv;
    
    int main()
    {
        Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);
    
        Mat1b w;
        // Add bg border
        copyMakeBorder(img, w, 1, 1, 1, 1, BORDER_CONSTANT, Scalar(0));
    
        vector<Vec4i> lines;
        Vec4i line;
    
        // Scan horizontal lines 
        for (int y = 1; y < w.rows - 1; ++y)
        {
            for (int x = 1; x < w.cols - 1; ++x)
            {
                if (w(y, x) == 255)
                {
                    int yy = y;
                    int xx = x;
    
                    //Save first point
                    line[0] = xx - 1;
                    line[1] = yy - 1;
    
                    while (true)
                    {
                        if (w(yy, xx + 1))
                        {
                            // Mark as detected
                            w(yy, xx) = 1;
                            ++xx;
                        }
                        else
                        {
                            // End of the line
                            line[2] = xx - 1;
                            line[3] = yy - 1;
    
                            if (line[2] - line[0] > 0)
                            {
                                lines.push_back(line);
                            }
                            break;
                        }
                    }
                }
            }
        }
    
        // Scan vertical lines 
        for (int y = 1; y < w.rows - 1; ++y)
        {
            for (int x = 1; x < w.cols - 1; ++x)
            {
                if (w(y, x) == 255)
                {
                    int yy = y;
                    int xx = x;
    
                    //Save first point
                    line[0] = xx - 1;
                    line[1] = yy - 1;
    
                    while (true)
                    {
                        if (w(yy + 1, xx))
                        {
                            // Mark as detected
                            w(yy, xx) = 1;
                            ++yy;
                        }
                        else
                        {
                            // End of the line
                            line[2] = xx - 1;
                            line[3] = yy - 1;
    
                            if (line[3] - line[1] > 0)
                            {
                                lines.push_back(line);
                            }
                            break;
                        }
                    }
                }
            }
        }
    
        // Scan for diagonal low lines 
        for (int y = 1; y < w.rows - 1; ++y)
        {
            for (int x = 1; x < w.cols - 1; ++x)
            {
                if (w(y, x) == 255)
                {
                    int yy = y;
                    int xx = x;
    
                    //Save first point
                    line[0] = xx - 1;
                    line[1] = yy - 1;
    
                    while (true)
                    {
                        if (w(yy + 1, xx + 1))
                        {
                            // Mark as detected
                            w(yy, xx) = 1;
                            ++xx;
                            ++yy;
                        }
                        else
                        {
                            // End of the line
                            line[2] = xx - 1;
                            line[3] = yy - 1;
                            if (line[2] - line[0] > 0)
                            {
                                lines.push_back(line);
                            }
                            break;
                        }
                    }
                }
            }
        }
    
        // Scan for diagonal high lines 
        for (int y = 1; y < w.rows - 1; ++y)
        {
            for (int x = 1; x < w.cols - 1; ++x)
            {
                if (w(y, x) == 255)
                {
                    int yy = y;
                    int xx = x;
    
                    //Save first point
                    line[0] = xx - 1;
                    line[1] = yy - 1;
    
                    while (true)
                    {
                        if (w(yy - 1, xx + 1))
                        {
                            // Mark as detected
                            w(yy, xx) = 1;
                            ++xx;
                            --yy;
                        }
                        else
                        {
                            // End of the line
                            line[2] = xx - 1;
                            line[3] = yy - 1;
                            if (line[2] - line[0] > 0)
                            {
                                lines.push_back(line);
                            }
                            break;
                        }
                    }
                }
            }
        }
    
        RNG rng(12345);
        Mat3b res;
        cvtColor(img, res, COLOR_GRAY2BGR);
    
        for (int i = 0; i < lines.size(); ++i)
        {
            const Vec4i& lin = lines[i];
            Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
            cv::line(res, Point(lin[0], lin[1]), Point(lin[2], lin[3]), color);
        }
    
        imshow("res", res);
        waitKey();
    
        return 0;
    }
    
    #包括
    使用名称空间std;
    使用名称空间cv;
    int main()
    {
    Mat1b img=imread(“路径到图像”,imread\U灰度);
    Mat1b w;
    //添加背景边框
    copyMakeBorder(img,w,1,1,1,1,BORDER_常量,标量(0));
    矢量线;
    Vec4i线;
    //扫描水平线
    对于(int y=1;y0)
    {
    线。推回(线);
    }
    打破
    }
    }
    }
    }
    }
    //扫描垂直线
    对于(int y=1;y0)
    {
    线。推回(线);
    }
    打破
    }
    }
    }
    }
    }
    //扫描低对角线
    对于(int y=1;y0)
    {
    线。推回(线);
    }
    打破
    }
    }
    }
    }
    }
    //扫描对角线
    对于(int y=1;y0)
    {
    线。推回(线);
    }
    打破
    }
    }
    }
    }
    }
    RNG RNG(12345);
    Mat3b res;
    CVT颜色(img、res、COLOR_GRAY2BGR);
    对于(int i=0;i
    Sta