文章目录
前言
在神经网络蓬勃发展的背景下,交通标志识别也不例外的被其轻松解决。
然而本文主要回顾机器学习中,其他经典方法对限速标志的识别,包括K近邻法(knn)、支持向量机(SVM)、集成分类器等。
一、数据集准备
数据集分为10类,限速5、15、30、50以及70(km/s)等等。
数据集下载地址:
提取码:tqlh
以及所用到的vl_feat工具包下载地址:
提取码:yw9y
限速标志5km/s数据如图:
二、特征选择与提取
下载后的数据集里面的.txt文件保存了需要读入的文件名字。
2.1导入工具包
源码使用了著名机器视觉开源库VL-feat.
close all;
clear;
clc
addpath(genpath('vlfeat'));
2.2 读入数据集
路径需要改成你下载数据的路径,注意相对路径和绝对路径,建议使用相对路径。
img_h = 64;
img_w = 64;
%读入训练集
[trainlist, train_label] = textread('./交通路标识别/data/train.txt','%s%n');
[train_num,~]=size(train_label);
Train_hog = zeros(train_num,8*8*31);
for i = 1 : train_num
%读入数据并对其预处理
img_path = ['./交通路标识别/data/', trainlist{i}];
img_train = imread(img_path);
%预处理
img_gama_train=Gamma(img_train, img_h, img_w);
%转换为单精度,对64x128的图片水平方向将有7个扫描窗口,垂直方向将有15个扫描窗口,31个方向。
hog = vl_hog(single(img_gama_train), 8);
Train_hog(i, :) = hog(1:8*8*31);
end
%读入测试集
[testlist, test_label] = textread('./交通路标识别/data/test.txt','%s%n');
[test_num,~]=size(test_label);
Test_hog = zeros(test_num,8*8*31);
for i = 1 : test_num
img_path = ['./交通路标识别/data/', testlist{i}];
img_test = imread(img_path);
%预处理
img_gama_test=Gamma(img_test, img_h, img_w);
hog = vl_hog(single(img_gama_test), 8);
Test_hog(i,:) = hog(1:8*8*31);
end
2.3 PCA对HOG特征降维
利用latent降序特征值,计算贡献率在96%时包含的前idx个特征,构成降维后的特征向量。
%PCA对HOG特征降维
HOG=[Train_hog;Test_hog];
[T,pca_hog,latent,~]=pca(HOG);%T为变换矩阵,train_hog为降维后特征,latent为降序特征值
latent=cumsum(latent)./sum(latent);
lat_idx=find(latent>=0.96);
idx=min(lat_idx);
HOG=pca_hog(:,1:idx);%降维后hog特征
train_hog=HOG(1:train_num,:);
test_hog=HOG(train_num+1:train_num+test_num,:);
column=idx;%变换特征后样本的特征维数column
%保存前idx个特征向量构成的变换矩阵
exa_T=T(:,1:idx);
三、分类器设计
一对多分类(One vs Multiple),以及一对一(One vs One)两者都是特殊的多对多(Multiple vs Multiple);MVM常采用纠错输出码ECOC技术。
采用OvM方案设计多分类器,每个二分类器为SVM分类器,且采用线性核函数时效果更佳。
3.1 SVM分类器
每个分类器训练样本为40个正例,40个负例,且40个负例来源其他类。
% 训练数据分为10类,每个分类器输入样本80
% 每类别i的正样本,选择类别i的全部,负样本从其余类别中随机选择(个数与正样本相同)
n=40;class=10;
train_data=train_hog;
dim=column;
%对数据分类,i代表第i个分类器数据
train_data_hog=zeros(2*n,dim,class);
train_data_label=[ones(n,1);-1*ones(n,1)];
for i=1:class
train_data_hog(1:n,:,i) = train_data((i-1)*n+1:i*n,:);
% randperm(n,k)是从1到n的序号中随机返回k个
index1 = randperm(n*class-n,n);
% 从其余样本中随机选择k个
train_data_c= train_data;
train_data_c((i-1)*n+1:i*n,:) = [];
class_n = train_data_c(index1,:);
%构成第i个分类器训练数据
train_data_hog(n+1:2*n,:,i)=class_n;
end
% 分别训练10个类别的SVM模型
model1 = fitcsvm(train_data_hog(:,:,1),train_data_label,'ClassNames',{'-1','1'},'KernelFunction','linear');
model2 = fitcsvm(train_data_hog(:,:,2),train_data_label,'ClassNames',{'-1','1'},'KernelFunction','linear');
model3 = fitcsvm(train_data_hog(:,:,3),train_data_label,'ClassNames',{'-1','1'},'KernelFunction','linear');
model4 = fitcsvm(train_data_hog(:,:,4),train_data_label,'ClassNames',{'-1','1'},'KernelFunction','linear');
model5 = fitcsvm(train_data_hog(:,:,5),train_data_label,'ClassNames',{'-1','1'},'KernelFunction','linear');
model6 = fitcsvm(train_data_hog(:,:,6),train_data_label,'ClassNames',{'-1','1'},'KernelFunction','linear');
model7 = fitcsvm(train_data_hog(:,:,7),train_data_label,'ClassNames',{'-1','1'},'KernelFunction','linear');
model8 = fitcsvm(train_data_hog(:,:,8),train_data_label,'ClassNames',{'-1','1'},'KernelFunction','linear');
model9 = fitcsvm(train_data_hog(:,:,9),train_data_label,'ClassNames',{'-1','1'},'KernelFunction','linear');
model10 = fitcsvm(train_data_hog(:,:,10),train_data_label,'ClassNames',{'-1','1'},'KernelFunction','linear');
fprintf('-----模型训练完毕-----\n\n');
3.2 测试集
由于数据集标签设置为具体限速数值,此处需要替换为类别1-10,与后面计算得分的下标1-10相对应。
%测试集测试
test_data=test_hog;%加载测试集hog特征
test_features=test_data;
test_label(test_label==5)=1;
test_label(test_label==15)=2;
test_label(test_label==20)=3;
test_label(test_label==30)=4;
test_label(test_label==50)=5;
test_label(test_label==60)=6;
test_label(test_label==70)=7;
test_label(test_label==80)=8;
test_label(test_label==100)=9;
test_label(test_label==120)=10;
% label是n*1的矩阵,每一行是对应测试样本的预测标签;
% score是n*2的矩阵,第一列为预测为“负”的得分,第二列为预测为“正”的得分。
% 用训练好的10个SVM模型分别对测试样本进行预测分类,得到10个预测标签
[~,score1] = predict(model1,test_features);
[~,score2] = predict(model2,test_features);
[~,score3] = predict(model3,test_features);
[~,score4] = predict(model4,test_features);
[~,score5] = predict(model5,test_features);
[~,score6] = predict(model6,test_features);
[~,score7] = predict(model7,test_features);
[~,score8] = predict(model8,test_features);
[~,score9] = predict(model9,test_features);
[~,score10] = predict(model10,test_features);
3.3 性能评估
1.正确率:最终预测标签group_hat与原始标签group比较即可得到全部测试集的正确率
2.P-R指标:分别计算每一类的查准率与查全率。
% 求出测试样本在10个模型中预测为“正”得分的最大值,作为该测试样本的最终预测标签
score = [score1(:,2),score2(:,2),score3(:,2),score4(:,2),score5(:,2),score6(:,2),score7(:,2),score8(:,2),score9(:,2),score10(:,2)];
% 最终预测标签为k*1矩阵,k为预测样本的个数
final_labels = zeros(test_num,1);
for i = 1:test_num
% 返回每一行的最大值和其位置
[~,p] = max(score(i,:));
% 位置即为标签
final_labels(i,:) = p;
end
fprintf('-----样本预测完毕-----\n\n');
% 分类评价指标
group = test_label; % 真实标签
grouphat = final_labels; % 预测标签
[C,~] = confusionmat(group,grouphat,'Order',[1;2;3;4;5;6;7;8;9;10]);%'Order'指定类别的顺序
%正确率
count=0;
for i=1:test_num
if grouphat(i)==test_label(i)
count=count+1;
end
end
fprintf('正确率:%f\n',count/test_num);
%查准率P=TP/(TP+FP),查全率R=TP/(TP+FN);F值是 “查准率和查全率” 的调和平均值
perf_coff=zeros(class,3);%分类器性能度量
for i=1:class
perf_coff(i,1) = C(i,i) / sum(C(:,i));
perf_coff(i,2) = C(i,i) / sum(C(i,:));
perf_coff(i,3) = 2*perf_coff(i,2)*perf_coff(i,1) / (perf_coff(i,1) + perf_coff(i,2));
fprintf('c%i类的查准率为%f,查全率为%f,F测度为%f\n\n',i,perf_coff(i,1),perf_coff(i,2),perf_coff(i,3));
end
一次测试P-R如图
四、总结:
本文为交通限速标志的最后一环:目标识别。而交通标志检测与识别中交通标志的检测亦是重中之重,故下文:“基于颜色与Huff变换的路标检测”
1.检测结果
2.识别结果