记录学习,TensorFlow车牌识别

感谢这位作者,以下记录是来自于https://blog.csdn.net/shadown1ght/article/details/78571187的,我看到比较好,就转记录到自己的博客了,如果有侵权,立马删掉

车牌数据集下载地址(约4000张图片):https://pan.baidu.com/s/1RyoMbHtLUlsMDsvLBCLZ2w

省份简称训练+识别代码(保存文件名为train-license-province.py)(拷贝代码请务必注意python文本缩进,只要有一处缩进错误,就无法得到正确结果,或者出现异常):

[python]  view plain  copy
  1. #!/usr/bin/python3.5  
  2. # -*- coding: utf-8 -*-    
  3.   
  4. import sys  
  5. import os  
  6. import time  
  7. import random  
  8.   
  9. import numpy as np  
  10. import tensorflow as tf  
  11.   
  12. from PIL import Image  
  13.   
  14.   
  15. SIZE = 1280  
  16. WIDTH = 32  
  17. HEIGHT = 40  
  18. NUM_CLASSES = 6  
  19. iterations = 300  
  20.   
  21. SAVER_DIR = "train-saver/province/"  
  22.   
  23. PROVINCES = ("京","闽","粤","苏","沪","浙")  
  24. nProvinceIndex = 0  
  25.   
  26. time_begin = time.time()  
  27.   
  28.   
  29. # 定义输入节点,对应于图片像素值矩阵集合和图片标签(即所代表的数字)  
  30. x = tf.placeholder(tf.float32, shape=[None, SIZE])  
  31. y_ = tf.placeholder(tf.float32, shape=[None, NUM_CLASSES])  
  32.   
  33. x_image = tf.reshape(x, [-1, WIDTH, HEIGHT, 1])  
  34.   
  35.   
  36. # 定义卷积函数  
  37. def conv_layer(inputs, W, b, conv_strides, kernel_size, pool_strides, padding):  
  38.     L1_conv = tf.nn.conv2d(inputs, W, strides=conv_strides, padding=padding)  
  39.     L1_relu = tf.nn.relu(L1_conv + b)  
  40.     return tf.nn.max_pool(L1_relu, ksize=kernel_size, strides=pool_strides, padding='SAME')  
  41.   
  42. # 定义全连接层函数  
  43. def full_connect(inputs, W, b):  
  44.     return tf.nn.relu(tf.matmul(inputs, W) + b)  
  45.   
  46.   
  47. if __name__ =='__main__' and sys.argv[1]=='train':  
  48.     # 第一次遍历图片目录是为了获取图片总数  
  49.     input_count = 0  
  50.     for i in range(0,NUM_CLASSES):  
  51.         dir = './train_images/training-set/chinese-characters/%s/' % i           # 这里可以改成你自己的图片目录,i为分类标签  
  52.         for rt, dirs, files in os.walk(dir):  
  53.             for filename in files:  
  54.                 input_count += 1  
  55.   
  56.     # 定义对应维数和各维长度的数组  
  57.     input_images = np.array([[0]*SIZE for i in range(input_count)])  
  58.     input_labels = np.array([[0]*NUM_CLASSES for i in range(input_count)])  
  59.   
  60.     # 第二次遍历图片目录是为了生成图片数据和标签  
  61.     index = 0  
  62.     for i in range(0,NUM_CLASSES):  
  63.         dir = './train_images/training-set/chinese-characters/%s/' % i          # 这里可以改成你自己的图片目录,i为分类标签  
  64.         for rt, dirs, files in os.walk(dir):  
  65.             for filename in files:  
  66.                 filename = dir + filename  
  67.                 img = Image.open(filename)  
  68.                 width = img.size[0]  
  69.                 height = img.size[1]  
  70.                 for h in range(0, height):  
  71.                     for w in range(0, width):  
  72.                         # 通过这样的处理,使数字的线条变细,有利于提高识别准确率  
  73.                         if img.getpixel((w, h)) > 230:  
  74.                             input_images[index][w+h*width] = 0  
  75.                         else:  
  76.                             input_images[index][w+h*width] = 1  
  77.                 input_labels[index][i] = 1  
  78.                 index += 1  
  79.   
  80.     # 第一次遍历图片目录是为了获取图片总数  
  81.     val_count = 0  
  82.     for i in range(0,NUM_CLASSES):  
  83.         dir = './train_images/validation-set/chinese-characters/%s/' % i           # 这里可以改成你自己的图片目录,i为分类标签  
  84.         for rt, dirs, files in os.walk(dir):  
  85.             for filename in files:  
  86.                 val_count += 1  
  87.   
  88.     # 定义对应维数和各维长度的数组  
  89.     val_images = np.array([[0]*SIZE for i in range(val_count)])  
  90.     val_labels = np.array([[0]*NUM_CLASSES for i in range(val_count)])  
  91.   
  92.     # 第二次遍历图片目录是为了生成图片数据和标签  
  93.     index = 0  
  94.     for i in range(0,NUM_CLASSES):  
  95.         dir = './train_images/validation-set/chinese-characters/%s/' % i          # 这里可以改成你自己的图片目录,i为分类标签  
  96.         for rt, dirs, files in os.walk(dir):  
  97.             for filename in files:  
  98.                 filename = dir + filename  
  99.                 img = Image.open(filename)  
  100.                 width = img.size[0]  
  101.                 height = img.size[1]  
  102.                 for h in range(0, height):  
  103.                     for w in range(0, width):  
  104.                         # 通过这样的处理,使数字的线条变细,有利于提高识别准确率  
  105.                         if img.getpixel((w, h)) > 230:  
  106.                             val_images[index][w+h*width] = 0  
  107.                         else:  
  108.                             val_images[index][w+h*width] = 1  
  109.                 val_labels[index][i] = 1  
  110.                 index += 1  
  111.       
  112.     with tf.Session() as sess:  
  113.         # 第一个卷积层  
  114.         W_conv1 = tf.Variable(tf.truncated_normal([88116], stddev=0.1), name="W_conv1")  
  115.         b_conv1 = tf.Variable(tf.constant(0.1, shape=[16]), name="b_conv1")  
  116.         conv_strides = [1111]  
  117.         kernel_size = [1221]  
  118.         pool_strides = [1221]  
  119.         L1_pool = conv_layer(x_image, W_conv1, b_conv1, conv_strides, kernel_size, pool_strides, padding='SAME')  
  120.   
  121.         # 第二个卷积层  
  122.         W_conv2 = tf.Variable(tf.truncated_normal([551632], stddev=0.1), name="W_conv2")  
  123.         b_conv2 = tf.Variable(tf.constant(0.1, shape=[32]), name="b_conv2")  
  124.         conv_strides = [1111]  
  125.         kernel_size = [1111]  
  126.         pool_strides = [1111]  
  127.         L2_pool = conv_layer(L1_pool, W_conv2, b_conv2, conv_strides, kernel_size, pool_strides, padding='SAME')  
  128.   
  129.   
  130.         # 全连接层  
  131.         W_fc1 = tf.Variable(tf.truncated_normal([16 * 20 * 32512], stddev=0.1), name="W_fc1")  
  132.         b_fc1 = tf.Variable(tf.constant(0.1, shape=[512]), name="b_fc1")  
  133.         h_pool2_flat = tf.reshape(L2_pool, [-116 * 20*32])  
  134.         h_fc1 = full_connect(h_pool2_flat, W_fc1, b_fc1)  
  135.   
  136.   
  137.         # dropout  
  138.         keep_prob = tf.placeholder(tf.float32)  
  139.   
  140.         h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)  
  141.   
  142.   
  143.         # readout层  
  144.         W_fc2 = tf.Variable(tf.truncated_normal([512, NUM_CLASSES], stddev=0.1), name="W_fc2")  
  145.         b_fc2 = tf.Variable(tf.constant(0.1, shape=[NUM_CLASSES]), name="b_fc2")  
  146.   
  147.         # 定义优化器和训练op  
  148.         y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2  
  149.         cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))  
  150.         train_step = tf.train.AdamOptimizer((1e-4)).minimize(cross_entropy)  
  151.   
  152.         correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))  
  153.         accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))  
  154.   
  155.         # 初始化saver  
  156.         saver = tf.train.Saver()  
  157.   
  158.         sess.run(tf.global_variables_initializer())  
  159.   
  160.         time_elapsed = time.time() - time_begin  
  161.         print("读取图片文件耗费时间:%d秒" % time_elapsed)  
  162.         time_begin = time.time()  
  163.   
  164.         print ("一共读取了 %s 个训练图像, %s 个标签" % (input_count, input_count))  
  165.   
  166.         # 设置每次训练op的输入个数和迭代次数,这里为了支持任意图片总数,定义了一个余数remainder,譬如,如果每次训练op的输入个数为60,图片总数为150张,则前面两次各输入60张,最后一次输入30张(余数30)  
  167.         batch_size = 60  
  168.         iterations = iterations  
  169.         batches_count = int(input_count / batch_size)  
  170.         remainder = input_count % batch_size  
  171.         print ("训练数据集分成 %s 批, 前面每批 %s 个数据,最后一批 %s 个数据" % (batches_count+1, batch_size, remainder))  
  172.   
  173.         # 执行训练迭代  
  174.         for it in range(iterations):  
  175.             # 这里的关键是要把输入数组转为np.array  
  176.             for n in range(batches_count):  
  177.                 train_step.run(feed_dict={x: input_images[n*batch_size:(n+1)*batch_size], y_: input_labels[n*batch_size:(n+1)*batch_size], keep_prob: 0.5})  
  178.             if remainder > 0:  
  179.                 start_index = batches_count * batch_size;  
  180.                 train_step.run(feed_dict={x: input_images[start_index:input_count-1], y_: input_labels[start_index:input_count-1], keep_prob: 0.5})  
  181.   
  182.             # 每完成五次迭代,判断准确度是否已达到100%,达到则退出迭代循环  
  183.             iterate_accuracy = 0  
  184.             if it%5 == 0:  
  185.                 iterate_accuracy = accuracy.eval(feed_dict={x: val_images, y_: val_labels, keep_prob: 1.0})  
  186.                 print ('第 %d 次训练迭代: 准确率 %0.5f%%' % (it, iterate_accuracy*100))  
  187.                 if iterate_accuracy >= 0.9999 and it >= 150:  
  188.                     break;  
  189.   
  190.         print ('完成训练!')  
  191.         time_elapsed = time.time() - time_begin  
  192.         print ("训练耗费时间:%d秒" % time_elapsed)  
  193.         time_begin = time.time()  
  194.   
  195.         # 保存训练结果  
  196.         if not os.path.exists(SAVER_DIR):  
  197.             print ('不存在训练数据保存目录,现在创建保存目录')  
  198.             os.makedirs(SAVER_DIR)  
  199.         saver_path = saver.save(sess, "%smodel.ckpt"%(SAVER_DIR))  
  200.   
  201.   
  202.   
  203. if __name__ =='__main__' and sys.argv[1]=='predict':  
  204.     saver = tf.train.import_meta_graph("%smodel.ckpt.meta"%(SAVER_DIR))  
  205.     with tf.Session() as sess:  
  206.         model_file=tf.train.latest_checkpoint(SAVER_DIR)  
  207.         saver.restore(sess, model_file)  
  208.   
  209.         # 第一个卷积层  
  210.         W_conv1 = sess.graph.get_tensor_by_name("W_conv1:0")  
  211.         b_conv1 = sess.graph.get_tensor_by_name("b_conv1:0")  
  212.         conv_strides = [1111]  
  213.         kernel_size = [1221]  
  214.         pool_strides = [1221]  
  215.         L1_pool = conv_layer(x_image, W_conv1, b_conv1, conv_strides, kernel_size, pool_strides, padding='SAME')  
  216.   
  217.         # 第二个卷积层  
  218.         W_conv2 = sess.graph.get_tensor_by_name("W_conv2:0")  
  219.         b_conv2 = sess.graph.get_tensor_by_name("b_conv2:0")  
  220.         conv_strides = [1111]  
  221.         kernel_size = [1111]  
  222.         pool_strides = [1111]  
  223.         L2_pool = conv_layer(L1_pool, W_conv2, b_conv2, conv_strides, kernel_size, pool_strides, padding='SAME')  
  224.   
  225.   
  226.         # 全连接层  
  227.         W_fc1 = sess.graph.get_tensor_by_name("W_fc1:0")  
  228.         b_fc1 = sess.graph.get_tensor_by_name("b_fc1:0")  
  229.         h_pool2_flat = tf.reshape(L2_pool, [-116 * 20*32])  
  230.         h_fc1 = full_connect(h_pool2_flat, W_fc1, b_fc1)  
  231.   
  232.   
  233.         # dropout  
  234.         keep_prob = tf.placeholder(tf.float32)  
  235.   
  236.         h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)  
  237.   
  238.   
  239.         # readout层  
  240.         W_fc2 = sess.graph.get_tensor_by_name("W_fc2:0")  
  241.         b_fc2 = sess.graph.get_tensor_by_name("b_fc2:0")  
  242.   
  243.         # 定义优化器和训练op  
  244.         conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)  
  245.   
  246.         for n in range(1,2):  
  247.             path = "test_images/%s.bmp" % (n)  
  248.             img = Image.open(path)  
  249.             width = img.size[0]  
  250.             height = img.size[1]  
  251.   
  252.             img_data = [[0]*SIZE for i in range(1)]  
  253.             for h in range(0, height):  
  254.                 for w in range(0, width):  
  255.                     if img.getpixel((w, h)) < 190:  
  256.                         img_data[0][w+h*width] = 1  
  257.                     else:  
  258.                         img_data[0][w+h*width] = 0  
  259.               
  260.             result = sess.run(conv, feed_dict = {x: np.array(img_data), keep_prob: 1.0})  
  261.             max1 = 0  
  262.             max2 = 0  
  263.             max3 = 0  
  264.             max1_index = 0  
  265.             max2_index = 0  
  266.             max3_index = 0  
  267.             for j in range(NUM_CLASSES):  
  268.                 if result[0][j] > max1:  
  269.                     max1 = result[0][j]  
  270.                     max1_index = j  
  271.                     continue  
  272.                 if (result[0][j]>max2) and (result[0][j]<=max1):  
  273.                     max2 = result[0][j]  
  274.                     max2_index = j  
  275.                     continue  
  276.                 if (result[0][j]>max3) and (result[0][j]<=max2):  
  277.                     max3 = result[0][j]  
  278.                     max3_index = j  
  279.                     continue  
  280.               
  281.             nProvinceIndex = max1_index  
  282.             print ("概率:  [%s %0.2f%%]    [%s %0.2f%%]    [%s %0.2f%%]" % (PROVINCES[max1_index],max1*100, PROVINCES[max2_index],max2*100, PROVINCES[max3_index],max3*100))  
  283.               
  284.         print ("省份简称是: %s" % PROVINCES[nProvinceIndex])  

城市代号训练+识别代码(保存文件名为train-license-letters.py):

[python]  view plain  copy
  1. #!/usr/bin/python3.5  
  2. # -*- coding: utf-8 -*-    
  3.   
  4. import sys  
  5. import os  
  6. import time  
  7. import random  
  8.   
  9. import numpy as np  
  10. import tensorflow as tf  
  11.   
  12. from PIL import Image  
  13.   
  14.   
  15. SIZE = 1280  
  16. WIDTH = 32  
  17. HEIGHT = 40  
  18. NUM_CLASSES = 26  
  19. iterations = 500  
  20.   
  21. SAVER_DIR = "train-saver/letters/"  
  22.   
  23. LETTERS_DIGITS = ("A","B","C","D","E","F","G","H","J","K","L","M","N","P","Q","R","S","T","U","V","W","X","Y","Z","I","O")  
  24. license_num = ""  
  25.   
  26. time_begin = time.time()  
  27.   
  28.   
  29. # 定义输入节点,对应于图片像素值矩阵集合和图片标签(即所代表的数字)  
  30. x = tf.placeholder(tf.float32, shape=[None, SIZE])  
  31. y_ = tf.placeholder(tf.float32, shape=[None, NUM_CLASSES])  
  32.   
  33. x_image = tf.reshape(x, [-1, WIDTH, HEIGHT, 1])  
  34.   
  35.   
  36. # 定义卷积函数  
  37. def conv_layer(inputs, W, b, conv_strides, kernel_size, pool_strides, padding):  
  38.     L1_conv = tf.nn.conv2d(inputs, W, strides=conv_strides, padding=padding)  
  39.     L1_relu = tf.nn.relu(L1_conv + b)  
  40.     return tf.nn.max_pool(L1_relu, ksize=kernel_size, strides=pool_strides, padding='SAME')  
  41.   
  42. # 定义全连接层函数  
  43. def full_connect(inputs, W, b):  
  44.     return tf.nn.relu(tf.matmul(inputs, W) + b)  
  45.   
  46.   
  47. if __name__ =='__main__' and sys.argv[1]=='train':  
  48.     # 第一次遍历图片目录是为了获取图片总数  
  49.     input_count = 0  
  50.     for i in range(0+10,NUM_CLASSES+10):  
  51.         dir = './train_images/training-set/letters/%s/' % i           # 这里可以改成你自己的图片目录,i为分类标签  
  52.         for rt, dirs, files in os.walk(dir):  
  53.             for filename in files:  
  54.                 input_count += 1  
  55.   
  56.     # 定义对应维数和各维长度的数组  
  57.     input_images = np.array([[0]*SIZE for i in range(input_count)])  
  58.     input_labels = np.array([[0]*NUM_CLASSES for i in range(input_count)])  
  59.   
  60.     # 第二次遍历图片目录是为了生成图片数据和标签  
  61.     index = 0  
  62.     for i in range(0+10,NUM_CLASSES+10):  
  63.         dir = './train_images/training-set/letters/%s/' % i          # 这里可以改成你自己的图片目录,i为分类标签  
  64.         for rt, dirs, files in os.walk(dir):  
  65.             for filename in files:  
  66.                 filename = dir + filename  
  67.                 img = Image.open(filename)  
  68.                 width = img.size[0]  
  69.                 height = img.size[1]  
  70.                 for h in range(0, height):  
  71.                     for w in range(0, width):  
  72.                         # 通过这样的处理,使数字的线条变细,有利于提高识别准确率  
  73.                         if img.getpixel((w, h)) > 230:  
  74.                             input_images[index][w+h*width] = 0  
  75.                         else:  
  76.                             input_images[index][w+h*width] = 1  
  77.                 #print ("i=%d, index=%d" % (i, index))  
  78.                 input_labels[index][i-10] = 1  
  79.                 index += 1  
  80.   
  81.     # 第一次遍历图片目录是为了获取图片总数  
  82.     val_count = 0  
  83.     for i in range(0+10,NUM_CLASSES+10):  
  84.         dir = './train_images/validation-set/%s/' % i           # 这里可以改成你自己的图片目录,i为分类标签  
  85.         for rt, dirs, files in os.walk(dir):  
  86.             for filename in files:  
  87.                 val_count += 1  
  88.   
  89.     # 定义对应维数和各维长度的数组  
  90.     val_images = np.array([[0]*SIZE for i in range(val_count)])  
  91.     val_labels = np.array([[0]*NUM_CLASSES for i in range(val_count)])  
  92.   
  93.     # 第二次遍历图片目录是为了生成图片数据和标签  
  94.     index = 0  
  95.     for i in range(0+10,NUM_CLASSES+10):  
  96.         dir = './train_images/validation-set/%s/' % i          # 这里可以改成你自己的图片目录,i为分类标签  
  97.         for rt, dirs, files in os.walk(dir):  
  98.             for filename in files:  
  99.                 filename = dir + filename  
  100.                 img = Image.open(filename)  
  101.                 width = img.size[0]  
  102.                 height = img.size[1]  
  103.                 for h in range(0, height):  
  104.                     for w in range(0, width):  
  105.                         # 通过这样的处理,使数字的线条变细,有利于提高识别准确率  
  106.                         if img.getpixel((w, h)) > 230:  
  107.                             val_images[index][w+h*width] = 0  
  108.                         else:  
  109.                             val_images[index][w+h*width] = 1  
  110.                 val_labels[index][i-10] = 1  
  111.                 index += 1  
  112.       
  113.     with tf.Session() as sess:  
  114.         # 第一个卷积层  
  115.         W_conv1 = tf.Variable(tf.truncated_normal([88116], stddev=0.1), name="W_conv1")  
  116.         b_conv1 = tf.Variable(tf.constant(0.1, shape=[16]), name="b_conv1")  
  117.         conv_strides = [1111]  
  118.         kernel_size = [1221]  
  119.         pool_strides = [1221]  
  120.         L1_pool = conv_layer(x_image, W_conv1, b_conv1, conv_strides, kernel_size, pool_strides, padding='SAME')  
  121.   
  122.         # 第二个卷积层  
  123.         W_conv2 = tf.Variable(tf.truncated_normal([551632], stddev=0.1), name="W_conv2")  
  124.         b_conv2 = tf.Variable(tf.constant(0.1, shape=[32]), name="b_conv2")  
  125.         conv_strides = [1111]  
  126.         kernel_size = [1111]  
  127.         pool_strides = [1111]  
  128.         L2_pool = conv_layer(L1_pool, W_conv2, b_conv2, conv_strides, kernel_size, pool_strides, padding='SAME')  
  129.   
  130.   
  131.         # 全连接层  
  132.         W_fc1 = tf.Variable(tf.truncated_normal([16 * 20 * 32512], stddev=0.1), name="W_fc1")  
  133.         b_fc1 = tf.Variable(tf.constant(0.1, shape=[512]), name="b_fc1")  
  134.         h_pool2_flat = tf.reshape(L2_pool, [-116 * 20*32])  
  135.         h_fc1 = full_connect(h_pool2_flat, W_fc1, b_fc1)  
  136.   
  137.   
  138.         # dropout  
  139.         keep_prob = tf.placeholder(tf.float32)  
  140.   
  141.         h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)  
  142.   
  143.   
  144.         # readout层  
  145.         W_fc2 = tf.Variable(tf.truncated_normal([512, NUM_CLASSES], stddev=0.1), name="W_fc2")  
  146.         b_fc2 = tf.Variable(tf.constant(0.1, shape=[NUM_CLASSES]), name="b_fc2")  
  147.   
  148.         # 定义优化器和训练op  
  149.         y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2  
  150.         cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))  
  151.         train_step = tf.train.AdamOptimizer((1e-4)).minimize(cross_entropy)  
  152.   
  153.         correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))  
  154.         accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))  
  155.   
  156.         sess.run(tf.global_variables_initializer())  
  157.   
  158.         time_elapsed = time.time() - time_begin  
  159.         print("读取图片文件耗费时间:%d秒" % time_elapsed)  
  160.         time_begin = time.time()  
  161.   
  162.         print ("一共读取了 %s 个训练图像, %s 个标签" % (input_count, input_count))  
  163.   
  164.         # 设置每次训练op的输入个数和迭代次数,这里为了支持任意图片总数,定义了一个余数remainder,譬如,如果每次训练op的输入个数为60,图片总数为150张,则前面两次各输入60张,最后一次输入30张(余数30)  
  165.         batch_size = 60  
  166.         iterations = iterations  
  167.         batches_count = int(input_count / batch_size)  
  168.         remainder = input_count % batch_size  
  169.         print ("训练数据集分成 %s 批, 前面每批 %s 个数据,最后一批 %s 个数据" % (batches_count+1, batch_size, remainder))  
  170.   
  171.         # 执行训练迭代  
  172.         for it in range(iterations):  
  173.             # 这里的关键是要把输入数组转为np.array  
  174.             for n in range(batches_count):  
  175.                 train_step.run(feed_dict={x: input_images[n*batch_size:(n+1)*batch_size], y_: input_labels[n*batch_size:(n+1)*batch_size], keep_prob: 0.5})  
  176.             if remainder > 0:  
  177.                 start_index = batches_count * batch_size;  
  178.                 train_step.run(feed_dict={x: input_images[start_index:input_count-1], y_: input_labels[start_index:input_count-1], keep_prob: 0.5})  
  179.   
  180.             # 每完成五次迭代,判断准确度是否已达到100%,达到则退出迭代循环  
  181.             iterate_accuracy = 0  
  182.             if it%5 == 0:  
  183.                 iterate_accuracy = accuracy.eval(feed_dict={x: val_images, y_: val_labels, keep_prob: 1.0})  
  184.                 print ('第 %d 次训练迭代: 准确率 %0.5f%%' % (it, iterate_accuracy*100))  
  185.                 if iterate_accuracy >= 0.9999 and it >= iterations:  
  186.                     break;  
  187.   
  188.         print ('完成训练!')  
  189.         time_elapsed = time.time() - time_begin  
  190.         print ("训练耗费时间:%d秒" % time_elapsed)  
  191.         time_begin = time.time()  
  192.   
  193.         # 保存训练结果  
  194.         if not os.path.exists(SAVER_DIR):  
  195.             print ('不存在训练数据保存目录,现在创建保存目录')  
  196.             os.makedirs(SAVER_DIR)  
  197.         # 初始化saver  
  198.         saver = tf.train.Saver()              
  199.         saver_path = saver.save(sess, "%smodel.ckpt"%(SAVER_DIR))  
  200.   
  201.   
  202.   
  203. if __name__ =='__main__' and sys.argv[1]=='predict':  
  204.     saver = tf.train.import_meta_graph("%smodel.ckpt.meta"%(SAVER_DIR))  
  205.     with tf.Session() as sess:  
  206.         model_file=tf.train.latest_checkpoint(SAVER_DIR)  
  207.         saver.restore(sess, model_file)  
  208.   
  209.         # 第一个卷积层  
  210.         W_conv1 = sess.graph.get_tensor_by_name("W_conv1:0")  
  211.         b_conv1 = sess.graph.get_tensor_by_name("b_conv1:0")  
  212.         conv_strides = [1111]  
  213.         kernel_size = [1221]  
  214.         pool_strides = [1221]  
  215.         L1_pool = conv_layer(x_image, W_conv1, b_conv1, conv_strides, kernel_size, pool_strides, padding='SAME')  
  216.   
  217.         # 第二个卷积层  
  218.         W_conv2 = sess.graph.get_tensor_by_name("W_conv2:0")  
  219.         b_conv2 = sess.graph.get_tensor_by_name("b_conv2:0")  
  220.         conv_strides = [1111]  
  221.         kernel_size = [1111]  
  222.         pool_strides = [1111]  
  223.         L2_pool = conv_layer(L1_pool, W_conv2, b_conv2, conv_strides, kernel_size, pool_strides, padding='SAME')  
  224.   
  225.   
  226.         # 全连接层  
  227.         W_fc1 = sess.graph.get_tensor_by_name("W_fc1:0")  
  228.         b_fc1 = sess.graph.get_tensor_by_name("b_fc1:0")  
  229.         h_pool2_flat = tf.reshape(L2_pool, [-116 * 20*32])  
  230.         h_fc1 = full_connect(h_pool2_flat, W_fc1, b_fc1)  
  231.   
  232.   
  233.         # dropout  
  234.         keep_prob = tf.placeholder(tf.float32)  
  235.   
  236.         h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)  
  237.   
  238.   
  239.         # readout层  
  240.         W_fc2 = sess.graph.get_tensor_by_name("W_fc2:0")  
  241.         b_fc2 = sess.graph.get_tensor_by_name("b_fc2:0")  
  242.   
  243.         # 定义优化器和训练op  
  244.         conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)  
  245.   
  246.         for n in range(2,3):  
  247.             path = "test_images/%s.bmp" % (n)  
  248.             img = Image.open(path)  
  249.             width = img.size[0]  
  250.             height = img.size[1]  
  251.   
  252.             img_data = [[0]*SIZE for i in range(1)]  
  253.             for h in range(0, height):  
  254.                 for w in range(0, width):  
  255.                     if img.getpixel((w, h)) < 190:  
  256.                         img_data[0][w+h*width] = 1  
  257.                     else:  
  258.                         img_data[0][w+h*width] = 0  
  259.               
  260.             result = sess.run(conv, feed_dict = {x: np.array(img_data), keep_prob: 1.0})  
  261.               
  262.             max1 = 0  
  263.             max2 = 0  
  264.             max3 = 0  
  265.             max1_index = 0  
  266.             max2_index = 0  
  267.             max3_index = 0  
  268.             for j in range(NUM_CLASSES):  
  269.                 if result[0][j] > max1:  
  270.                     max1 = result[0][j]  
  271.                     max1_index = j  
  272.                     continue  
  273.                 if (result[0][j]>max2) and (result[0][j]<=max1):  
  274.                     max2 = result[0][j]  
  275.                     max2_index = j  
  276.                     continue  
  277.                 if (result[0][j]>max3) and (result[0][j]<=max2):  
  278.                     max3 = result[0][j]  
  279.                     max3_index = j  
  280.                     continue  
  281.               
  282.             if n == 3:  
  283.                 license_num += "-"  
  284.             license_num = license_num + LETTERS_DIGITS[max1_index]  
  285.             print ("概率:  [%s %0.2f%%]    [%s %0.2f%%]    [%s %0.2f%%]" % (LETTERS_DIGITS[max1_index],max1*100, LETTERS_DIGITS[max2_index],max2*100, LETTERS_DIGITS[max3_index],max3*100))  
  286.               
  287.         print ("城市代号是: 【%s】" % license_num)  
车牌编号训练+识别代码( 保存文件名为train-license-digits.py ):
[python]  view plain  copy
  1. #!/usr/bin/python3.5  
  2. # -*- coding: utf-8 -*-    
  3.   
  4. import sys  
  5. import os  
  6. import time  
  7. import random  
  8.   
  9. import numpy as np  
  10. import tensorflow as tf  
  11.   
  12. from PIL import Image  
  13.   
  14.   
  15. SIZE = 1280  
  16. WIDTH = 32  
  17. HEIGHT = 40  
  18. NUM_CLASSES = 34  
  19. iterations = 1000  
  20.   
  21. SAVER_DIR = "train-saver/digits/"  
  22.   
  23. LETTERS_DIGITS = ("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")  
  24. license_num = ""  
  25.   
  26. time_begin = time.time()  
  27.   
  28.   
  29. # 定义输入节点,对应于图片像素值矩阵集合和图片标签(即所代表的数字)  
  30. x = tf.placeholder(tf.float32, shape=[None, SIZE])  
  31. y_ = tf.placeholder(tf.float32, shape=[None, NUM_CLASSES])  
  32.   
  33. x_image = tf.reshape(x, [-1, WIDTH, HEIGHT, 1])  
  34.   
  35.   
  36. # 定义卷积函数  
  37. def conv_layer(inputs, W, b, conv_strides, kernel_size, pool_strides, padding):  
  38.     L1_conv = tf.nn.conv2d(inputs, W, strides=conv_strides, padding=padding)  
  39.     L1_relu = tf.nn.relu(L1_conv + b)  
  40.     return tf.nn.max_pool(L1_relu, ksize=kernel_size, strides=pool_strides, padding='SAME')  
  41.   
  42. # 定义全连接层函数  
  43. def full_connect(inputs, W, b):  
  44.     return tf.nn.relu(tf.matmul(inputs, W) + b)  
  45.   
  46.   
  47. if __name__ =='__main__' and sys.argv[1]=='train':  
  48.     # 第一次遍历图片目录是为了获取图片总数  
  49.     input_count = 0  
  50.     for i in range(0,NUM_CLASSES):  
  51.         dir = './train_images/training-set/%s/' % i           # 这里可以改成你自己的图片目录,i为分类标签  
  52.         for rt, dirs, files in os.walk(dir):  
  53.             for filename in files:  
  54.                 input_count += 1  
  55.   
  56.     # 定义对应维数和各维长度的数组  
  57.     input_images = np.array([[0]*SIZE for i in range(input_count)])  
  58.     input_labels = np.array([[0]*NUM_CLASSES for i in range(input_count)])  
  59.   
  60.     # 第二次遍历图片目录是为了生成图片数据和标签  
  61.     index = 0  
  62.     for i in range(0,NUM_CLASSES):  
  63.         dir = './train_images/training-set/%s/' % i          # 这里可以改成你自己的图片目录,i为分类标签  
  64.         for rt, dirs, files in os.walk(dir):  
  65.             for filename in files:  
  66.                 filename = dir + filename  
  67.                 img = Image.open(filename)  
  68.                 width = img.size[0]  
  69.                 height = img.size[1]  
  70.                 for h in range(0, height):  
  71.                     for w in range(0, width):  
  72.                         # 通过这样的处理,使数字的线条变细,有利于提高识别准确率  
  73.                         if img.getpixel((w, h)) > 230:  
  74.                             input_images[index][w+h*width] = 0  
  75.                         else:  
  76.                             input_images[index][w+h*width] = 1  
  77.                 input_labels[index][i] = 1  
  78.                 index += 1  
  79.   
  80.     # 第一次遍历图片目录是为了获取图片总数  
  81.     val_count = 0  
  82.     for i in range(0,NUM_CLASSES):  
  83.         dir = './train_images/validation-set/%s/' % i           # 这里可以改成你自己的图片目录,i为分类标签  
  84.         for rt, dirs, files in os.walk(dir):  
  85.             for filename in files:  
  86.                 val_count += 1  
  87.   
  88.     # 定义对应维数和各维长度的数组  
  89.     val_images = np.array([[0]*SIZE for i in range(val_count)])  
  90.     val_labels = np.array([[0]*NUM_CLASSES for i in range(val_count)])  
  91.   
  92.     # 第二次遍历图片目录是为了生成图片数据和标签  
  93.     index = 0  
  94.     for i in range(0,NUM_CLASSES):  
  95.         dir = './train_images/validation-set/%s/' % i          # 这里可以改成你自己的图片目录,i为分类标签  
  96.         for rt, dirs, files in os.walk(dir):  
  97.             for filename in files:  
  98.                 filename = dir + filename  
  99.                 img = Image.open(filename)  
  100.                 width = img.size[0]  
  101.                 height = img.size[1]  
  102.                 for h in range(0, height):  
  103.                     for w in range(0, width):  
  104.                         # 通过这样的处理,使数字的线条变细,有利于提高识别准确率  
  105.                         if img.getpixel((w, h)) > 230:  
  106.                             val_images[index][w+h*width] = 0  
  107.                         else:  
  108.                             val_images[index][w+h*width] = 1  
  109.                 val_labels[index][i] = 1  
  110.                 index += 1  
  111.       
  112.     with tf.Session() as sess:  
  113.         # 第一个卷积层  
  114.         W_conv1 = tf.Variable(tf.truncated_normal([88116], stddev=0.1), name="W_conv1")  
  115.         b_conv1 = tf.Variable(tf.constant(0.1, shape=[16]), name="b_conv1")  
  116.         conv_strides = [1111]  
  117.         kernel_size = [1221]  
  118.         pool_strides = [1221]  
  119.         L1_pool = conv_layer(x_image, W_conv1, b_conv1, conv_strides, kernel_size, pool_strides, padding='SAME')  
  120.   
  121.         # 第二个卷积层  
  122.         W_conv2 = tf.Variable(tf.truncated_normal([551632], stddev=0.1), name="W_conv2")  
  123.         b_conv2 = tf.Variable(tf.constant(0.1, shape=[32]), name="b_conv2")  
  124.         conv_strides = [1111]  
  125.         kernel_size = [1111]  
  126.         pool_strides = [1111]  
  127.         L2_pool = conv_layer(L1_pool, W_conv2, b_conv2, conv_strides, kernel_size, pool_strides, padding='SAME')  
  128.   
  129.   
  130.         # 全连接层  
  131.         W_fc1 = tf.Variable(tf.truncated_normal([16 * 20 * 32512], stddev=0.1), name="W_fc1")  
  132.         b_fc1 = tf.Variable(tf.constant(0.1, shape=[512]), name="b_fc1")  
  133.         h_pool2_flat = tf.reshape(L2_pool, [-116 * 20*32])  
  134.         h_fc1 = full_connect(h_pool2_flat, W_fc1, b_fc1)  
  135.   
  136.   
  137.         # dropout  
  138.         keep_prob = tf.placeholder(tf.float32)  
  139.   
  140.         h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)  
  141.   
  142.   
  143.         # readout层  
  144.         W_fc2 = tf.Variable(tf.truncated_normal([512, NUM_CLASSES], stddev=0.1), name="W_fc2")  
  145.         b_fc2 = tf.Variable(tf.constant(0.1, shape=[NUM_CLASSES]), name="b_fc2")  
  146.   
  147.         # 定义优化器和训练op  
  148.         y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2  
  149.         cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y_conv))  
  150.         train_step = tf.train.AdamOptimizer((1e-4)).minimize(cross_entropy)  
  151.   
  152.         correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))  
  153.         accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))  
  154.   
  155.         sess.run(tf.global_variables_initializer())  
  156.   
  157.         time_elapsed = time.time() - time_begin  
  158.         print("读取图片文件耗费时间:%d秒" % time_elapsed)  
  159.         time_begin = time.time()  
  160.   
  161.         print ("一共读取了 %s 个训练图像, %s 个标签" % (input_count, input_count))  
  162.   
  163.         # 设置每次训练op的输入个数和迭代次数,这里为了支持任意图片总数,定义了一个余数remainder,譬如,如果每次训练op的输入个数为60,图片总数为150张,则前面两次各输入60张,最后一次输入30张(余数30)  
  164.         batch_size = 60  
  165.         iterations = iterations  
  166.         batches_count = int(input_count / batch_size)  
  167.         remainder = input_count % batch_size  
  168.         print ("训练数据集分成 %s 批, 前面每批 %s 个数据,最后一批 %s 个数据" % (batches_count+1, batch_size, remainder))  
  169.   
  170.         # 执行训练迭代  
  171.         for it in range(iterations):  
  172.             # 这里的关键是要把输入数组转为np.array  
  173.             for n in range(batches_count):  
  174.                 train_step.run(feed_dict={x: input_images[n*batch_size:(n+1)*batch_size], y_: input_labels[n*batch_size:(n+1)*batch_size], keep_prob: 0.5})  
  175.             if remainder > 0:  
  176.                 start_index = batches_count * batch_size;  
  177.                 train_step.run(feed_dict={x: input_images[start_index:input_count-1], y_: input_labels[start_index:input_count-1], keep_prob: 0.5})  
  178.   
  179.             # 每完成五次迭代,判断准确度是否已达到100%,达到则退出迭代循环  
  180.             iterate_accuracy = 0  
  181.             if it%5 == 0:  
  182.                 iterate_accuracy = accuracy.eval(feed_dict={x: val_images, y_: val_labels, keep_prob: 1.0})  
  183.                 print ('第 %d 次训练迭代: 准确率 %0.5f%%' % (it, iterate_accuracy*100))  
  184.                 if iterate_accuracy >= 0.9999 and it >= iterations:  
  185.                     break;  
  186.   
  187.         print ('完成训练!')  
  188.         time_elapsed = time.time() - time_begin  
  189.         print ("训练耗费时间:%d秒" % time_elapsed)  
  190.         time_begin = time.time()  
  191.   
  192.         # 保存训练结果  
  193.         if not os.path.exists(SAVER_DIR):  
  194.             print ('不存在训练数据保存目录,现在创建保存目录')  
  195.             os.makedirs(SAVER_DIR)  
  196.         # 初始化saver  
  197.         saver = tf.train.Saver()              
  198.         saver_path = saver.save(sess, "%smodel.ckpt"%(SAVER_DIR))  
  199.   
  200.   
  201.   
  202. if __name__ =='__main__' and sys.argv[1]=='predict':  
  203.     saver = tf.train.import_meta_graph("%smodel.ckpt.meta"%(SAVER_DIR))  
  204.     with tf.Session() as sess:  
  205.         model_file=tf.train.latest_checkpoint(SAVER_DIR)  
  206.         saver.restore(sess, model_file)  
  207.   
  208.         # 第一个卷积层  
  209.         W_conv1 = sess.graph.get_tensor_by_name("W_conv1:0")  
  210.         b_conv1 = sess.graph.get_tensor_by_name("b_conv1:0")  
  211.         conv_strides = [1111]  
  212.         kernel_size = [1221]  
  213.         pool_strides = [1221]  
  214.         L1_pool = conv_layer(x_image, W_conv1, b_conv1, conv_strides, kernel_size, pool_strides, padding='SAME')  
  215.   
  216.         # 第二个卷积层  
  217.         W_conv2 = sess.graph.get_tensor_by_name("W_conv2:0")  
  218.         b_conv2 = sess.graph.get_tensor_by_name("b_conv2:0")  
  219.         conv_strides = [1111]  
  220.         kernel_size = [1111]  
  221.         pool_strides = [1111]  
  222.         L2_pool = conv_layer(L1_pool, W_conv2, b_conv2, conv_strides, kernel_size, pool_strides, padding='SAME')  
  223.   
  224.   
  225.         # 全连接层  
  226.         W_fc1 = sess.graph.get_tensor_by_name("W_fc1:0")  
  227.         b_fc1 = sess.graph.get_tensor_by_name("b_fc1:0")  
  228.         h_pool2_flat = tf.reshape(L2_pool, [-116 * 20*32])  
  229.         h_fc1 = full_connect(h_pool2_flat, W_fc1, b_fc1)  
  230.   
  231.   
  232.         # dropout  
  233.         keep_prob = tf.placeholder(tf.float32)  
  234.   
  235.         h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)  
  236.   
  237.   
  238.         # readout层  
  239.         W_fc2 = sess.graph.get_tensor_by_name("W_fc2:0")  
  240.         b_fc2 = sess.graph.get_tensor_by_name("b_fc2:0")  
  241.   
  242.         # 定义优化器和训练op  
  243.         conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)  
  244.   
  245.         for n in range(3,8):  
  246.             path = "test_images/%s.bmp" % (n)  
  247.             img = Image.open(path)  
  248.             width = img.size[0]  
  249.             height = img.size[1]  
  250.   
  251.             img_data = [[0]*SIZE for i in range(1)]  
  252.             for h in range(0, height):  
  253.                 for w in range(0, width):  
  254.                     if img.getpixel((w, h)) < 190:  
  255.                         img_data[0][w+h*width] = 1  
  256.                     else:  
  257.                         img_data[0][w+h*width] = 0  
  258.               
  259.             result = sess.run(conv, feed_dict = {x: np.array(img_data), keep_prob: 1.0})  
  260.               
  261.             max1 = 0  
  262.             max2 = 0  
  263.             max3 = 0  
  264.             max1_index = 0  
  265.             max2_index = 0  
  266.             max3_index = 0  
  267.             for j in range(NUM_CLASSES):  
  268.                 if result[0][j] > max1:  
  269.                     max1 = result[0][j]  
  270.                     max1_index = j  
  271.                     continue  
  272.                 if (result[0][j]>max2) and (result[0][j]<=max1):  
  273.                     max2 = result[0][j]  
  274.                     max2_index = j  
  275.                     continue  
  276.                 if (result[0][j]>max3) and (result[0][j]<=max2):  
  277.                     max3 = result[0][j]  
  278.                     max3_index = j  
  279.                     continue  
  280.               
  281.             license_num = license_num + LETTERS_DIGITS[max1_index]  
  282.             print ("概率:  [%s %0.2f%%]    [%s %0.2f%%]    [%s %0.2f%%]" % (LETTERS_DIGITS[max1_index],max1*100, LETTERS_DIGITS[max2_index],max2*100, LETTERS_DIGITS[max3_index],max3*100))  
  283.               
  284.         print ("车牌编号是: 【%s】" % license_num)  
保存好上面三个python脚本后,我们首先进行省份简称训练。在运行代码之前,需要先把数据集解压到训练脚本所在目录。然后,在命令行中进入脚本所在目录,输入执行如下命令:
[python]  view plain  copy
  1. python train-license-province.py train  
训练结果如下:

然后进行省份简称识别,在命令行输入执行如下命令:

[python]  view plain  copy
  1. python train-license-province.py predict  


执行城市代号训练(相当于训练26个字母):

[python]  view plain  copy
  1. python train-license-letters.py train  

识别城市代号:

[python]  view plain  copy
  1. python train-license-letters.py predict  


执行车牌编号训练(相当于训练24个字母+10个数字,我国交通法规规定车牌编号中不包含字母I和O):

[python]  view plain  copy
  1. python train-license-digits.py train  

识别车牌编号:

[python]  view plain  copy
  1. python train-license-digits.py predict  

可以看到,在测试图片上,识别准确率很高。识别结果是闽O-1672Q。


下图是测试图片的车牌原图:


猜你喜欢

转载自blog.csdn.net/zr940326/article/details/80558442
今日推荐