OpenCV(C++)识别结构化道路

一、前提

        课程中提供了关于MATLAB识别道路的代码。代码如下

srcImage = imread('lane.jpg');%读取图像
grayImage = rgb2gray(srcImage);%灰度图?
denoisedImage = medfilt2(grayImage, [5,5]); %中值滤波 
H = fspecial('sobel'); %预定义边缘增强算子为sobel算子
sobelImage= imfilter(denoisedImage, H); %采用sobel算子突出边缘 
% imshow(sobelImage);
thresh = graythresh(sobelImage); %通过Otsu方法获得阈值
% imshow(thresh);
binaryImage = imbinarize(sobelImage, thresh); %图像二值化
% imshow(binaryImage);
[H, theta, rho] = hough(binaryImage); %hough变换
p=houghpeaks(H, 8, 'threshold', ceil(0.3*max(H(:)))); %获取hough空间中前5个最大点
lines = houghlines(binaryImage,theta, rho,p,'FillGap',50,'MinLength',60); %通过hough空间中找到图像中对应的直线段
line_length_thred = 100;%车道线长度阈值?
slope_thred = 0.3;%车道线斜率阈值?
imshow(srcImage);
for k = 1:length(lines)
    xy = [lines(k).point1; lines(k).point2];
    line_length = sqrt((xy(1,1)-xy(2,1)) * (xy(1,1)-xy(2,1)) + (xy(1,2)-xy(2,2)) * (xy(1,2)-xy(2,2)));%线段长度
    %根据线段长度筛除部分线段
    if(line_length < line_length_thred)
        continue;
    end
    slopes = (xy(1,2)-xy(2,2)) / (xy(1,1)-xy(2,1)); %斜率
    %根据线段斜率筛除部分线段
    if abs(slopes) < slope_thred
        continue;
    end
    %在图像上画出车道
    xx = [xy(1,1), xy(2,1)];
    yy = [xy(1,2), xy(2,2)];
%     plot(xx,yy,'LineWidth',2,'Color','green');
    line(xx, yy,'LineWidth',2,'Color','green');
end

        所处理的图像如图所示:

二、转化为C++代码

(一)展示图像

        将图像展示封装成函数进行使用。

// 图片展示封装
void PictureShow(const cv::Mat pic)
{
	cv::imshow("haha", pic);
	cv::waitKey();
}

(二)转化为灰度图

        转化为灰度图。需要包含头文件,CV_BGR2GRAY才可以使用。

        具体参考opencv4中未定义标识符CV_BGR2GRAY和CV_CAP_PROP_FRAME_COUNT问题-CSDN博客

// 转化为灰度图使用
#include <opencv2/imgproc/types_c.h>	// 里面包含着CV_BGR2GRAY,转换为灰度图使用

// 图片转化为灰度值图片
void myFunction2Gray(cv::Mat& pic)
{
	cv::Mat grey;
	cv::cvtColor(pic, grey, CV_BGR2GRAY);
	pic = grey;
}

(三)中值滤波

        进行中值滤波。

        可参考C/C++ OpenCV中值滤波&双边滤波_opencv c++ 消除笔-CSDN博客

// 中值滤波
void myFunctionMedianBlur(cv::Mat& pic)
{
	cv::Mat out;
	// cv::medianBlur最后一个参数是滤波模块的大小
	cv::medianBlur(pic, out, 5);
	pic = out;
	//PictureShow(pic);
}

(四)使用sobel算子进行边缘增强

        使用sobel算子进行边缘增强。分别包含x方向、y方向以及xy两者的混合梯度。测试之后发现只使用x方向的梯度效果最好。

        可以参考Opencv(C++)学习系列---Sobel索贝尔算子边缘检测_cv::sobel-CSDN博客【OpenCV3】cv::convertScaleAbs()使用详解_cv.convertscaleabs-CSDN博客

// 使用sobel算子进行边缘增强
void myFunctionSobel(cv::Mat& pic)
{
	// grad_x是求x方向的梯度,grad_y是求y方向的梯度
	cv::Mat grad_x, grad_y;
	cv::Mat abs_grad_x, abs_grad_y, dst;

	// 计算x方向的梯度
	cv::Sobel(pic, grad_x, CV_16S, 1, 0, 3);
	//PictureShow(grad_x);	// 这个图像不能看
	// 需要使用这个
	cv::convertScaleAbs(grad_x, abs_grad_x);
	//PictureShow(abs_grad_x);

	// 计算y方向的梯度
	//cv::Sobel(pic, grad_y, CV_16S, 0, 1, 3);
	//PictureShow(grad_x);	// 这个图像不能看
	// 需要使用这个
	//cv::convertScaleAbs(grad_y, abs_grad_y);
	//PictureShow(abs_grad_y);

	// 合并梯度(近似)
	//cv::addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, dst);
	//PictureShow(dst);
	
	//pic = dst;
	pic = abs_grad_x;
	//pic = abs_grad_y;
	//PictureShow(pic);
}

(五)计算Otsu所需要的阈值范围

        使用Otsu算法进行二值化处理。

        可以参考OpenCV基础——threshold函数的使用_cv::threshold-CSDN博客

// 使用Ostu算法
void myFunctionOtsu(cv::Mat& pic)
{
	cv::Mat temp;
	cv::threshold(pic, temp, 0, 255, CV_THRESH_OTSU);
	PictureShow(temp);
	pic = temp;
}

(六)使用hough,并绘制图像

        使用hough,并绘制图像。

        可以参考hough transform algorithm c++-掘金

        https://www.cnblogs.com/nipan/p/4162747.html

// 使用hough变换
void myFunctionHough(cv::Mat& pic, cv::Mat& src)
{
	//vector<Vec2f> lines;
	vector<cv::Vec2f> lines;
	cv::HoughLines(pic, lines, 1, CV_PI / 180, 100, 0, 0);

	//cout << lines.size() << endl;
	for (size_t i = 0; i < lines.size(); i++)
	{
		double rho = lines[i][0], theta = lines[i][1];
		cv::Point pt1, pt2;
		double a = cos(theta), b = sin(theta);
		double x0 = a * rho, 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));
		/*pt1.x = cvRound(x0);
		pt2.y = cvRound(y0);*/
		cv::line(src, pt1, pt2, cv::Scalar(0, 0, 255), 3, cv::LINE_AA);
		//PictureShow(src);
	}
	PictureShow(src);
}

 (七)主函数及头文件

#include <iostream>
#include <opencv2/opencv.hpp>

// 转化为灰度图使用
#include <opencv2/imgproc/types_c.h>	// 里面包含着CV_BGR2GRAY,转换为灰度图使用

// 中值滤波使用、sobel算子使用、使用Ostu
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>

int main(int argc, char** argv)
{
	// 图片路径
	const char* imagePath = "D:/北京理工大学/学习/大三下学期/智能无人车/test/one/lane.jpg";
	// 读取图片
	cv::Mat pic = cv::imread(imagePath);
	// 将原图图像保存
	cv::Mat src = pic;

	// 转化为灰度图像
	myFunction2Gray(pic);

	// 中值滤波
	myFunctionMedianBlur(pic);

	// 使用sobel算子
	myFunctionSobel(pic);

	// 使用Otsu算法
	myFunctionOtsu(pic);

	// hough变换
	myFunctionHough(pic, src);

	// 展示图片进行测试
	//cv::imshow("zhanshi", pic);
	//cv::waitKey();
	//PictureShow(pic);
	
	return 0;

}

 (八)结果展示

 三、总结

        可以识别出来,但是效果不好,后续进行改进。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GFCGUO

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值