CNN——基于CNN的车牌号识别

CNN——基于CNN的车牌识别
car-board-reg
数据集介绍
车牌构成
为简化实验,在该实验中默认车牌字符已经得到划分,因此车牌识别可以分解为三个区域的字符识别任务(多分类任务),共实现7个字符的识别。
例如:京A·F0236
其中第⼀部分 京 表⽰车牌所在的省市,后⾯紧跟的A是发牌单位,间隔符·后⾯的5个字符就是序号。
省市Province:
(“皖”, “沪”, “津”, “渝”, “冀”, “晋”, “蒙”, “辽”, “吉”, “⿊”, “苏”, “浙”, “京”, “闽”, “赣”, “鲁”, “豫”,“鄂”, “湘”, “粤”, “桂”, “琼”, “川”, “贵”, “云”, “藏”, “陕”, “⽢”, “青”, “宁”, “新”)
发牌单位Area:
(“A”,“B”,“C”,“D”,“E”,“F”,“G”,“H”,“I”,“J”,“K”,“L”,“M”,“N”,“O”,“P”,“Q”,“R”,“S”,“T”,“U ”,“V”,“W”,“X”,“Y”,“Z”)
字符Letter:
(“0”,“1”,“2”,“3”,“4”,“5”,“6”,“7”,“8”,“9”,“A”,“B”,“C”,“D”,“E”,“F”,“G”,“H”,“J”,“K”,“L ”,“M”,“N”,“P”,“Q”,“R”,“S”,“T”,“U”,“V”,“W”,“X”,“Y”,“Z”)
数据集⽬录:
└─dataset
├─maps.py    ---->映射关系⽂件
幻听的中药
├─train    ---->训练
│├─area
│├─letter
│└─province
└─val      ----->验证集
├─area
├─letter
└─province
PIL读取Image⽂件
本例提供的训练集⾥⾯的每个图⽚都是20x20 的⼆值化后的灰度图,例如:
因此,我们需要使⽤PIL库或opencv库把灰度图转换为我们⽅便处理的数据形式。本⼈是先转化为list of list.
__author__ ='jmh081701'
from PIL import  Image
def img2mat(img_filename):
#把所有的图⽚都resize为20x20
img = Image.open(img_filename)
img = size((20,20))
mat =[[pixel((x,y))for x in range(0,img.size[0])]for y in range(0,img.size[1])]
return mat
def test():
mat = img2mat("dataset\\test\\1.bmp")
print(mat)
print(mat[0][0],len(mat),len(mat[0]))
if __name__ =='__main__':
test()
样例输出:
[[0, 0, 0, 0, 144, 212, 74, 17, 15, 60, 60, 62, 64, 67, 67, 68, 35, 0, 0, 0], [0, 0, 0, 0, 28, 119, 255, 101, 61, 233, 255, 255, 255, 255, 255, 255, 241, 44, 0, 0], [0, 0, 0, 0, 0, 15, 170, 92, 8, 14, 34, 31, 29, 29, 24, 74, 226, 38, 0, 0], [0, 0, 67, 220, 83, 4, 0, 0, 0, 84, 160, 0, 0, 0, 0, 52, 170, 11, 0, 0], [0, 0, 71, 255, 105, 10, 0, 0, 75, 230, 246, 124, 5, 0, 0, 49, 188, 19, 0, 0], [0, 0, 64, 255, 113, 15, 152, 216, 246, 255, 255, 255, 226, 225, 27, 46, 255, 59, 0, 0], [0, 0, 53, 255, 120, 22, 172, 249, 255, 255, 255, 255, 255, 255, 35, 33, 213, 61, 0, 0], [0, 0, 43, 255, 139, 105, 243, 254, 130, 231, 255, 139, 217, 255, 37, 35, 234, 63, 0, 0], [0, 0, 34, 247, 151, 68, 166, 248, 143, 225, 255, 159, 219, 255, 41, 37, 240, 50, 0, 0], [0, 0, 26, 240, 136, 38, 143, 246, 255, 255, 255, 255, 255, 255, 4 3, 29, 168, 0, 0, 0], [0, 0, 18, 231, 142, 44, 135, 246, 255, 255, 255, 230, 190, 98, 6, 25, 210, 49, 2, 0], [0, 0, 17, 223, 147, 49, 112, 214, 123, 226, 255, 14 7, 0, 0, 0, 28, 218, 10, 1, 0], [0, 0, 16, 212, 154, 56, 0, 0, 4, 69, 249, 149, 148, 216, 46, 18, 205, 94, 13, 0], [0, 0, 15, 200, 157, 59, 0, 11, 45, 255, 255, 242, 244, 255, 57, 3, 33, 13, 2, 0], [0, 0, 15, 196, 164, 66, 0, 66, 253, 198, 198, 198, 200, 225, 154, 87, 252, 90, 18, 0], [0, 0, 14, 184, 171, 73, 0, 8, 31, 1, 0, 0, 1, 16, 8, 13, 255, 110, 25, 0], [0, 0, 13, 175, 177, 79, 0, 0, 0, 0, 0, 0, 0, 0, 8, 37, 255, 117, 30, 0], [0, 0, 10, 134, 147, 69, 0, 0, 0, 0, 0, 0, 0, 0, 29, 127, 230, 24, 5, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 18, 2, 0, 0, 0], [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]
0 20 20
模型设计
数据集已经把⼀个车牌的三个部分都分开了,所以可以设计三个模型分别去识别这三部分。在本例中,本⼈为了简单期间,三个部分⽤了⽤⼀个CNN ⽹络结构,但是每个⽹络结构⾥⾯的具体参数是各⾃独⽴的。
CNN⽹络结构:
1. 输⼊层:20x20
智能sd卡2. 第⼀层卷积:卷积核⼤⼩:3x3,卷积核个数:32,Stride 步长:1,Same 卷积
3. 第⼆层卷积:卷积核⼤下:3x3,卷积核个数:64,Stride 步长:1,Same卷积
(两个卷积级联,效果就是5x5的卷积核,但是减少了参数个数)
4. 第⼆层池化:池化⼤⼩:2x2,max pool,Stride 步长:2
5. 第三层卷积:卷积核⼤⼩:3x3,卷积核个数:8,Stride 步长:1,Same卷积
6. 第三层池化:池化⼤⼩:2x2,max pooling,Stride :2。应该得到8个5x5的特征图。
平坦化:得到8x5x5=200维的向量
7. 第四层全连接:512个神经元,激活函数为relu。
8. 第五层全连接:34个神经元,softmax激活函数。
第五层是分类层,⼀共有34个神经元,表⽰最多有34个类别。对于province来说,只有前31类有效;对于area来说只有前26类有效;对于letter来说,这34个神经元都有效。因此在⽣成训练集的时候,需要把正确的答案标签编码为34维的one-hot
数据处理
数据处理模块,主要仿照minist数据集的写法,编写⼀个类,实现next_train_batch,next_test_batch,next_valid_batch函数。
__author__ ='jmh081701'
from dataset.map import  maps as aspectMap
import  os
from picReader import  img2mat
import  random
class data_generator:
def__init__(self,aspect='area',seperate_ratio=0.1):
'''
:param aspect: 打开什么样的训练集,[area,letter,province] 三选⼀
:param seperate_ratio: 测试集划分⽐例 ,从训练集和验证集⾥⾯随机抽取seperate_ratio作为训练集
:return:
'''
机械制图标题栏
self.val_dir  ="dataset\\val\\%s\\"% aspect
self.seperate_ratio = seperate_ratio
self.data_vector_set  =[]#保存所有的图⽚向量
self.data_label_set  =[]#保存所有的标签
self.valid_set =[]#保存验证集的下标
self.valid_batch_index =0
self.classes =0#最⼤的classes为34,这个值会在载⼊train和test后有所变化
self.data_set_cnt =0
self.load_train()
self.load_valid()
def load_train(self):
for rt,dirs,files in os.ain_dir):
self.classes =max(self.classes,len(dirs))
if len(dirs)==0:
#说明到了叶⼦⽬录,⾥⾯放着就是图⽚
label =int(rt.split('\\')[-1])
for name in files:
img_filename = os.path.join(rt,name)
vec = img2mat(img_filename)
self.data_vector_set.append(vec)
self.data_label_set.append(label)
if random.random()< self.seperate_ratio:
else:
self.data_set_cnt +=1
def load_valid(self):
for rt,dirs,files in os.walk(self.val_dir):
self.classes =max(self.classes,len(dirs))
if len(dirs)==0:
#说明到了叶⼦⽬录,⾥⾯放着就是图⽚
label =int(rt.split('\\')[-1])
for name in files:
img_filename = os.path.join(rt,name)
vec = img2mat(img_filename)
self.data_vector_set.append(vec)
self.data_label_set.append(label)
if random.random()< self.seperate_ratio:
else:
self.valid_set.append(self.data_set_cnt)
self.data_set_cnt +=1
def next_train_batch(self,batch=100):
input_x =[]
input_y =[]
for i in range(batch):
input_x.append(self.data_vector_ain_set[(ain_batch_index + i)%ain_set)]])            y =[0]* self.classes
y[self.data_label_ain_set[(ain_batch_index +i)%ain_set)]]]=1
input_y.append(y)
return  input_x,input_y
def next_valid_batch(self,batch=100):
input_x =[]
input_y =[]
for i in range(batch):
index = random.randint(0,len(self.valid_set)-1)
input_x.append(self.data_vector_set[index])
y =[0]*34
y[self.data_label_set[index]]=1
input_y.append(y)
self.valid_batch_index +=batch
self.valid_batch_index %=len(self.valid_set)
return  input_x,input_ain_epoch
def next_test_batch(self,batch=100):
input_x =[]
input_y =[]
for i in range(batch):
input_x.append(self.data_vector_st_set[(st_batch_index + i)%st_set)]])
y =[0]* self.classes
y[self.data_label_st_set[(st_batch_index +i)%(st_set))]]]=1
input_y.append(y)
return  input_x,input_y
if __name__ =='__main__':
data_gen = data_generator()
print(len(st_set))
print(_train_batch(50))
print(_valid_batch(50)[1])
print(_train_batch(30))
构建CNN模型
cnn_model.py
__author__ ='jmh081701'
import  tensorflow as tf
from BaseTool import  data_generator
batch_size =100# 每个batch的⼤⼩
learning_rate=1e-4#学习速率
aspect ="area"
data_gen = data_generator(aspect)
input_x  =tf.placeholder(dtype=tf.float32,shape=[None,20,20],name='input_x')
input_y  =tf.placeholder(dtype=tf.float32,shape=[None,34],name='input_y')
with tf.name_scope('conv1'):
W_C1 = tf.uncated_normal(shape=[3,3,1,32],stddev=0.1))
b_C1 = tf.stant(0.1,tf.float32,shape=[32]))
shape(input_x,[-1,20,20,1])
featureMap_C1 = v2d(X,W_C1,strides=[1,1,1,1],padding='SAME')+ b_C1 )
with tf.name_scope('conv2'):
W_C2 = tf.uncated_normal(shape=[3,3,32,64],stddev=0.1))
b_C2 = tf.stant(0.1,tf.float32,shape=[64]))
featureMap_C2 = v2d(featureMap_C1,W_C2,strides=[1,1,1,1],padding='SAME')+ b_C2)
with tf.name_scope('pooling2'):
featureMap_S2 = tf.nn.max_pool(featureMap_C2,ksize=[1,2,2,1],strides=[1,2,2,1],padding='VALID')
with tf.name_scope('conv3'):
无电沉镍
W_C3 = tf.uncated_normal(shape=[3,3,64,8],stddev=0.1))
b_C3 = tf.stant(0.1,shape=[8],dtype=tf.float32))
featureMap_C3 = v2d(featureMap_S2,filter=W_C3,strides=[1,1,1,1],padding='SAME')+ b_C3)
with tf.name_scope('pooling3'):
featureMap_S3 = tf.nn.max_pool(featureMap_C3,[1,2,2,1],[1,2,2,1],padding='VALID')
with tf.name_scope('fulnet'):
featureMap_flatten = tf.reshape(featureMap_S3,[-1,5*5*8])
优糖米
W_F4 = tf.uncated_normal(shape=[5*5*8,512],stddev=0.1))
b_F4 = tf.stant(0.1,shape=[512],dtype=tf.float32))
out_F4 = lu(tf.matmul(featureMap_flatten,W_F4)+ b_F4)
#out_F4 =tf.nn.dropout(out_F4,keep_prob=0.5)
with tf.name_scope('output'):
W_OUTPUT = tf.uncated_normal(shape=[512,34],stddev=0.1))
b_OUTPUT = tf.stant(0.1,shape=[34],dtype=tf.float32))
logits = tf.matmul(out_F4,W_OUTPUT)+b_OUTPUT
loss = tf.reduce_softmax_cross_entropy_with_logits(labels=input_y,logits=logits)) train_op = tf.train.AdamOptimizer(learning_rate).minimize(loss)
predictY = tf.nn.softmax(logits)
y_pred=tf.arg_max(predictY,1)
bool_pred=tf.equal(tf.arg_max(input_y,1),y_pred)
right_duce__float(bool_pred))
saver = tf.train.Saver()
def load_model(sess,dir,modelname):
_checkpoint_state(dir)
if ckpt del_checkpoint_path:
print("*"*30)
print("load ")
print("*"*30)
def save_model(sess,dir,modelname):
saver.save(sess,dir+modelname)
dir= r".//"
modelname = aspect
with tf.Session()as sess:
sess.run(tf.initialize_all_variables())
step =1
display_interval=200
max_epoch =50
epoch =0
acc =0
load_model(sess,dir=dir,modelname=modelname)
while True:
if step % display_interval ==0:
image_batch,label_batch,epoch = _valid_batch(batch_size)
acc = sess.run(right_rate,feed_dict={input_x:image_batch,input_y:label_batch}) print({'!'*30+str(epoch)+":"+str(step):acc})
image_batch,label_batch,epoch = _train_batch(batch_size)
sess.run([loss,train_op],{input_x:image_batch,input_y:label_batch})
if(epoch> max_epoch):
break
step +=1
while True:
test_img,test_lab,test_epoch = _test_batch(batch_size)
test_acc = sess.run(right_rate,{input_x:test_img,input_y:test_lab})
acc = test_acc *0.8+ acc *0.2#指数滑动平均
if(test_epoch!=epoch):
糖尿病检测仪print({" acc:":acc})
break
save_model(sess,dir,modelname)
训练结果:
area:

本文发布于:2024-09-23 01:38:50,感谢您对本站的认可!

本文链接:https://www.17tex.com/tex/2/254347.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:车牌   训练   卷积   识别   灰度   数据   保存   任务
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议