1. 程式人生 > >交通標識牌檢測及識別c++程式碼例項及執行結果 (可自行在網上下載圖片測試)

交通標識牌檢測及識別c++程式碼例項及執行結果 (可自行在網上下載圖片測試)

執行環境:vs2013+opencv2.4.9+win10

資料來源於GTSRB

效果不是很理想(預處理方法、檢測用的rgb2hsv、圓度檢測,、引數,總之改變程式中很多東西可以嘗試提高準確率),但檢測及識別的道路是打通了

c++程式碼

#include<iostream>
#include<opencv2/opencv.hpp>
#include<string>
#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;
		//return ;
	}
	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()
{
	char path[512];
	CvSVM classifier;//載入分類器
	classifier.load("E:\\vs2013\\opencv_code\\GTSRBtrafficSign\\train\\train.xml");//路徑
	for (int k = 0; k<10; k++)//k為測試圖片數量
	{
		sprintf_s(path, "E:\\vs2013\\opencv_code\\GTSRBtrafficSign\\extractAndPredict\\image\\%d.jpg",k+1);
 		cout << path << endl;
		Mat src = imread(path);
		Mat copy;
		src.copyTo(copy);
		int width = src.cols;   //影象寬度
		int height = src.rows;   //影象高度
		//色彩分割
		double B = 0.0, G = 0.0, R = 0.0, H = 0.0, S = 0.0, V = 0.0;
		Mat matRgb = Mat::zeros(src.size(), CV_8UC1);
		Mat Mat_rgb_copy;//一個暫存單元
		int x, y;
		for (y = 0; y<height; y++)
		{
			for (x = 0; x<width; x++)
			{
				B = src.at<Vec3b>(y, x)[0];
				G = src.at<Vec3b>(y, x)[1];
				R = src.at<Vec3b>(y, x)[2];
				RGB2HSV(R, G, B, H, S, V);
				//紅色:337-360
				if ((H >= 337 && H <= 360 || H >= 0 && H <= 10) && S >= 12 && S <= 100 && V>20 && V<99)
				{
					matRgb.at<uchar>(y, x) = 255;
				}
			}
		}
		//imshow("hsi",Mat_rgb);
		//imshow("Mat_rgb",Mat_rgb);
		medianBlur(matRgb, matRgb, 3);
		//imshow("medianBlur", Mat_rgb);
		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", Mat_rgb);
		dilate(matRgb, matRgb, element1);//膨脹
		//imshow("dilate", Mat_rgb);
		fillHole(matRgb, matRgb);//填充 
		//imshow("fillHole", Mat_rgb);
		matRgb.copyTo(Mat_rgb_copy);
		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];
			//cout << rect<<endl;
			//高寬比限制
			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;
			Mat_rgb_copy(rect).copyTo(roiImage);
			//imshow("roiImage",roiImage);
			//imshow("test",roiImage);
			Mat temp;
			copy(rect).copyTo(temp);
			//imshow("test2",temp);//顯示從場景圖中提取出的標識,留著。

			copy(rect).copyTo(roiImage);
			//*********svm*********
			Mat temp2 = Mat::zeros(temp.size(), CV_8UC1);
			cvtColor(temp, temp2, CV_BGR2GRAY);
			//resize(temp2, temp2, Size(48, 48));
			resize(temp2, temp2, Size(30, 30));//30*30=900
			temp2 = temp2.reshape(0, 1);
			temp2.convertTo(temp2, CV_32F);
			cout << temp2.size() << endl;
			
 			int result = (int)classifier.predict(temp2) - 1;//svm預測
			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(src, boundRect[i].tl(), boundRect[i].br(), color, 2, 8, 0);
			//putText(src, labelname[result], cvPoint(boundRect[i].x, boundRect[i].y - 10), 1, 1, CV_RGB(255, 0, 0), 2);//紅色字型註釋
			//circle( drawing, center[i], (int)radius[i], color, 2, 8, 0 );
			count1++;
			//sprintf_s(path, "E:\\vs2013\\opencv_code\\GTSRBtrafficSign\\extractAndPredict\\image\\result/%d_%d.jpg", k, count1);
			sprintf_s(path, "E:\\vs2013\\opencv_code\\GTSRBtrafficSign\\extractAndPredict\\image\\%d_%d.jpg",k+1, count1);
			imwrite(path, src);//儲存最終的檢測識別結果
		}
	}
	system("pause");
	waitKey(0);
	return 0;
}


執行結果

相關推薦

交通標識檢測識別c++程式碼例項執行結果 自行網上下載圖片測試

執行環境:vs2013+opencv2.4.9+win10 資料來源於GTSRB 效果不是很理想(預處理方法、檢測用的rgb2hsv、圓度檢測,、引數,總之改變程式中很多東西可以嘗試提高準確率),但檢測及識別的道路是打通了 c++程式碼 #include<iostr

Opencv檢測交通中紅色標識輪廓c++程式碼例項執行結果

環境vs2013+opencv2.4.9 c++程式碼 #include<opencv2/opencv.hpp> #include<iostream> #define PI 3.1415926 using namespace std; using

opencv讀取彩色/灰度圖片畫素值並存儲在本地檔案中c++程式碼例項執行結果

c++程式碼彩色圖片#include<opencv2/opencv.hpp> #include<fstream> using namespace std; using namespace cv; int main(int argc, char* ar

篩選法查詢1000以內的素數c++程式碼例項執行結果

c++程式碼 #include <iostream> #include<iomanip> #define N 1000 using namespace std; int main() { int array[N];//陣列array標記是否

刪除特定位置前面的字串c++程式碼例項執行結果

原始字串樣式 c++程式碼 #include<iostream> #include<string> #include<vector> #include<fstream> using namespace std; int

C語言身份證資訊查詢系統驗證輸入身份證是否合法

利用C語言做的一個身份證資訊查詢系統。 原理很簡單,也沒什麼技術難度,城市資訊不是很多,就一併加入到了原始碼中了。 關於身份證非法的判斷還是很有用的,另外以下程式碼如有需要的可以直接使用或根據需要修改原始碼。 (有待改進實現檔案讀取查詢,那樣城市資訊可以更新的更加詳

gsoap入門:C/C++程式碼生成編譯--包含soapcpp2 -qname新增名稱空間後報錯的解決方法--可用

gsoap是什麼 先來一段百度百科,說說gsoap是什麼: gSOAP一種跨平臺的開源的C/C++軟體開發工具包。生成C/C++的RPC程式碼,XML資料繫結,對SOAP Web服務和其他應用形成高效的具體架構解析器,它們都受益於一個XML介面。 這個工具包提供了一個全面和透明的XML資料繫結解決方案,A

墨卡託投影座標系Mercator Projection原理實現C程式碼

轉:https://www.cnblogs.com/DHUtoBUAA/p/6706642.html   墨卡託投影是一種“等角正切圓柱投影”,荷蘭地圖學家墨卡託(Mercator)在1569年擬定:假設地球被圍在一箇中空的圓柱裡,其赤道與圓柱相接觸,然後再假

交通標誌牌的檢測識別

             Driver Assistance System已經成為學術研究的一大領域,作為智慧交通的一部分,有大量研究人員投身其中,每年都會有大量的成果發表在IEEE trans on intelligent transportation system

MD5演算法的C程式碼實現測試

本程式主要是通過 rfc1321.txt 整理而來。這個檔案可以在下面的地址下載。 本程式在VC 2003 .NET 和 Dev C++ 4.9下編譯通過。 #include <stdio.h> typedef struct { unsigned int

matlab程式碼C++程式碼轉化使用全攻略

1.在matlab中輸入命令: mbuild -setup 安裝編譯器。(注意點:選擇計算機上已有的VC/VS編譯器,並輸入相應的路徑) 2.在matlab中輸入命令: deploytool   進入該模式 3.按新建按鈕,選擇C++ Shared Library,進行工程

Aras學習筆記 (12) C#程式碼讀取域使用者列表轉,翻譯

Get List of Active Directory Users in C# - 作者原文標題 Introduction  This tip describes how to list Active Directory users.  介紹如何提取AD域中的使用者列表 Using

通俗易懂地理解執行緒池&&C++程式碼例項與講解

本機環境:win10   64位   vs2017 C++新手,程式碼寫得比較一般,高手見諒(抱拳)。 歡迎留言交流! 簡介執行緒池: 在介紹執行緒池之前,我們要首先知道多執行緒是啥。 單執行緒:就是說你現在有四件毫不相干的事情要分

使用VisualStudio完成自動化C++程式碼生成和編譯工作GacUI

    GacUI終於進入製作dll的階段了。昨天上傳了一個新的工程,在Vczh Library++3.0(E:\Codeplex\vlpp\Workspace\Tools\Release\SideProjects\GacUI\GacUI.sln)。這裡面一共有三個工程,有兩個是工具,一個是dll。    為

Android Studio開發jni例項詳解 (呼叫C程式碼例項)

FATAL EXCEPTION: main Process: com.example.jni.jnitest, PID: 30152 java.lang.UnsatisfiedLinkError: com.android.tools.fd.runtime.IncrementalClassLoader$Dele

一個例子告訴你什麼是封裝,繼承和多型(C++ 程式碼例項)

add by WJB   date 2018/08/30 面向物件的三大特性:封裝,繼承和多型; 封裝:將事物擁有的屬性和動作隱藏起來,只保留特定的方法與外界聯絡。 繼承:子類可以擁有父類的屬性和方法; 多型:以說是“一個介面,多種實現”或者說是父類的引用變數可以指向

c++使用樸素遞迴演算法自頂向下遞迴和動態規劃dp帶備忘的自頂向下,自底向上解決鋼條切割執行例項結果

本博文資料來源於演算法導論第三版 動態規劃有兩種等價實現方法:帶備忘的自頂向下發(topDownWithMemoization),自底向上方法,付出額外的記憶體空間來節省計算時間,是典型的時空權衡,遞迴時會儲存每個子問題的解 長度n與對應價格p關係 1~10的對應最

改進你的c#程式碼的5個技巧

親愛的讀者,在這篇文章中,我提供了一些c#程式設計的最佳實踐。 你是否在使用者輸入驗證中使用異常處理機制? 如果是,那麼你就是那個把你的專案執行速度降低了62倍的人。你不相信我嗎?等幾分鐘;我來教你怎麼做。但是在這個例子之前,讓我們瞭解一下在什麼地方需要異常處理。 例如,你正在驗證使用者的資料,對於任何無

改進你的c#程式碼的5個技巧

在本文中,我將向你展示c#程式設計的5個最佳實踐。我從日常程式設計經驗中學到了這些實踐。我在release模式下測試了所有的程式碼,並在開發環境穩定後進行了截圖。我想你會喜歡這些建議的。 在使用資料型別之前選擇它 對於許多型別,我們寧願不決定在日常程式設計生活中使用什麼資料型別。就在幾個月前,我也是其中之

改進你的c#程式碼的5個技巧

本文完全獨立於前兩篇文章。如果你喜歡它們,我希望你也會喜歡這個。在上一篇文章中,我展示了哪種方法更快,並比較了程式碼的執行速度。在本文中,我將展示不同程式碼片段的記憶體消耗情況。為了顯示記憶體對映和分配圖,我使用了CLR profiler 32位版本,和往常一樣,我在Windows平臺上使用了4GB RAM和