寻找直线的方法

实际项目中需要寻找这些线段的端点:

 

 


 
1、首先对图片进行细化操作,这样获得直线还是比较清晰的。

 

 

 
2、在使用霍夫变换直线检测的时候,根据本图的先验知识,那就是直线在交点位置产生了急剧的变化,所以调大其第3参数,也就是角度变化。

 

 

下一步就可以进行端点检测。这里绘制出目前检测出来的端点:

 

 

端点的检测,需要比对的是每一个端点的相对位置。一般来说,我都选用更加靠近中间位置的端点作为结果。
 
复制代码
void thin(const Mat &src, Mat &dst, const int iterations = 100);//Mat 需要为DEPTH_8U型二值图 
    //将 DEPTH_8U型二值图像进行细化  经典的Zhang并行快速细化算法
    //细化算法
void thin(const Mat &src, Mat &dst, const int iterations) {
    const int height = src.rows - 1;
    const int width = src.cols - 1;
    //拷贝一个数组给另一个数组
    if (src.data != dst.data)
        src.copyTo(dst);
    int n = 0, i = 0, j = 0;
    Mat tmpImg;
    uchar *pU, *pC, *pD;
    bool isFinished = false;
    for (n = 0; n < iterations; n++) {
        dst.copyTo(tmpImg);
        isFinished = false;   //一次 先行后列扫描 开始
        //扫描过程一 开始
        for (i = 1; i < height; i++) {
            pU = tmpImg.ptr<uchar>(i - 1);
            pC = tmpImg.ptr<uchar>(i);
            pD = tmpImg.ptr<uchar>(i + 1);
            for (int j = 1; j < width; j++) {
                if (pC[j] > 0) {
                    int ap = 0;
                    int p2 = (pU[j] > 0);
                    int p3 = (pU[j + 1] > 0);
                    if (p2 == 0 && p3 == 1)
                        ap++;
                    int p4 = (pC[j + 1] > 0);
                    if (p3 == 0 && p4 == 1)
                        ap++;
                    int p5 = (pD[j + 1] > 0);
                    if (p4 == 0 && p5 == 1)
                        ap++;
                    int p6 = (pD[j] > 0);
                    if (p5 == 0 && p6 == 1)
                        ap++;
                    int p7 = (pD[j - 1] > 0);
                    if (p6 == 0 && p7 == 1)
                        ap++;
                    int p8 = (pC[j - 1] > 0);
                    if (p7 == 0 && p8 == 1)
                        ap++;
                    int p9 = (pU[j - 1] > 0);
                    if (p8 == 0 && p9 == 1)
                        ap++;
                    if (p9 == 0 && p2 == 1)
                        ap++;
                    if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) > 1 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) < 7) {
                        if (ap == 1) {
                            if ((p2*p4*p6 == 0) && (p4*p6*p8 == 0)) {
                                dst.ptr<uchar>(i)[j] = 0;
                                isFinished = true;
                            }
                        }
                    }
                }
            } //扫描过程一 结束
            dst.copyTo(tmpImg);
            //扫描过程二 开始
            for (i = 1; i < height; i++) {
                pU = tmpImg.ptr<uchar>(i - 1);
                pC = tmpImg.ptr<uchar>(i);
                pD = tmpImg.ptr<uchar>(i + 1);
                for (int j = 1; j < width; j++) {
                    if (pC[j] > 0) {
                        int ap = 0;
                        int p2 = (pU[j] > 0);
                        int p3 = (pU[j + 1] > 0);
                        if (p2 == 0 && p3 == 1)
                            ap++;
                        int p4 = (pC[j + 1] > 0);
                        if (p3 == 0 && p4 == 1)
                            ap++;
                        int p5 = (pD[j + 1] > 0);
                        if (p4 == 0 && p5 == 1)
                            ap++;
                        int p6 = (pD[j] > 0);
                        if (p5 == 0 && p6 == 1)
                            ap++;
                        int p7 = (pD[j - 1] > 0);
                        if (p6 == 0 && p7 == 1)
                            ap++;
                        int p8 = (pC[j - 1] > 0);
                        if (p7 == 0 && p8 == 1)
                            ap++;
                        int p9 = (pU[j - 1] > 0);
                        if (p8 == 0 && p9 == 1)
                            ap++;
                        if (p9 == 0 && p2 == 1)
                            ap++;
                        if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) > 1 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) < 7) {
                            if (ap == 1) {
                                if ((p2*p4*p8 == 0) && (p2*p6*p8 == 0)) {
                                    dst.ptr<uchar>(i)[j] = 0;
                                    isFinished = true;
                                }
                            }
                        }
                    }
                }
            } //一次 先行后列扫描完成          
            //如果在扫描过程中没有删除点,则提前退出
            if (isFinished == false)
                break;
        }
    }
}
// end of thin
int main()
{
    RNG rng = RNG(12345);    //随机数
    Mat src = imread("f:/template/lines.png");
    Mat gray; Mat bin; Mat matThin;
    cvtColor(src, gray, COLOR_BGR2GRAY);
    threshold(gray, bin, 0, 255, THRESH_BINARY_INV);
    thin(bin, matThin);
    imshow("matThin", matThin);//展示提取的边缘
    vector<Vec4f> lines;//存储直线的容器
    Mat dst = Mat(src.size(), src.type(), Scalar(255, 255, 255));//创建大小和类型都与源图像相同的背景为白色的图像
    HoughLinesP(matThin, lines, 1, CV_PI / 180, 60, 0, 8);//霍夫变换直线检测
    
    for (int i = 0; i < lines.size(); i++) {
        Scalar  lineColor = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
        Vec4f l = lines[i];
        line(dst, Point(l[0], l[1]), Point(l[2], l[3]), lineColor, 3, LINE_AA);//在创建的白色图像上画直线
         circle(src, Point(l[0], l[1]), 3,Scalar(0,0,255), 2);
         circle(src, Point(l[2], l[3]), 3,Scalar(0,255,0), 1);  
    }
    int i = 0;
}
复制代码

 

 

posted on   jsxyhelu  阅读(373)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示