交通标识检测c++代码实例及运行结果

环境vs2013+opencv2.4.9

交通标识分为检测和识别两部分,检测只检测红色标识,其他标识同理。本片博客介绍交通标识检测部分,识别部分后续介绍。

c++代码

#include<iostream>
#include<opencv2/opencv.hpp>
#define PI 3.1415926

using namespace std;
using namespace cv;

void RGB2HSV(double red, double green, double blue, double& hue, double& saturation, double& intensity)
{

	double r, g, b;
	double h, s, i;

	double sum;
	double minRGB, maxRGB;
	double theta;

	r = red / 255.0;
	g = green / 255.0;
	b = blue / 255.0;

	minRGB = ((r<g) ? (r) : (g));
	minRGB = (minRGB<b) ? (minRGB) : (b);

	maxRGB = ((r>g) ? (r) : (g));
	maxRGB = (maxRGB>b) ? (maxRGB) : (b);

	sum = r + g + b;
	i = sum / 3.0;

	if (i<0.001 || maxRGB - minRGB<0.001)
	{

		h = 0.0;
		s = 0.0;
	}
	else
	{
		s = 1.0 - 3.0*minRGB / sum;
		theta = sqrt((r - g)*(r - g) + (r - b)*(g - b));
		theta = acos((r - g + r - b)*0.5 / theta);
		if (b <= g)
			h = theta;
		else
			h = 2 * PI - theta;
		if (s <= 0.01)
			h = 0;
	}

	hue = (int)(h * 180 / PI);
	saturation = (int)(s * 100);
	intensity = (int)(i * 100);
}

void fillHole(const Mat srcBw, Mat &dstBw)
{
	Size m_Size = srcBw.size();
	Mat Temp = Mat::zeros(m_Size.height + 2, m_Size.width + 2, srcBw.type());
	srcBw.copyTo(Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)));

	cv::floodFill(Temp, Point(0, 0), Scalar(255));

	Mat cutImg;
	Temp(Range(1, m_Size.height + 1), Range(1, m_Size.width + 1)).copyTo(cutImg);

	dstBw = srcBw | (~cutImg);
}

int main()
{
	Mat srcImg = imread("result\\1.jpg");
	//resize(srcImg, srcImg, Size(204.8, 137.6));重置图片大小为什么检测不到
	imshow("srcImg",srcImg);
	Mat srcImgCopy;
	srcImg.copyTo(srcImgCopy);

	int width = srcImg.cols;//图像宽度
	int height = srcImg.rows;//图像高度
	double B = 0.0, G = 0.0, R = 0.0, H = 0.0, S = 0.0, V = 0.0;
	Mat matRgb = Mat::zeros(srcImg.size(), CV_8UC1);
	int x, y; //循环
	for (y = 0; y<height; y++)
	{
		for (x = 0; x<width; x++)
		{
			// 获取BGR值
			B = srcImg.at<Vec3b>(y, x)[0];
			G = srcImg.at<Vec3b>(y, x)[1];
			R = srcImg.at<Vec3b>(y, x)[2];
			RGB2HSV(R, G, B, H, S, V);
			//红色范围
			if ((H >= 337 && H <= 360 || H >= 0 && H <= 10) && S >= 12 && S <= 100 && V>20 && V<99)
			{
				matRgb.at<uchar>(y, x) = 255;  
			}
		}
	}
	blur(matRgb, matRgb, Size(3, 3));
	Mat element = getStructuringElement(MORPH_ELLIPSE, Size(2 * 1 + 1, 2 * 1 + 1), Point(1, 1));
	Mat element1 = getStructuringElement(MORPH_ELLIPSE, Size(2 * 3 + 1, 2 * 3 + 1), Point(3, 3));
	erode(matRgb, matRgb, element);//腐蚀  
	imshow("erode", matRgb);
	dilate(matRgb, matRgb, element1);//膨胀  
	imshow("dilate", matRgb);
	fillHole(matRgb, matRgb);//填充  
	imshow("fillHole", matRgb);
	Mat matRgbCopy;
	matRgb.copyTo(matRgbCopy);
	//cvtColor(srcImg, grayImg, CV_BGR2GRAY);     
	vector<vector<Point>>contours; //轮廓  
	vector<Vec4i> hierarchy;//分层  
	findContours(matRgb, contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));//寻找轮廓  
	vector<vector<Point>> contours_poly(contours.size());  //近似后的轮廓点集  
	vector<Rect> boundRect(contours.size());  //包围点集的最小矩形vector  
	vector<Point2f> center(contours.size());  //包围点集的最小圆形vector  
	vector<float> radius(contours.size());  //包围点集的最小圆形半径vector  
	for (int i = 0; i < contours.size(); i++)
	{
		approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true); //对多边形曲线做适当近似,contours_poly[i]是输出的近似点集  
		boundRect[i] = boundingRect(Mat(contours_poly[i])); //计算并返回包围轮廓点集的最小矩形  
		minEnclosingCircle(contours_poly[i], center[i], radius[i]);//计算并返回包围轮廓点集的最小圆形及其半径  
	}

	Mat drawing = Mat::zeros(matRgb.size(), CV_8UC3);
	//int count1 = 0;
	for (int i = 0; i < contours.size(); i++)
	{
		Rect rect = boundRect[i];
		//首先进行一定的限制,筛选出区域
		//高宽比限制
		float ratio = (float)rect.width / (float)rect.height;
		//轮廓面积     
		float Area = (float)rect.width * (float)rect.height;
		float dConArea = (float)contourArea(contours[i]);
		float dConLen = (float)arcLength(contours[i], 1);
		if (dConArea < 400)
			continue;
		if (ratio > 2 || ratio < 0.5)
			continue;

		//进行圆筛选,通过四块的缺失像素比较
		Mat roiImage;
		matRgbCopy(rect).copyTo(roiImage);
		Mat temp;
		srcImgCopy(rect).copyTo(temp);
		float C = (4 * PI*dConArea) / (dConLen*dConLen);
		if (C < 0.4)//利用圆度初步对形状进行筛选
			continue;
		srcImgCopy(rect).copyTo(roiImage);
		Scalar color = (0, 0, 255);//蓝色线画轮廓  
		drawContours(drawing, contours_poly, i, color, 1, 8, vector<Vec4i>(), 0, Point());
		rectangle(drawing, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);
		rectangle(srcImg, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);
		imshow("1_1.jpg", srcImg);
		imwrite("result\\1_1.jpg", srcImg);//保存最终的检测识别结果
	}
	waitKey(0);
	//system("pause");
	return 0;
}

运行结果

原始图


检测结果




评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值