首页 PaddleCV 帖子详情
【深度学习】用Paddle进行车牌识别二
收藏
快速回复
PaddleCV 问答目标检测目标识别 4580 1
【深度学习】用Paddle进行车牌识别二
收藏
快速回复
PaddleCV 问答目标检测目标识别 4580 1

上节我们讲了第一部分,如何用生成简易的车牌,这节课中我们会用PaddlePaddle来识别生成的车牌。


 数据读取

  在上一节生成车牌时,我们可以分别生成训练数据和测试数据,方法如下(完整代码在这里):

# 将生成的车牌图片写入文件夹,对应的label写入label.txt
def genBatch(self, batchSize,pos,charRange, outputPath,size):
    if (not os.path.exists(outputPath)):
        os.mkdir(outputPath)
    outfile = open('label.txt','w')
    for i in xrange(batchSize):
            plateStr,plate = G.genPlateString(-1,-1)
            print plateStr,plate
            img =  G.generate(plateStr);
            img = cv2.resize(img,size);
            cv2.imwrite(outputPath + "/" + str(i).zfill(2) + ".jpg", img);
            outfile.write(str(plate)+"\n")

  生成好数据后,我们写一个reader来读取数据 ( reador.py )

1 def reader_creator(data,label):
2     def reader():
3         for i in xrange(len(data)):
4             yield data[i,:],int(label[i])
5     return reader

灌入模型时,我们需要调用paddle.batch函数,将数据shuffle后批量灌入模型中:

# 读取训练数据
train_reader = paddle.batch(paddle.reader.shuffle(
                reador.reader_creator(X_train,Y_train),buf_size=200),
                batch_size=16)

# 读取验证数据
 val_reader = paddle.batch(paddle.reader.shuffle(
                reador.reader_creator(X_val,Y_val),buf_size=200),
                batch_size=16)
       trainer.train(reader=train_reader,num_passes=20,event_handler=event_handler)


 构建网络模型

  因为我们训练的是端到端的车牌识别,所以一开始构建了两个卷积-池化层训练,训练完后同步训练7个全连接层,分别对应车牌的7位字符,最后将其拼接起来,与原始的label计算Softmax值,预测训练结果。 

class NeuralNetwork(object):
    def __init__(self,X_train,Y_train,X_val,Y_val):
        paddle.init(use_gpu = with_gpu,trainer_count=1)

        self.X_train = X_train
        self.Y_train = Y_train
        self.X_val = X_val
        self.Y_val = Y_val

    
    def get_network_cnn(self):
        
        x = paddle.layer.data(name='x', type=paddle.data_type.dense_vector(self.data))
        y = paddle.layer.data(name='y', type=paddle.data_type.integer_value(self.label))
        conv_pool_1 = paddle.networks.simple_img_conv_pool(
            input=x,
            filter_size=12,
            num_filters=50,
            num_channel=1,
            pool_size=2,
            pool_stride=2,
            act=paddle.activation.Relu())
        drop_1 = paddle.layer.dropout(input=conv_pool_1, dropout_rate=0.5)
        conv_pool_2 = paddle.networks.simple_img_conv_pool(
            input=drop_1,
            filter_size=5,
            num_filters=50,
            num_channel=20,
            pool_size=2,
            pool_stride=2,
            act=paddle.activation.Relu())
        drop_2 = paddle.layer.dropout(input=conv_pool_2, dropout_rate=0.5)

        fc = paddle.layer.fc(input = drop_2, size = 120)
        fc1_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
        fc1 = paddle.layer.fc(input = fc1_drop,size = 65,act = paddle.activation.Linear())
        
        fc2_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
        fc2 = paddle.layer.fc(input = fc2_drop,size = 65,act = paddle.activation.Linear())
        
        fc3_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
        fc3 = paddle.layer.fc(input = fc3_drop,size = 65,act = paddle.activation.Linear())
        
        fc4_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
        fc4 = paddle.layer.fc(input = fc4_drop,size = 65,act = paddle.activation.Linear())
        
        fc5_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
        fc5 = paddle.layer.fc(input = fc5_drop,size = 65,act = paddle.activation.Linear())
        
        fc6_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)
        fc6 = paddle.layer.fc(input = fc6_drop,size = 65,act = paddle.activation.Linear())

        fc7_drop = paddle.layer.dropout(input = fc,dropout_rate = 0.5)    
        fc7 = paddle.layer.fc(input = fc7_drop,size = 65,act = paddle.activation.Linear())
        
        fc_concat = paddle.layer.concact(input = [fc21, fc22, fc23, fc24,fc25,fc26,fc27], axis = 0)
        predict = paddle.layer.classification_cost(input = fc_concat,label = y,act=paddle.activation.Softmax())
        return predict

    # 定义训练器
    def get_trainer(self):

        cost = self.get_network()

        #获取参数
        parameters = paddle.parameters.create(cost)


        optimizer = paddle.optimizer.Momentum(
                                momentum=0.9,
                                regularization=paddle.optimizer.L2Regularization(rate=0.0002 * 128),
                                learning_rate=0.001,
                                learning_rate_schedule = "pass_manual")
    

        # 创建训练器
        trainer = paddle.trainer.SGD(
                cost=cost, parameters=parameters, update_equation=optimizer)
        return trainer


    # 开始训练
    def start_trainer(self,X_train,Y_train,X_val,Y_val):
        trainer = self.get_trainer()

        result_lists = []
        def event_handler(event):
            if isinstance(event, paddle.event.EndIteration):
                if event.batch_id % 10 == 0:
                    print "\nPass %d, Batch %d, Cost %f, %s" % (
                        event.pass_id, event.batch_id, event.cost, event.metrics)
            if isinstance(event, paddle.event.EndPass):
                    # 保存训练好的参数
                with open('params_pass_%d.tar' % event.pass_id, 'w') as f:
                    parameters.to_tar(f)
                # feeding = ['x','y']
                result = trainer.test(
                        reader=val_reader)
                            # feeding=feeding)
                print "\nTest with Pass %d, %s" % (event.pass_id, result.metrics)

                result_lists.append((event.pass_id, result.cost,
                        result.metrics['classification_error_evaluator']))

        # 开始训练
        train_reader = paddle.batch(paddle.reader.shuffle(
                reador.reader_creator(X_train,Y_train),buf_size=200),
                batch_size=16)

        val_reader = paddle.batch(paddle.reader.shuffle(
                reador.reader_creator(X_val,Y_val),buf_size=200),
                batch_size=16)
        # val_reader = paddle.reader(reador.reader_creator(X_val,Y_val),batch_size=16)

        trainer.train(reader=train_reader,num_passes=20,event_handler=event_handler)

 

输出结果

  上一步训练完以后,保存训练完的模型,然后写一个test.py进行预测,需要注意的是,在预测时,构建的网络结构得和训练的网络结构相同。

 

#批量预测测试图片准确率
python test.py /Users/shelter/test

##输出结果示例
output:
预测车牌号码为:津 K 4 2 R M Y
输入图片数量:100
输入图片行准确率:0.72
输入图片列准确率:0.86

  如果是一次性只预测一张的话,在终端里会显示原始的图片与预测的值,如果是批量预测的话,会打印出预测的总准确率,包括行与列的准确率。

 

 


总结

   车牌识别的方法有很多,商业化落地的方法也很成熟,传统的方法需要对图片灰度化,字符进行切分等,需要很多数据预处理的过程,端到端的方法可以直接将原始的图片灌进去进行训练,最后出来预测的车牌字符的结果,这个方法在构建了两层卷积-池化网络结构后,并行训练了7个全连接层来进行车牌的字符识别,可以实现端到端的识别。但是在实际训练过程中,仍然有一些问题,譬如前几个训练的全连接层的准确率要比最后一两个的准确率高,大家可以分别打印出每一个全连接层的训练结果准确率对比一下,可能是由于训练还没有收敛导致的,也可能有其他原因,如果在做的过程中发现有什么问题,或者有更好的方法,欢迎留言~

 

 

参考文献:

1.我的github:https://github.com/huxiaoman7/mxnet-cnn-plate-recognition

1
收藏
回复
全部评论(1)
时间顺序
lara吕雪莹
#2 回复于2021-06

点赞

0
回复
需求/bug反馈?一键提issue告诉我们
发现bug?如果您知道修复办法,欢迎提pr直接参与建设飞桨~
在@后输入用户全名并按空格结束,可艾特全站任一用户