1.题目介绍
红绿灯识别一向是自动驾驶实现的难点,而且是不得不攻克的难点。三色识别固然简单,然而这三多干扰中找出红绿灯并进行识别是问题的关键。红绿灯识别算法主要利用了交通灯的色彩特征及形状特征。
2.工作原理
区域提取
由于红绿灯的形状大多为圆形,采用基于形状特征的检测方法,从复杂的场景中,找出图片中的圆形,再对图像进行滤波处理,只留下感兴趣区域。
颜色识别
将RGB色彩转换成HSV模型,通过红绿黄3 种颜色的HSV阈值不同,提取分割后的红绿灯图像中HSV三通道的值,判断图像中何种颜色的分量占据多数,即可判断出此刻红绿灯的状态。
3.核心代码
调整图片大小,锁定纵横比
//调整图片大小
String filename=FileName.toStdString();
Mat src = imread(filename);
if (src.empty())
{
QMessageBox::information(this,"Information","Cannot open the picture");
return -1;
}
int Rows=600;
int Cols=src.cols*600/src.rows;
Mat dst(Rows,Cols,src.type());
cv::resize(src,dst,dst.size(),0,0,INTER_LINEAR);
区域提取
//霍夫变换圆检测
medianBlur(src, mout, 7); cvtColor(mout, mout, COLOR_BGR2GRAY);
cvtColor(mout, mout, COLOR_BGR2GRAY);//转化为灰度图
HoughCircles(mout, circles, HOUGH_GRADIENT, 1, 10, 100, 30, 5, 25);
image:输入图像:8-bit,灰度图
circles:输出圆的结果。
method:定义检测图像中圆的方法。目前唯一实现的方法HOUGH_GRADIENT。
dp:寻找圆弧圆心的累计分辨率,这个参数允许创建一个比输入图像分辨率低的累加器。(这样做是因为有理由认为图像中存在的圆会自然降低到与图像宽高相同数量的范畴)。如果dp设置为1,则分辨率是相同的;如果设置为更大的值(比如2),累加器的分辨率受此影响会变小(此情况下为一半)。dp的值不能比1小。
minDist:该参数是让算法能明显区分的两个不同圆之间的最小距离。
param1 :用于Canny的边缘阀值上限,下限被置为上限的一半。
param2:HOUGH_GRADIENT方法的累加器阈值。阈值越小,检测到的圈子越多。
minRadius :最小圆半径。
maxRadius:最大圆半径
for (int i = 0;( i < circles.size())&&i<100; i++) {
Vec3f c = circles[i];
Point center(c[0], c[1]);
int radius = c[2];
Mat split_circle(src.rows, src.cols, src.type(), Scalar(0, 0, 0));
int count = 0;
for (int x = 0; x < src.cols; x++)
{
for (int y = 0; y < src.rows; y++)
{
int temp = ((x - center.x) * (x - center.x) + (y - center.y) * (y - center.y));
if (temp < (radius * radius))
{
split_circle.at<Vec3b>(Point(x, y))[0] = src.at<Vec3b>(Point(x, y))[0];
split_circle.at<Vec3b>(Point(x, y))[1] = src.at<Vec3b>(Point(x, y))[1];
split_circle.at<Vec3b>(Point(x, y))[2] = src.at<Vec3b>(Point(x, y))[2];
count++;
}
else
{
split_circle[i].at<Vec3b>(Point(x, y))[0] = 0;
split_circle[i].at<Vec3b>(Point(x, y))[1] = 0;
split_circle[i].at<Vec3b>(Point(x, y))[2] = 0;
}
}
}
颜色识别
//转化为hsv模型
cvtColor(image, hsv, COLOR_BGR2HSV);
if (total == 0)
{
return -1;
}
//根据颜色阈值分别得到掩膜
inRange(hsv, lower_green, upper_green, maskGreen);
inRange(hsv, lower_red1, upper_red1, maskRed);
inRange(hsv, lower_yellow, upper_yellow, maskYellow);
//用掩膜进行二值化处理,并统计识别出的像素数目
medianBlur(maskGreen, green_result, 5);
green = countNonZero(green_result);
medianBlur(maskRed, red_result, 5);
red = countNonZero(red_result);
medianBlur(maskYellow, yellow_result, 5);
yellow = countNonZero(yellow_result);
颜色判决
//颜色判决
if ((yellow*1.0/total >= 0.5)|| (red*1.0 / total >=0.5 )|| (green*1.0 / total >= 0.5))
//判断红绿黄三色的像素占比是否过半
{
if (green > red && green > yellow) return 3;
else if (red > yellow) return 2;
else return 1;
}
else
{
return -1;//像素比例不够,退出函数
}
在ARM开发板study210上的效果图,可以实现对包含红绿灯图片中的红绿灯进行识别,并输出在文本框上,以动画的形式显示在左边。
?源代码如下所示:
基于ARM-Linux系统、Qt、OpenCV的红绿灯识别系统源代码-Linux文档类资源-CSDN文库
?
|