用opencv实现道路交通标志牌的检测

要求编程实现一个道路交通标志牌的检测,以颜色特征作为检测手段,且只需要检测含有红、白两种颜色的标志牌。编程实现的过程主要分为以下几步:转化到HSV空间,直方图均衡化减少亮度不均匀的影响。采用一种阈值化的方法将红色部分检测出来,检测结果以二值图像呈现;然后进行形态学运算,进行边缘、噪点、连通区域的处理;最后再用轮廓查找算法找出红色部分轮廓,将轮廓以最小外接矩形的方式在原图中画出来。为保证识别的准确性,再对识别出来的目标物体的最小外接矩形进行长宽比、面积的判别,它们必须处于一定范围,实际情况也是处于一定范围。下面是程序:

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

using namespace cv;
using namespace std;

void on_threshold1(int, void *);
void on_threshold2(int, void *);
void on_threshold3(int, void *);
void find_contours(Mat inputImage);

Mat src = imread("RoadSigns7.jpg");
Mat src1 = src.clone();
Mat RedImage;
int lowerH = 156, lowerS =178, lowerV = 46;
vector<Vec4i> hierarchy;

int main()
{
imshow("原图", src1);
cvtColor(src1, src1, CV_BGR2HSV);
//对亮度进行直方图均衡化
vector<Mat> channels;
split(src1, channels);
equalizeHist(channels[2], channels[2]);
merge(channels, src1);
//提取红色区域
Mat RedImage1;
inRange(src1, Scalar(lowerH, lowerS, lowerV), Scalar(180, 255, 255), RedImage);
inRange(src1, Scalar(0, lowerS, lowerV), Scalar(10, 255, 255), RedImage1);
addWeighted(RedImage, 1, RedImage1, 1, 0, RedImage);
imshow("提取的红色区域", RedImage);
namedWindow("control", WINDOW_AUTOSIZE);
createTrackbar("lowerh", "control", &lowerH, 180,on_threshold1);
createTrackbar("lowers", "control", &lowerS, 255, on_threshold2);
createTrackbar("lowerv", "control", &lowerV, 255,on_threshold3);

//开运算,去除图像的一些噪点
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5));
Mat dst2;
morphologyEx(RedImage, dst2, CV_MOP_CLOSE, element);
morphologyEx(dst2, dst2, CV_MOP_CLOSE, element);
morphologyEx(dst2, dst2, CV_MOP_CLOSE, element);
imshow("形态学运算之后", dst2);
//对二值图像找最外层轮廓,用最小外接矩形圈出,矩形面积大于某个值才作为检测目标
find_contours(dst2);

waitKey(0);
return(0);
}
void on_threshold1(int lowerH,void *)
{
inRange(src1, Scalar(lowerH, lowerS, lowerV), Scalar(180, 255, 255), RedImage);
imshow("dst1", RedImage);
}
void on_threshold2(int lowerS, void *)
{
inRange(src1, Scalar(lowerH, lowerS, lowerV), Scalar(180, 255, 255), RedImage);
imshow("dst1", RedImage);
}
void on_threshold3(int lowerV, void *)
{
inRange(src1, Scalar(lowerH, lowerS, lowerV), Scalar(180, 255, 255), RedImage);
imshow("dst1", RedImage);
}
void find_contours(Mat inputImage)
{
vector<vector<Point>> contours0;
RotatedRect rect;
findContours(inputImage, contours0, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
Point2f vtx[4];
double rato1,rato2,rato;
double length, height;
for (int i = 0;i < contours0.size();i++)
{
rect=minAreaRect(contours0.at(i));
rect.points(vtx);
length = sqrt((vtx[3].x - vtx[2].x)*(vtx[3].x - vtx[2].x) + (vtx[3].y - vtx[2].y)*(vtx[3].y - vtx[2].y));
height = sqrt((vtx[3].x - vtx[1].x)*(vtx[3].x - vtx[1].x) + (vtx[3].y - vtx[1].y)*(vtx[3].y - vtx[1].y));
rato1 = length / height;
rato2 = height / length;
rato = (rato1 <= rato2)? rato1 : rato2;
cout <<"长宽比:"<<rato << endl;
cout << "面积:" << length*height << endl;
if(0.7<=rato && rato<=0.91)
{
cout << "入围点长宽比:" <<rato<< endl;
cout << "入围点面积:" << length*height << endl;

if ((length*height) >=2646)
{
cout << endl;
cout << "-------实际点面积:" << length*height << endl;
for (int j = 0; j < 4; j++)
{
line(src, vtx[j], vtx[(j + 1) % 4], Scalar(0, 255, 0),2, LINE_AA);
}
}
}
}
imshow("检测图", src);
}

猜你喜欢

转载自www.cnblogs.com/nanjingli/p/9147604.html