OpenCV之霍夫变换检测直线

霍夫变换

首先是笛卡尔坐标系到霍夫空间的转换,比如笛卡尔坐标系中有一条直线 y=ax+b。

笛卡尔坐标系中一条直线,对应霍夫空间的一个点。

反过来同样成立(霍夫空间的一条直线,对应笛卡尔坐标系的一个点)

原理其实很简单

比如

(1)笛卡尔坐标系内y=ax+b 一条直线确定时 它的斜率和截距是确定的 即是a b是确定的,因此到了霍夫空间内就对应一个(a,b) 即是笛卡尔中一条直线对应霍夫空间一个点

(2)笛卡尔坐标系内一个点 比如x1,y1 相当于x1 y1是确定的 在霍夫空间中

b=-xa+y 即是 b=-x1a+y1 代表的是一条直线 即是笛卡尔中一个点对应霍夫空间一条直线

(3)笛卡尔坐标系多个点

这些点如果共线 就相当于回到了(1) 笛卡尔坐标系中一条直线对应霍夫空间一个点

(4)笛卡尔坐标系多个点 不共线

(5)但是 如果直线斜率不存在的时候 霍夫空间那就不容易表示

因此我们换成极坐标 一样的转换原理

先求极坐标方程 其中参数从斜率a和截距b变成 极径p和极角θ

比如下面的变换对比

具体计算过程举例:

OpenCV C++实现

/*
*参数说明:
*src:待检测的原图像
*rho:以像素为单位的距离分辨率,即距离r离散时的单位长度
*theat:以角度为单位的距离分辨率,即角度Θ离散时的单位长度(取值的步长)
*Threshold:累加器阈值,参数空间中离散化后每个方格被通过的
           累计次数大于该阈值,则该方格代表的直线被视为在
           原图像中存在
*lines:检测到的直线极坐标描述的系数数组,每条直线由两个参
       数表示,分别为直线到原点的距离r和原点到直线的垂线与
       x轴的夹角
*/
void myHoughLines(Mat src, double rho, double theat, int Threshold, vector<Vec2f>& lines)
{
    if (src.empty() || rho < 0.1 || theat>360 || theat < 0)
        return;

    int row = src.rows;
    int col = src.cols;
    Mat gray;
    if (src.channels() > 1)
    {
        cvtColor(src, gray, COLOR_BGR2GRAY);
    }
    else
        src.copyTo(gray);

    int maxDistance = sqrt(src.cols * src.cols + src.rows * src.rows); // 图像任意两点最大距离
    int houghMat_cols = 360 / theat;        // theat是角度取值的步长  霍夫变换后距离夹角坐标下对应的Mat的宽(一共多少个θ)
    int houghMat_rows = maxDistance / rho;  // 霍夫坐标距离夹角下对应的Mat的高 就是p的取值个数 
    Mat houghMat = Mat::zeros(houghMat_rows, houghMat_cols, CV_32FC1); // 存储p和 θ的矩阵

    //边缘检测
    Canny(gray, gray, 100, 200, 3);

    //二值化
    threshold(gray, gray, 160, 255, THRESH_BINARY);

    //遍历二值化后的图像
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            if (gray.ptr<uchar>(i)[j] != 0)
            {
                /*从0到360度遍历角度,得到一组关于距离夹角的离散点,即得到
                一组关于经过当前点(i,j)按单位角度theat旋转得到的直线*/
                for (int k = 0; k < 360 / theat; k += theat)
                {
                    // k * CV_PI / 180   是极角 θ 
                    double r = i * sin(k * CV_PI / 180) + j * cos(k * CV_PI / 180);
                    // 找哪个(θ,r)  最多 
                    if (r >= 0)
                    {   // 直线到原点的距离必须大于0 获得在霍夫变换距离夹角坐标系下对应的Mat的行的下标
                        int r_subscript = r / rho;
                        // 经过该直线的点数加1
                        houghMat.at<float>(r_subscript, k) = houghMat.at<float>(r_subscript, k) + 1;
                    }

                }
            }
        }
    }
    /*现在 houghMat 矩阵里面的数值N  是经过这点的线个数(极坐标下)
    比如说 (行,列)对应 (p, θ)  对应的值就是 经过(p, θ)的线一共N条
    经过直线的点数N 大于阈值, 则视为在原图中存在该直线  就要这条直线了 */
    for (int i = 0; i < houghMat_rows; i++)
    {
        for (int j = 0; j < houghMat_cols; j++)
        {
            if (houghMat.ptr<float>(i)[j] > Threshold)
            {
                // line保存直线到原点的距离和直线到坐标原点的垂线和x轴的夹角 求p和θ
                Vec2f line(i * rho, j * theat * CV_PI / 180);
                lines.push_back(line);
            }
        }
    }

}
相关推荐
北京搜维尔科技有限公司35 分钟前
搜维尔科技:【应用】Xsens在荷兰车辆管理局人体工程学评估中的应用
人工智能·安全
说私域38 分钟前
基于开源 AI 智能名片 S2B2C 商城小程序的视频号交易小程序优化研究
人工智能·小程序·零售
YRr YRr38 分钟前
深度学习:Transformer Decoder详解
人工智能·深度学习·transformer
知来者逆43 分钟前
研究大语言模型在心理保健智能顾问的有效性和挑战
人工智能·神经网络·机器学习·语言模型·自然语言处理
云起无垠1 小时前
技术分享 | 大语言模型赋能软件测试:开启智能软件安全新时代
人工智能·安全·语言模型
老艾的AI世界1 小时前
新一代AI换脸更自然,DeepLiveCam下载介绍(可直播)
图像处理·人工智能·深度学习·神经网络·目标检测·机器学习·ai换脸·视频换脸·直播换脸·图片换脸
翔云API2 小时前
PHP静默活体识别API接口应用场景与集成方案
人工智能
浊酒南街2 小时前
吴恩达深度学习笔记:卷积神经网络(Foundations of Convolutional Neural Networks)4.9-4.10
人工智能·深度学习·神经网络·cnn
Tony聊跨境2 小时前
独立站SEO类型及优化:来检查这些方面你有没有落下
网络·人工智能·tcp/ip·ip
懒惰才能让科技进步2 小时前
从零学习大模型(十二)-----基于梯度的重要性剪枝(Gradient-based Pruning)
人工智能·深度学习·学习·算法·chatgpt·transformer·剪枝