番禺论坛网站建设,网易企业邮箱邮件怎么撤回,做软件推广网站怎么赚钱,wordpress gzip插件目录1、前言2、霍夫线变换2.1、霍夫线变换是什么#xff1f;2.2、在opencv中的基本用法2.2.1、HoughLinesP函数定义2.2.2、用法3、识别车道3.1、优化3.1.1、降噪3.1.2、过滤方向3.1.3、截选区域3.1.4、测试其它图片图片1图片2图片31、前言
最近学习opencv学到了霍夫线变换2.2、在opencv中的基本用法2.2.1、HoughLinesP函数定义2.2.2、用法3、识别车道3.1、优化3.1.1、降噪3.1.2、过滤方向3.1.3、截选区域3.1.4、测试其它图片图片1图片2图片31、前言
最近学习opencv学到了霍夫线变换霍夫线变换是一个查找图像中直线的算法它的其中一种应用场景就是识别车道本文以识别车道为例介绍霍夫线的简单用法。
2、霍夫线变换
2.1、霍夫线变换是什么
下面是chatGPT给出的说明 霍夫线变换Hough Line Transform是一种图像处理技术可以用于检测图像中的直线。它的基本思想是将直线转换为参数空间并在参数空间中寻找与图像中的边缘相对应的点从而找到这些直线。霍夫线变换常用于计算机视觉领域例如在车道线检测、图像拼接、人脸识别等方面应用广泛。 原理性的东西这里不讲因为有点复杂我看得也有点懵。
2.2、在opencv中的基本用法
2.2.1、HoughLinesP函数定义
opencv实现霍夫线变换的函数是HoughLinesP它的定义如下。
void HoughLinesP( InputArray image, OutputArray lines,double rho, double theta, int threshold,double minLineLength 0, double maxLineGap 0 );它的参数的含义如下 image8位、单通道二进制源图像。 lines输出线的矢量。每条线由一个4元素矢量表示可以传入vector cv::Vec4i类型。 控制精度 rho累加器的距离分辨率以像素为单位。 theta累加器的角度分辨率弧度。 过滤 threshold累加器阈值参数。 minLineLength最小行长度。小于该长度的线段将被拒绝。 maxLineGap同一条线上链接点的最大允许间隙。
2.2.2、用法
因为HoughLinesP传入的图像必须是8位、单通道二进制源图像所以在传入图像之前需要做转灰度图-》转二进制图的操作。 opencv提供了一些转二进制图的方法因为HoughLinesP的目的是找到直线而直线其实也是轮廓的一部分所以一般我们采用Canny算法来把灰度图转为二进制图。 例程
#include opencv2/core.hpp
#include opencv2/imgcodecs.hpp
#include opencv2/highgui.hpp
#include opencv2/imgproc.hppusing namespace cv;int main() {Mat src imread(road.png);imshow(src, src);Mat gray;cvtColor(src, gray, COLOR_BGR2GRAY);imshow(gray, gray);// Apply Canny edge detectionMat edges;Canny(gray, edges, 50, 150);imshow(canny, edges);// Perform Hough transform to find linesstd::vectorVec4i lines;HoughLinesP(gray, lines, 1, CV_PI / 180, 50, 50, 10);// Draw lines on output imageMat dst src.clone();for (size_t i 0; i lines.size(); i) {Vec4i vline lines[i];line(dst, Point(vline[0], vline[1]), Point(vline[2], vline[3]), Scalar(0, 0, 255), 2);}imshow(dst, dst);waitKey(0);}3、识别车道
首先准备一张图片如下图所示要识别出它的白色车道线。 我们直接使用上一节的例程效果如下。 发现虽然车道是识别出来了但是环境中的纹理也被误认为车道所以要做进一步优化。
3.1、优化
3.1.1、降噪
从上面的Canny图可以看到环境中的树木形成了密密麻麻的纹理这些就是影响效果的因素之一。 经过测试我选用了“二值化 - 》腐蚀 - 》膨胀”的方式来完成降噪经过优化后的代码如下
#include opencv2/core.hpp
#include opencv2/imgcodecs.hpp
#include opencv2/highgui.hpp
#include opencv2/imgproc.hppusing namespace cv;int main() {Mat src imread(/road.png);imshow(src, src);Mat gray;cvtColor(src, gray, COLOR_BGR2GRAY);imshow(gray, gray);//二值化Mat thr;threshold(gray, thr, 100, 255, THRESH_BINARY);imshow(threshold, thr);// 腐蚀Mat eroded;Mat element getStructuringElement(MORPH_RECT, Size(5, 5));erode(thr, eroded, element);// 膨胀Mat dilated;dilate(eroded, dilated, element);imshow(dilated, dilated);// Apply Canny edge detectionMat edges;Canny(dilated, edges, 50, 150);imshow(canny, edges);// Perform Hough transform to find linesstd::vectorVec4i lines;HoughLinesP(edges, lines, 1, CV_PI / 180, 50, 50, 10);// Draw lines on output imageMat dst src.clone();for (size_t i 0; i lines.size(); i) {Vec4i vline lines[i];line(dst, Point(vline[0], vline[1]), Point(vline[2], vline[3]), Scalar(0, 0, 255), 2);}imshow(dst, dst);waitKey(0);
}优化后的效果如下 从Canny中明显可以看到环境纹理少了很多。
3.1.2、过滤方向
在上图中可以看到还有一些横向的纹理影响了效果我们可以通过直线的方向来做进一步过滤。 在车的视角下车道是朝中间斜的两边车道成八字型如图所示。 也就是说车道的线在图像上倾斜角度不会小所以我们可以在得出最终结果时添加一个过滤条件倾斜角度小于20度的直线不满足条件。 修改代码如下
.....// Perform Hough transform to find linesstd::vectorVec4i lines;HoughLinesP(edges, lines, 1, CV_PI / 180, 50, 50, 10);// Draw lines on output imageMat dst src.clone();for (size_t i 0; i lines.size(); i) {Vec4i vline lines[i];/* 过滤倾斜45度及以下的斜线 */float tanVal (float)(vline[3] - vline[1]) / (vline[2] - vline[0]);if (abs(tanVal) tan(CV_PI / 18)) continue;line(dst, Point(vline[0], vline[1]), Point(vline[2], vline[3]), Scalar(0, 0, 255), 2);}
.......效果
3.1.3、截选区域
在识别车道时因为车道是在车的脚下需要识别的图像只有相机拍下的下半截所以这里还可以加多一层优化把上半截图像砍掉只处理下半截图像。 修改代码
int main() {Mat src imread(road.png);Rect vaildRect(0, src.rows / 2, src.cols, src.rows / 2);Mat src src(vaildRect);imshow(src, src);
......效果
3.1.4、测试其它图片
图片1
因为拍照时的亮度不一所以需要根据亮度来调整二值化时的阀值此例用的是 threshold(gray, thr, 170, 255, THRESH_BINARY);
图片2 图片3
threshold(gray, gray, 150, 255, THRESH_BINARY);