py4CV例子2.5车牌识别和svm算法重构
1、什easypr数据集;
e
asyPR是一个开源的中文车牌识别系统,其目标是成为一个简单、高效、准确的非限制场景(unconstrained situation)下的车牌识别库。
相比于其他的车牌识别系统,EasyPR有如下特点:
- 它基于openCV这个开源库。这意味着你可以获取全部源代码,并且移植到opencv支持的所有平台。
- 它能够识别中文。例如车牌为苏EUK722的图片,它可以准确地输出std:string类型的"苏EUK722"的结果。
- 它的识别率较高。图片清晰情况下,车牌检测与字符识别可以达到80%以上的精度。点
它以 General Data Share License形式公开了一些中文汽车图片
因为我使用了交叉严重,所以不需要分目录放,直接可以把pos和neg图片各自放到一个目录下面。
2、重构算法,运行于easypr;
import cv2
import numpy
as np
from os.path
import join
import numpy
as np
import os
import math
#在carData建立svm模型并且k_fold测试,ratio=1表示全部数据用于测试
RATIO =
0.2
datapath =
"D:/dl4cv/datesets/EasyPRresources/train/svm/"
#分为has和no两个文件夹,全部取jpg图片
#根据Ratio获得训练和测试数据集的图片地址和标签
def
get_files(
file_dir,
ratio):
'''
Args:
file_dir: file directory
Returns:
list of images and labels
'''
pos = []
label_pos = []
neg = []
label_neg = []
for
file
in os.listdir(file_dir+
"has/"):
pos.append(file_dir +
"has/"+
file)
label_pos.append(
1)
for
file
in os.listdir(file_dir+
"no/"):
neg.append(file_dir +
"no/"+
file)
label_neg.append(
1)
print(
'数据集中有
%d
pos
\n
以及
%d
neg ' %(
len(pos),
len(neg)))
#图片list和标签list
#hstack 水平(按列顺序)把数组给堆叠起来
image_list = np.hstack((pos, neg))
label_list = np.hstack((label_pos, label_neg))
temp = np.array([image_list, label_list])
temp = temp.transpose()
#乱序的目的是为了让正样本和负样本混在一起,这样直接取其中百分之多少就可以来用了
np.random.shuffle(temp)
all_image_list = temp[:,
0]
all_label_list = temp[:,
1]
n_sample =
len(all_label_list)
#根据比率,确定训练和测试数量
n_val = math.ceil(n_sample*ratio)
# number of validation samples
n_train = n_sample - n_val
# number of trainning samples
tra_images = []
val_images = []
#按照0-n_train为tra_images,后面位val_images的方式来排序
tra_images = all_image_list[:n_train]
tra_labels = all_label_list[:n_train]
tra_labels = [
int(
float(i))
for i
in tra_labels]
val_images = all_image_list[n_train:]
val_labels = all_label_list[n_train:]
val_labels = [
int(
float(i))
for i
in val_labels]
return tra_images,tra_labels,val_images,val_labels
#创建sift特征提取
detect = cv2.xfeatures2d.SIFT_create()
extract = cv2.xfeatures2d.SIFT_create()
#创建基于flann的匹配器
flann_params =
dict(
algorithm =
1,
trees =
5)
matcher = cv2.FlannBasedMatcher(flann_params, {})
#创建bow训练器
bow_kmeans_trainer = cv2.BOWKMeansTrainer(
40)
extract_bow = cv2.BOWImgDescriptorExtractor(extract, matcher)
#以灰度方式读取图像,提取sift,并返回结果
def
extract_sift(
fn):
im = cv2.imread(fn)
try:
cv2.cvtColor(im,im,cv2.COLOR_BGR2GRAY)
except :
pass
return extract.compute(im, detect.detect(im))[
1]
#返回bow的描述符提取器计算得到的描述符
def
bow_features(
fn):
im = cv2.imread(fn,
0)
return extract_bow.compute(im, detect.detect(im))
#返回预测的结果
def
predict(
fn):
f = bow_features(fn);
p = svm.predict(f)
print(fn,
"
\t
", p[
1][
0][
0])
return p
############################################# main ###############################################
#获得训练和测试数据集的图片地址和标签
train_images, train_labels, val_images, val_labels = get_files(datapath, RATIO)
traindata, trainlabels = [],[]
#为feature模型输入正负样本
for i
in
range(
20):
try:
bow_kmeans_trainer.add(extract_sift(train_images[i]))
except :
pass
#feature模型聚类,返回词汇表
voc = bow_kmeans_trainer.cluster()
extract_bow.setVocabulary( voc )
#创建并训练一个svm模型
print(
"创建并训练一个svm模型")
for i
in
range(
len(train_images)):
try:
traindata.extend(bow_features(train_images[i]))
trainlabels.append(train_labels[i])
except :
pass
svm = cv2.ml.SVM_create()
svm.train(np.array(traindata), cv2.ml.ROW_SAMPLE, np.array(trainlabels))
print(
"在测试集上进行测试")
#在测试集上进行测试
result = []
for i
in
range(
len(val_images)):
try:
f = bow_features(val_images[i]);
p = svm.predict(f)
result.append(p[
1][
0][
0])
except :
result.append(
0)
np_val_labels = np.array(val_labels)[:,np.newaxis]
np_result = np.array(result)[:,np.newaxis]
matches = np_result == np_val_labels
correct = np.count_nonzero(matches)
accuracy = correct*
100.0/
len(result)
print(accuracy)
这里对相关算法进行了重构,主要是以下几个方面
1、将获得交叉数据集的函数和创建features的几个函数进行了重构,这样实现算法流程清晰;
2、添加了异常控制,避免错误;
3、添加了一些流程控制。
结果:
数据集中有 1917 pos
以及 3978 neg
创建并训练一个svm模型
在测试集上进行测试
96.09838846480068
附件列表