若该文为原创文章,未经允许不得转载 目录 2.一般来说,对于点(x0,y0),可以通过这个点的一组直线统一定义 3.对于一个给定点(x0,y0),在极坐标对极径和极角平面会出所有通过他的直线将得到一条正弦曲线 5.从以上得出,一条直线能够通过在平面θ-r寻找交于一点的曲线数量来检测。 红胖子来也!!! 去噪、边缘检测之后,就是特征提取了,识别图形的基本方法之一—霍夫变换,霍夫变换是图像处理中的一种特征提取技术,本篇章主要详解讲解了霍夫线变换。 霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,改过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特定形状的集合作为霍夫变换结果。 经典的霍夫变换用来检测图像中的直线,后来霍夫变换扩展到任意形状物体的识别,多为圆和椭圆。 霍夫变换运用两个坐标空间之间的变换将在一个空间中具有相同的形状的曲线或直线映射到另一个坐标控件的一个点上形成峰值,从而把检测任何形状的问题转化为统计峰值问题。 OpenCV中的霍夫变换分为两大类型,线变换下又分三种类型,如下图: 霍夫线变换,从名字就可以知道其实针对直线,显而易见就是用来寻找直线的方法,此处特别注意,使用霍夫线变换之前,肯定是需要对图片进行预处理:降噪、边缘检测处理,霍夫线变换只寻找直线,只能识别边缘二值图像,所以输入也就只能是二值化的图像了。 二值化的图像需要使用二值化的函数,之前边缘检测,得出的颜色是灰度的,还需要使用二值化的函数对灰度图像进行二值化。 霍夫线变换分为三种,如下图: 霍夫线变换会找出大量的线,但是有些线其实是无用的。 霍夫变换采用极坐标的方式来表示直线。 因此直线的表达式是: 得出r公式为: rθ= x0 * cosθ + y0 * sinθ 每一对(rθ,θ)代表一条通过点(x0,y0)的直线。 例如,对于给定点x0=8和y0=6,计算原理如下: 可以会出如下图曲线: 只绘出满足特定条件,如r>0和0<θ<2π,(注意:0表示垂直线,π/2度表示水平线); 如果两个不同点进行上述操作后得到的曲线在平面θ-r相交,这就意味着他们通过同一条直线。 例如,接上面的例子继续对点x1=9,y1=4和x2=12,y2=3绘图如下: 这三条曲线在平面相较于点(0.925, 9.6),坐标表示的是参数对θ-r或者是说点(x0, y0)、(x1, y1)和(x2, y2)组成的平面内的直线,所以其实是计算平面内的每个点的每个角度的距离,绘制成曲线后,如果3个点交叉了,那么3个点就是在一条直线上,示意如下图: (交于一点的曲线的数量超过了阈值(在同一条直线上点的数量),比如上面的示意图,就认为3个点就可以组成一条直线,那么他们可以检测出一跳直线) 越多曲线交于一点也就意味着这个点焦点表示的直线有更多的点组成。一般来说我们可以通过设置直线上点的阈值来定义多少条曲线交于一点,这样才认为检测到了一条直线。 以上就是霍夫变换所做的,它追踪图像中每个点对应曲线的交点,如果交于一点的曲线的数量超过了阈值(在同一条直线上点的数量阈值),那么可以认为这个交点所代表的参数对(θ,rθ)在原图像中为一条直线。 对应版本号v1.37.0 https://blog.csdn.net/shenziheng1/article/details/75307410 原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客地址:https://blog.csdn.net/qq21497936
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105527284
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
OpenCV开发专栏(点击传送门)
OpenCV开发笔记(四十二):红胖子8分钟带你深入了解标准霍夫线变换(图文并茂+浅显易懂+程序源码)
前言
Demo
霍夫变换
概述
标准霍夫线变换
概述
原理
1.一条直线的图像二维空间可由两个变量表示
2.一般来说,对于点(x0,y0),可以通过这个点的一组直线统一定义
3.对于一个给定点(x0,y0),在极坐标对极径和极角平面会出所有通过他的直线将得到一条正弦曲线
4.对图像中所有的点进行上述操作,得到曲线图集合
5.从以上得出,一条直线能够通过在平面θ-r寻找交于一点的曲线数量来检测。
标准霍夫变换函数原型
void HoughLines( InputArray image, OutputArray lines, double rho, double theta, int threshold, double srn = 0, double stn = 0, double min_theta = 0, double max_theta = CV_PI );
补充数据函数原型
cvRound():返回跟参数最接近的整数值,即四舍五入; cvFloor():返回不大于参数的最大整数值,即向下取整; cvCeil():返回不小于参数的最小整数值,即向上取整;
Demo源码
oid OpenCVManager::testHoughLines() { QString fileName1 = "E:/qtProject/openCVDemo/openCVDemo/modules/openCVManager/images/16.jpg"; cv::Mat srcMat = cv::imread(fileName1.toStdString()); int width = 400; int height = 300; cv::resize(srcMat, srcMat, cv::Size(width, height)); cv::Mat colorMat = srcMat.clone(); cv::String windowName = _windowTitle.toStdString(); cvui::init(windowName); cv::Mat windowMat = cv::Mat(cv::Size(srcMat.cols * 2, srcMat.rows * 3), srcMat.type()); cv::cvtColor(srcMat, srcMat, CV_BGR2GRAY); int threshold1 = 200; int threshold2 = 100; int apertureSize = 1; int rh0 = 1; // 默认1像素 int theta = 1; // 默认1° int threshold = 100; // 默认检测到同一直线的100个点 while(true) { qDebug() << __FILE__ << __LINE__; windowMat = cv::Scalar(0, 0, 0); cv::Mat mat; cv::Mat dstMat; cv::Mat grayMat; // 转换为灰度图像 // 原图先copy到左边 cv::Mat leftMat = windowMat(cv::Range(0, srcMat.rows), cv::Range(0, srcMat.cols)); cv::cvtColor(srcMat, grayMat, CV_GRAY2BGR); cv::addWeighted(leftMat, 0.0f, grayMat, 1.0f, 0.0f, leftMat); { cvui::printf(windowMat, srcMat.rows * 1 + 100, srcMat.cols * 0 + 20, "threshold1"); cvui::trackbar(windowMat, srcMat.rows * 1 + 100, srcMat.cols * 0 + 50, 200, &threshold1, 0, 255); cvui::printf(windowMat, srcMat.rows * 1 + 100, srcMat.cols * 0 + 100, "threshold2"); cvui::trackbar(windowMat, srcMat.rows * 1 + 100, srcMat.cols * 0 + 130, 200, &threshold2, 0, 255); cv::Canny(srcMat, dstMat, threshold1, threshold2, apertureSize * 2 + 1); // copy mat = windowMat(cv::Range(srcMat.rows * 1, srcMat.rows * 2), cv::Range(srcMat.cols * 0, srcMat.cols * 1)); cv::cvtColor(dstMat, grayMat, CV_GRAY2BGR); cv::addWeighted(mat, 0.0f, grayMat, 1.0f, 0.0f, mat); cvui::printf(windowMat, srcMat.rows * 1 + 100, srcMat.cols * 1 + 20, "rho"); cvui::trackbar(windowMat, srcMat.rows * 1 + 100, srcMat.cols * 1 + 50, 200, &rh0, 1, 255); cvui::printf(windowMat, srcMat.rows * 1 + 100, srcMat.cols * 1 + 100, "theta = value / 2"); cvui::trackbar(windowMat, srcMat.rows * 1 + 100, srcMat.cols * 1 + 130, 200, &theta, 1, 720); cvui::printf(windowMat, srcMat.rows * 1 + 100, srcMat.cols * 1 + 180, "min points"); cvui::trackbar(windowMat, srcMat.rows * 1 + 100, srcMat.cols * 1 + 210, 200, &threshold, 2, 300); // 边缘检测后,进行霍夫线检测 // 使用霍夫线变化检测所有角度范围内的直线 std::vector<cv::Vec2f> lines; cv::HoughLines(dstMat, // 输入8位 lines, // 输出线 std::vector<std::Vec2f> rh0, // 初步像素精度 theta / 720.0 * CV_PI, // 初步偏移角度精度 threshold, // 必须达到的点的数量 0, // 标准霍夫变换,为0 0, // 标准霍夫变换,为0 0, // 检测角度范围最小为0 CV_PI); // 检测角度范围最大为π,即360° // 在图中绘制出每条线段 dstMat = colorMat.clone(); qDebug() << __FILE__ << __LINE__ << lines.size(); for(int index = 0; index < lines.size(); index++) { float rho = lines[index][0]; float theta = lines[index][1]; cv::Point pt1; cv::Point pt2; double a = cos(theta); double b = sin(theta); double x0 = a * rho; double y0 = b * rho; // 计算出点的坐标 pt1.x = cvRound(x0 + 1000 * (-b)); pt1.y = cvRound(y0 + 1000 * (a)); pt2.x = cvRound(x0 - 1000 * (-b)); pt2.y = cvRound(y0 - 1000 * (a)); // 画线 cv::line(dstMat, pt1, pt2, cv::Scalar(0, 0, 255), 1, cv::LINE_AA); } // copy mat = windowMat(cv::Range(srcMat.rows * 2, srcMat.rows * 3), cv::Range(srcMat.cols * 0, srcMat.cols * 1)); cv::addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat); } // 更新 cvui::update(); // 显示 cv::imshow(windowName, windowMat); // esc键退出 if(cv::waitKey(25) == 27) { break; } } }
工程模板:对应版本号v1.37.0
参考博文
原博主博客导航:https://blog.csdn.net/qq21497936/article/details/102478062
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/105527284
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算