<file_sep># ai-car-plate
ai-car-plate
<file_sep>import numpy as np
import paddle.fluid as fluid
import matplotlib.pyplot as plt
import argparse
from PIL import Image
from plate_utils import plate_split
from lenet import LeNet5
from gen_utils import gen_dataset


def parse_args():
    parser = argparse.ArgumentParser("Prediction Parameters")
    parser.add_argument(
        '--weight_file',
        type=str,
        default='car_plate_10',
        help='the path of model parameters')
    parser.add_argument(
        '--test_plate',
        type=str,
        default='test/001.png',
        help='the test plate')
    args = parser.parse_args()
    return args


args = parse_args()
WEIGHT_FILE = args.weight_file
TEST_PLATE = args.test_plate


def predict(model, params_file_path, test_plate):
    with fluid.dygraph.guard():
        model_state_dict, _ = fluid.load_dygraph(params_file_path)
        model.load_dict(model_state_dict)
        model.eval()
        _, _, character_mapper = gen_dataset()
        img_character_dict = plate_split(test_plate)
        plate = []
        for key in img_character_dict:
            img = img_character_dict[key]
            img = img.flatten().astype('float32') / 255.0
            img = img.reshape(1, 1, 20, 20)
            img = fluid.dygraph.to_variable(img)
            logits = model(img)
            result = fluid.layers.softmax(logits).numpy()
            result = np.argmax(result[0])
            result = character_mapper.get(result, '')
            plate.append(result)
            print("key:{}, result:{}".format(key, result))
        plt.imshow(Image.open(test_plate))
        print("\n车牌识别结果为：", end='')
        for i in range(len(plate)):
            print(plate[i], end='')
        print("\n")
        plt.show()


if __name__ == '__main__':
    test_plate = TEST_PLATE
    params_file_path = WEIGHT_FILE
    with fluid.dygraph.guard():
        model = LeNet5('LeNet5', num_classes=65)
    predict(model, params_file_path, test_plate)
<file_sep>import numpy as np
import cv2
from gen_utils import gen_dataset


def img_mapper(sample):
    img, label = sample
    img = cv2.imdecode(np.fromfile(img, dtype=np.uint8), 0)
    img = img.flatten().astype('float32') / 255.0
    img = img.reshape(1, 20, 20)
    return img, label


def data_loader(img_list, batch_size=100, mode='train'):
    def reader():
        if mode == 'train':
            np.random.shuffle(img_list)

        batch_imgs = []
        batch_labels = []
        for info in img_list:
            path, label = info
            img, label = img_mapper((path, label))
            batch_imgs.append(img)
            batch_labels.append(label)
            if len(batch_imgs) == batch_size:
                img_array = np.array(batch_imgs).astype('float32')
                labels_array = np.array(batch_labels).astype('int64').reshape(-1, 1)
                yield img_array, labels_array
                batch_imgs = []
                batch_labels = []

        if len(batch_imgs) > 0:
            img_array = np.array(batch_imgs).astype('float32')
            labels_array = np.array(batch_labels).astype('int64').reshape(-1, 1)
            yield img_array, labels_array

    return reader


if __name__ == '__main__':
    train_dataset, _, _ = gen_dataset()
    train_loader = data_loader(train_dataset)
    train_img, train_label = next(train_loader())
    print(train_img.shape)
    print(train_label.shape)
<file_sep>import paddle.fluid as fluid
from paddle.fluid.dygraph.nn import Conv2D, Pool2D, FC


class LeNet5(fluid.dygraph.Layer):
    def __init__(self, name_scope, num_classes):
        super(LeNet5, self).__init__(name_scope)
        self.conv1 = Conv2D(self.full_name(), num_filters=50, filter_size=5, stride=1)
        self.pool1 = Pool2D(self.full_name(), pool_size=2, pool_stride=1, pool_type='max')
        self.conv2 = Conv2D(self.full_name(), num_filters=32, filter_size=3, stride=1)
        self.pool2 = Pool2D(self.full_name(), pool_size=2, pool_stride=1, pool_type='max')
        self.fc1 = FC(self.full_name(), size=num_classes, act='softmax')

    def forward(self, x):
        x = self.conv1(x)
        x = self.pool1(x)
        x = self.conv2(x)
        x = self.pool2(x)
        x = self.fc1(x)
        return x
<file_sep>import numpy as np
import cv2


def plate_split(plate_file):
    img_character_dict = {}
    img_plate = cv2.imread(plate_file)
    img_plate = cv2.cvtColor(img_plate, cv2.COLOR_RGB2GRAY)
    th, binary_plate = cv2.threshold(img_plate, 175, 255, cv2.THRESH_BINARY)
    result = []
    for col in range(binary_plate.shape[1]):
        result.append(0)
        for row in range(binary_plate.shape[0]):
            result[col] = result[col] + binary_plate[row][col] / 255
    character_dict = {}
    num = 0
    i = 0
    while i < len(result):
        if result[i] == 0:
            i += 1
        else:
            index = i + 1
            while result[index] != 0:
                index += 1
            character_dict[num] = [i, index - 1]
            num += 1
            i = index

    for i in range(8):
        if i == 2:
            continue
        padding = (170 - (character_dict[i][1] - character_dict[i][0])) / 2
        img_character = np.pad(binary_plate[:, character_dict[i][0]:character_dict[i][1]],
                               ((0, 0), (int(padding), int(padding))), 'constant', constant_values=(0, 0))
        img_character = cv2.resize(img_character, (20, 20))
        # cv2.imwrite(str(i) + '.png', img_character)
        img_character_dict[i] = img_character

    return img_character_dict


if __name__ == '__main__':
    img_character_dict = plate_split('test/001.png')
    for key in img_character_dict:
        print("key:{}, img shape:{}".format(key, img_character_dict[key].shape))
<file_sep>import os

folder_mapper = {'0': '0',
                 '1': '1',
                 '2': '2',
                 '3': '3',
                 '4': '4',
                 '5': '5',
                 '6': '6',
                 '7': '7',
                 '8': '8',
                 '9': '9',
                 'A': 'A',
                 'B': 'B',
                 'C': 'C',
                 'cuan': '川',
                 'D': 'D',
                 'E': 'E',
                 'e1': '鄂',
                 'F': 'F',
                 'G': 'G',
                 'gan': '赣',
                 'gan1': '甘',
                 'gui': '贵',
                 'gui1': '桂',
                 'H': 'H',
                 'hei': '黑',
                 'hu': '沪',
                 'J': 'J',
                 'ji': '冀',
                 'ji1': '吉',
                 'jin': '津',
                 'jing': '京',
                 'K': 'K',
                 'L': 'L',
                 'liao': '辽',
                 'lu': '鲁',
                 'M': 'M',
                 'meng': '蒙',
                 'min': '闽',
                 'N': 'N',
                 'ning': '宁',
                 'P': 'P',
                 'Q': 'Q',
                 'qing': '青',
                 'qiong': '琼',
                 'R': 'R',
                 'S': 'S',
                 'shan': '陕',
                 'su': '苏',
                 'sx': '晋',
                 'T': 'T',
                 'U': 'U',
                 'V': 'V',
                 'W': 'W',
                 'wan': '皖',
                 'X': 'X',
                 'xiang': '湘',
                 'xin': '新',
                 'Y': 'Y',
                 'yu': '豫',
                 'yu1': '渝',
                 'yue': '粤',
                 'yun': '云',
                 'Z': 'Z',
                 'zang': '藏',
                 'zhe': '浙'}


# 生成车牌字符图像列表
def gen_dataset():
    data_path = 'train'
    character_folders = os.listdir(data_path)
    label = 0
    train_dataset = []
    valid_dataset = []
    character_mapper = {}
    for character_folder in character_folders:
        if character_folder == '.DS_Store' \
                or character_folder == '.ipynb_checkpoints':
            continue
        character_mapper[label] = folder_mapper.get(character_folder, '')
        # print(str(label) + "  " + character_folder + "  " + character_mapper[label])
        character_imgs = os.listdir(os.path.join(data_path, character_folder))
        for i in range(len(character_imgs)):
            if i % 10 == 0:
                valid_dataset.append((os.path.join(os.path.join(data_path, character_folder),
                                                   character_imgs[i]), label))
            else:
                train_dataset.append((os.path.join(os.path.join(data_path, character_folder),
                                                   character_imgs[i]), label))
        label = label + 1
    return train_dataset, valid_dataset, character_mapper


if __name__ == '__main__':
    train_dataset, valid_dataset, character_mapper = gen_dataset()
    print('train size:{}, valid_size:{}, mapper_len:{}'.format(len(train_dataset),
                                                               len(valid_dataset),
                                                               len(character_mapper)))
<file_sep>import matplotlib.pyplot as plt


# 绘制训练趋势图
def draw_figure(acc, val_acc, loss, val_loss):
    count = len(acc)
    epochs = range(1, count + 1)
    plt.plot(epochs, acc, 'bo', label='Training accuracy')
    plt.plot(epochs, val_acc, 'b', label='Validation accuracy')
    plt.title('Training and validation accuracy')
    plt.legend()
    plt.savefig('car_plate_acc_{}.png'.format(count))

    plt.figure()
    plt.plot(epochs, loss, 'bo', label='Training loss')
    plt.plot(epochs, val_loss, 'b', label='Validation loss')
    plt.title('Training and validation loss')
    plt.legend()
    plt.savefig('car_plate_loss_{}.png'.format(count))
    # plt.show()
<file_sep>certifi==2019.11.28
chardet==3.0.4
cycler==0.10.0
decorator==4.4.1
funcsigs==1.0.2
graphviz==0.13.2
idna==2.9
kiwisolver==1.1.0
matplotlib==3.1.3
nltk==3.4.5
numpy==1.18.1
objgraph==3.4.1
opencv-python==4.2.0.32
paddlepaddle==1.6.3
Pillow==7.0.0
prettytable==0.7.2
protobuf==3.11.3
pyparsing==2.4.6
python-dateutil==2.8.1
PyYAML==5.3
rarfile==3.1
requests==2.23.0
scipy==1.4.1
six==1.14.0
urllib3==1.25.8
<file_sep>import datetime
import paddle.fluid as fluid
import numpy as np
import argparse
from reader import data_loader
from lenet import LeNet5
from figure_utils import draw_figure
from gen_utils import gen_dataset


def parse_args():
    parser = argparse.ArgumentParser("Training Parameters")
    parser.add_argument(
        '--num_epoch',
        type=int,
        default=20,
        help='the epoch num')
    parser.add_argument(
        '--batch_size',
        type=int,
        default=100,
        help='the batch size')
    args = parser.parse_args()
    return args


args = parse_args()
NUM_EPOCH = args.num_epoch
BATCH_SIZE = args.batch_size


def train(model):
    with fluid.dygraph.guard():
        print('start training ... ')
        begin = datetime.datetime.now()
        model.train()
        epoch_num = NUM_EPOCH
        all_acc = []
        all_val_acc = []
        all_loss = []
        all_val_loss = []
        opt = fluid.optimizer.Momentum(learning_rate=0.001, momentum=0.9)
        train_dataset, valid_dataset, _ = gen_dataset()
        train_loader = data_loader(train_dataset, batch_size=BATCH_SIZE, mode='train')
        valid_loader = data_loader(valid_dataset, batch_size=BATCH_SIZE, mode='valid')
        for epoch in range(epoch_num):
            accuracies = []
            losses = []
            for batch_id, data in enumerate(train_loader()):
                x_data, y_data = data
                img = fluid.dygraph.to_variable(x_data)
                label = fluid.dygraph.to_variable(y_data)
                logits = model(img)
                cost = fluid.layers.cross_entropy(input=logits, label=label)
                acc = fluid.layers.accuracy(input=logits, label=label)
                avg_cost = fluid.layers.mean(cost)
                if batch_id % 50 == 0:
                    print("epoch: {}, batch_id: {}, acc is {}, loss is: {}".format(epoch,
                                                                                   batch_id,
                                                                                   acc.numpy(),
                                                                                   avg_cost.numpy()))

                # 反向传播，更新权重，清除梯度
                avg_cost.backward()
                opt.minimize(avg_cost)
                model.clear_gradients()
                accuracies.append(acc.numpy())
                losses.append(avg_cost.numpy())

            print("[train] accuracy/loss: {}/{}".format(np.mean(accuracies), np.mean(losses)))
            all_acc.append(np.mean(accuracies))
            all_loss.append(np.mean(losses))

            # 每5轮过后保存模型参数
            if (epoch % 5 == 0) or (epoch == epoch_num - 1):
                fluid.save_dygraph(model.state_dict(), 'car_plate_{}'.format(epoch))

            model.eval()
            accuracies = []
            losses = []
            for batch_id, data in enumerate(valid_loader()):
                x_data, y_data = data
                img = fluid.dygraph.to_variable(x_data)
                label = fluid.dygraph.to_variable(y_data)
                logits = model(img)
                cost = fluid.layers.cross_entropy(input=logits, label=label)
                acc = fluid.layers.accuracy(input=logits, label=label)
                avg_cost = fluid.layers.mean(cost)
                accuracies.append(acc.numpy())
                losses.append(avg_cost.numpy())

            print("[validation] accuracy/loss: {}/{}".format(np.mean(accuracies), np.mean(losses)))
            all_val_acc.append(np.mean(accuracies))
            all_val_loss.append(np.mean(losses))

            # 绘图，每5轮绘制一个趋势图
            if (epoch % 5 == 0) or (epoch == epoch_num - 1):
                count = len(all_acc)
                if count > 2:
                    sub_all_acc = all_acc[2:]
                    sub_all_val_acc = all_val_acc[2:]
                    sub_all_loss = all_loss[2:]
                    sub_all_val_loss = all_val_loss[2:]
                    draw_figure(sub_all_acc, sub_all_val_acc, sub_all_loss, sub_all_val_loss)

            model.train()

        end = datetime.datetime.now()
        seconds = (end - begin).seconds
        print("finished. total cost {}".format(datetime.timedelta(seconds=seconds)))


if __name__ == '__main__':
    with fluid.dygraph.guard():
        model = LeNet5('LeNet5', num_classes=65)
    train(model)
