淘先锋技术网

首页 1 2 3 4 5 6 7

(一)数据处理

1.图像增强:

from keras.preprocessing import image
import os
import matplotlib.pyplot as plt
import numpy as np
from imageio import imwrite

"""
数据增强实现
将 1084 张图片扩为 1084*80 张
"""

# 常量
im_h = 46       # 图片高度
im_w = 120      # 图片宽度
im_chan = 3     # 图片通道数目
im_n = 4        # 每张图片分割的子图数目
w = 30          # 分割图片宽度,为im_w的四分之一


def load_img_t(path):
    """
    加载完整的一张图片
    origin: (43, 120, 3)
    target: (1, 43, 120, 3)
    :param path: 图片路径
    :return:
    """
    im = plt.imread(path)
    im.resize(im_h, im_w, im_chan)       # 压缩成标准尺寸
    x = np.zeros((1, im_h, im_w, im_chan))
    x[0] = im
    return x


def splice_img(arr):
    """
    拼接图片
    origin: (4, 43, 30, 3)
    target: (43, 120, 3)
    :param arr: 四张子图片数组
    :return:
    """
    im = np.zeros((im_h, im_w, im_chan))
    for i in range(im_n):
        im[:, i*w:(i+1)*w, :] = arr[i]
    return im


def load_img(path):
    """
    加载某张图片,每张分割成四张图片,返回x数组
    origin: (43, 120, 3)
    target: (4, 43, 30, 3)
    :param path: 图片路径
    :return:
    """
    im = plt.imread(path)
    im.resize(im_h, im_w, im_chan)       # 压缩成标准尺寸
    x = np.zeros((im_n, im_h, w, im_chan))        # 分割成四张图片
    for i in range(im_n):
        x[i] = im[:, i*w:(i+1)*w, :]
    return x


im_dir = '../../data/images/'
im_aug_dir = '../../data/images_aug/'

files = os.listdir(im_dir)

n = 10

# 1 - 10
# 缩放与旋转
im_gen1 = image.ImageDataGenerator(zoom_range=[2, 1], rotation_range=40)

for file in files:
    im = load_img(os.path.join(im_dir, file))
    im_iter = im_gen1.flow(im, batch_size=4, shuffle=False)
    for i in range(n):
        imwrite(im_aug_dir + file[:-5] + str(i+1) + '.png', splice_img(im_iter.next()))
        # plt.imsave(im_aug_dir + file[:-5] + str(i+1) + '.png', splice_img(im_iter.next()))

# 11 - 20
im_gen2 = image.ImageDataGenerator(samplewise_center=True,
                                   samplewise_std_normalization=True)
for file in files:
    im = load_img(os.path.join(im_dir, file))
    im_iter = im_gen2.flow(im, batch_size=4, shuffle=False)
    for i in range(n):
        imwrite(im_aug_dir + file[:-5] + str(i+1+n) + '.png', splice_img(im_iter.next()))
        # plt.imsave(im_aug_dir + file[:-5] + str(i+1+n) + '.png', splice_img(im_iter.next()))

# 21 - 30
im_gen3 = image.ImageDataGenerator(shear_range=0.5)
for file in files:
    im = load_img(os.path.join(im_dir, file))
    im_iter = im_gen3.flow(im, batch_size=4, shuffle=False)
    for i in range(n):
        imwrite(im_aug_dir + file[:-5] + str(i+1+n*2) + '.png', splice_img(im_iter.next()))
        # plt.imsave(im_aug_dir + file[:-5] + str(i+1+n*2) + '.png', splice_img(im_iter.next()))

# 31 - 40
im_gen4 = image.ImageDataGenerator(channel_shift_range=0.2)
for file in files:
    im = load_img_t(os.path.join(im_dir, file))
    im_iter = im_gen4.flow(im, batch_size=1, shuffle=False)
    for i in range(n):
        imwrite(im_aug_dir + file[:-5] + str(i+1+n*3) + '.png', im_iter.next()[0])
        # plt.imsave(im_aug_dir + file[:-5] + str(i+1+n*3) + '.png', im_iter.next()[0])

# 41 - 50
im_gen5 = image.ImageDataGenerator(zoom_range=[2, 1])

for file in files:
    im = load_img(os.path.join(im_dir, file))
    im_iter = im_gen5.flow(im, batch_size=4, shuffle=False)
    for i in range(n):
        imwrite(im_aug_dir + file[:-5] + str(i+1+n*4) + '.png', splice_img(im_iter.next()))
        # plt.imsave(im_aug_dir + file[:-5] + str(i+1+n*4) + '.png', splice_img(im_iter.next()))

# 51 - 60
im_gen6 = image.ImageDataGenerator(rotation_range=40)

for file in files:
    im = load_img(os.path.join(im_dir, file))
    im_iter = im_gen6.flow(im, batch_size=4, shuffle=False)
    for i in range(n):
        imwrite(im_aug_dir + file[:-5] + str(i+1+n*5) + '.png', splice_img(im_iter.next()))
        # plt.imsave(im_aug_dir + file[:-5] + str(i+1+n*5) + '.png', splice_img(im_iter.next()))

# 61 - 70
im_gen7 = image.ImageDataGenerator(zoom_range=[1.5, 1], channel_shift_range=0.1)

for file in files:
    im = load_img(os.path.join(im_dir, file))
    im_iter = im_gen7.flow(im, batch_size=4, shuffle=False)
    for i in range(n):
        imwrite(im_aug_dir + file[:-5] + str(i+1+n*6) + '.png', splice_img(im_iter.next()))
        # plt.imsave(im_aug_dir + file[:-5] + str(i+1+n*6) + '.png', splice_img(im_iter.next()))

# 71 - 80
im_gen8 = image.ImageDataGenerator(rotation_range=30, channel_shift_range=0.1)

for file in files:
    im = load_img(os.path.join(im_dir, file))
    im_iter = im_gen8.flow(im, batch_size=4, shuffle=False)
    for i in range(n):
        imwrite(im_aug_dir + file[:-5] + str(i+1+n*7) + '.png', splice_img(im_iter.next()))
        # plt.imsave(im_aug_dir + file[:-5] + str(i+1+n*7) + '.png', splice_img(im_iter.next()))


2.图像灰度化

from imageio import imwrite
import matplotlib.pyplot as plt
import os

"""
将所有rgb图片转换成灰度图,放入 /data/images_gray/ 中
"""


def rgb2gray(rgb):
    """
    将rgb图转换为灰度图
    :param rgb:
    :return:
    """
    r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2]
    gray = 0.2989 * r + 0.5870 * g + 0.1140 * b
    return gray


im_dir = '../../data/images/'
im_aug_dir = '../../data/images_aug/'
im_gray_dir = '../../data/images_gray/'


files = os.listdir(im_dir)
for file in files:
    im = plt.imread(os.path.join(im_dir, file))
    imwrite(im_gray_dir + file, rgb2gray(im))


files = os.listdir(im_aug_dir)
for file in files:
    im = plt.imread(os.path.join(im_aug_dir, file))
    imwrite(im_gray_dir + file, rgb2gray(im))

 模型训练与预测:

 (二)pytorch写法:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
import torch
import os
import torch.utils.data as Data
import torch.nn as nn
from torch.autograd import Variable
import torch.nn.functional as F

learning_rate = 0.02
batch_size=256
num_epochs = 20
num_classes=1
"""
图片处理与数据加载相关工具方法
"""

# 数字列表
digit_list = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '']

# 常量
im_h = 46       # 图片高度
im_w = 120      # 图片宽度
im_chan = 3     # 图片通道数目
im_chan_2 = 4   # 图片通道数目
im_n = 4        # 每张图片分割的子图数目
w = 30          # 分割图片宽度,为im_w的四分之一

######################################################################
def load_dir_img(path):
    """加载目录下所有的灰度图片,每张分割成四张图片,返回x数组和y标签数组"""
    files = os.listdir(path)
    # print('files',files)
    #一张训练图片有4张可以分割的图片
    x = np.zeros((len(files)*im_n, im_h, w))
    #分割的图片是原先训练图片的4倍,产生四倍标签
    y = np.zeros(len(files)*im_n)
    for i in range(len(files)):
        file_path = os.path.join(path, files[i])
        im = plt.imread(file_path)
        labels = []
        for k in files[i][0:im_n]:
            if k == '_':
                labels.append(10)
            else:
                labels.append(int(k))
        #切割图片然后将1/4的图片赋值给x
        for j in range(im_n):
            x[i*im_n+j] = im[:, j*w:(j+1)*w]
            y[i*im_n+j] = labels[j]
    return x, y
def load_data_2(img_dir=r'../../data/images_gray', npz_path='../../data/digits.npz'):
    """加载目录下所有图片,自动分成训练集和测试集"""
    x, y = load_dir_img(img_dir)
    # print('load images finished')
    #将图片分为x_train,y_train,将标签分为y_train,y_test
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.1, random_state=42)
    np.savez(npz_path, x_train=x_train, y_train=y_train, x_test=x_test, y_test=y_test)
    # print('data saved as ', npz_path)
    return (x_train, y_train), (x_test, y_test)


def load_data_3(path='../../data/digits.npz'):
    """加载已保存的数据"""
    if os.path.exists(path):
        print('load saved data')
        with np.load(path) as f:
            x_train, y_train = f['x_train'], f['y_train']
            x_test, y_test = f['x_test'], f['y_test']
        return (x_train, y_train), (x_test, y_test)
    else:
        print('initial load data')
        return load_data_2(npz_path=path)
#多分类标签label 转换为 one-hot
def dense_to_one_hot(labels_dense, num_classes):
    """Convert class labels from scalars to one-hot vectors."""
    num_labels = labels_dense.shape[0]
    index_offset = np.arange(num_labels) * num_classes
    labels_one_hot = np.zeros((num_labels, num_classes))
    labels_one_hot.flat[index_offset+labels_dense.ravel()] = 1
    return labels_one_hot

def setdata():
    (x_train, y_train), (x_test, y_test) = load_data_3()
    x_train = x_train[:, np.newaxis, :, :]
    x_train=torch.from_numpy(x_train)
    x_train = x_train.type(torch.FloatTensor)  # 转LongTensor
    # print(x_train.shape)
    y_train = y_train.astype(np.int64)
    # y_train = dense_to_one_hot(y_train, 11)
    # print(y_train)
    # y_train = y_train.astype(np.int64)
    y_train=torch.from_numpy(y_train)
    # print(y_train.shape)
    # print('ay_train', y_train.shape)


    x_test = x_test[:, np.newaxis, :, :]
    x_test=torch.from_numpy(x_test)
    x_test = x_test.type(torch.FloatTensor)  # 转LongTensor

    y_test = y_test.astype(np.int64)
    # y_test = dense_to_one_hot(y_test, num_classes)
    # y_test = y_test.astype(np.int64)
    y_test=torch.from_numpy(y_test)
    # print('y_test', y_test)
    train_dataset = Data.TensorDataset(x_train, y_train)
    test_dataset = Data.TensorDataset(x_test, y_test)
    return  train_dataset,test_dataset
####################################################
#########数据集构建#########
train_dataset,test_dataset=setdata()
train_loader=Data.DataLoader(dataset=train_dataset,batch_size=batch_size,shuffle=True)
test_loader=Data.DataLoader(dataset=test_dataset,batch_size=batch_size,shuffle=True)
####################################################
# 将数据处理成Variable, 如果有GPU, 可以转成cuda形式
def get_variable(x):
    x = Variable(x)
    return x.cuda() if torch.cuda.is_available() else x

def get_test_variable(x):
    with torch.no_grad():
        x = Variable(x)
    return x.cuda() if torch.cuda.is_available() else x

class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(1, 32, kernel_size=5, padding=2),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True)
        )

        self.layer2 = nn.Sequential(
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Dropout(0.25),
        )

        self.layer3 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=5),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True)
        )

        self.layer4 = nn.Sequential(
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Dropout(0.5),
        )

        self.fc = nn.Sequential(
            nn.Linear(2880, 256),
            nn.ReLU(inplace=True),
            # nn.Dropout(0.5),
            nn.Linear(256, 84),
            nn.ReLU(inplace=True),
            nn.Dropout(0.5),
            nn.Linear(84, 11),
        )

    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x

import time
# model = CNN()
model=torch.load("cnn1.pkl")
# model = torch.load('cnn1.pkl')
model.cuda()
##### 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)

### 训练模型

print('************************模型训练开始************************')
start = time.process_time()
step = 0  # 步数,可用下面的 i
for i in range(num_epochs):
    for data in train_loader:
        img, label = data
        # img = img.view(img.size(0), -1)
        img = Variable(img)
        if torch.cuda.is_available():
            img = img.cuda()
            label = label.cuda()
        else:
            img = Variable(img)
            label = Variable(label)
        out = model(img)
        loss = criterion(out, label)
        print_loss = loss.data.item()

        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        step += 1
        print('steps: {}, loss: {:.4}'.format(step, print_loss))

print('************************模型训练结束************************')
end = time.process_time() - start
print('模型耗时:{:.2f}/s'.format(end))

# 保存模型
torch.save(model, 'cnn1.pkl')

# 模型评估
# model.eval()
eval_loss = 0
eval_acc = 0
for data in test_loader:
    img, label = data
    # img = img.view(img.size(0), -1)
    img = Variable(img)
    if torch.cuda.is_available():
        img = img.cuda()
        label = label.cuda()

    out = model(img)
    loss = criterion(out, label)
    eval_loss += loss.data.item() * label.size(0)
    _, pred = torch.max(out, 1)
    num_correct = (pred == label).sum()
    eval_acc += num_correct.item()

print('Test Loss: {:.6f}, Acc: {:.6f}'.format(
    eval_loss / (len(test_dataset)),
    eval_acc / (len(test_dataset))
))
print('预测结果对照显示 (部分) :')
pred_y = torch.max(out.cpu(), 1)[1].data.numpy().squeeze()

label = label.cpu().data.numpy().squeeze()
print(pred_y, '         prediction number')
print(label, '         real number')

模型测试

#keras 预测
import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
import torch
import os
import torch.utils.data as Data
import torch.nn as nn
from torch.autograd import Variable
import torch.nn.functional as F
import utils
"""
测试数字识别
"""

root_path = r'..\..\data\test_images'
im_h = 46
w = 30
# 数字列表
digit_list = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '']
# 两层卷积两层全连接层
class CNN(nn.Module):
    def __init__(self):
        super(CNN, self).__init__()
        self.layer1 = nn.Sequential(
            nn.Conv2d(1, 32, kernel_size=5, padding=2),
            nn.BatchNorm2d(32),
            nn.ReLU(inplace=True)
        )

        self.layer2 = nn.Sequential(
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Dropout(0.25),
        )

        self.layer3 = nn.Sequential(
            nn.Conv2d(32, 64, kernel_size=5),
            nn.BatchNorm2d(64),
            nn.ReLU(inplace=True)
        )

        self.layer4 = nn.Sequential(
            nn.MaxPool2d(kernel_size=2, stride=2),
            nn.Dropout(0.5),
        )

        self.fc = nn.Sequential(
            nn.Linear(2880, 256),
            nn.ReLU(inplace=True),
            # nn.Dropout(0.5),
            nn.Linear(256, 84),
            nn.ReLU(inplace=True),
            nn.Dropout(0.5),
            nn.Linear(84, 11),
        )

    def forward(self, x):
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.layer4(x)
        x = x.view(x.size(0), -1)
        x = self.fc(x)
        return x

def to_digit(index):
    return digit_list[index]

def getPred(pred):
    res = ''
    for i in range(4):
        index = pred[i]
        if to_digit(index) == '':
            res += '_'
        else:
            res += digit_list[index]
    return res

model=torch.load("cnn1.pkl")

model.cuda()
import cv2
files = os.listdir(root_path)
for file in files:
    im_path = os.path.join(root_path, file)

    im = utils.load_img(im_path)
    im = utils.rgb2gray_2(im)

    # im = utils.rgb2gray_2(im)
    im = im.reshape(im.shape[0], 1,im_h, w)
    # print(im.shape)

    im = torch.from_numpy(im)  # numpy_data为numpy类型
    im = im.type(torch.FloatTensor)  # 转LongTensor
    im = Variable(im)
    if torch.cuda.is_available():
        im = im.cuda()

    out = model(im)
    _, pred = torch.max(out, 1)

    pred = pred.cpu().numpy()          #tensor_data为tensor张量
    pred = list(pred)
    pred = getPred(pred)
    print('label: ', file[:-4][0:4], '   digits: ', pred)

 

(三)keras写法:

utils.py

import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
import keras
import os

"""
图片处理与数据加载相关工具方法
"""

# 数字列表
digit_list = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '']

# 常量
im_h = 46       # 图片高度
im_w = 120      # 图片宽度
im_chan = 3     # 图片通道数目
im_chan_2 = 4   # 图片通道数目
im_n = 4        # 每张图片分割的子图数目
w = 30          # 分割图片宽度,为im_w的四分之一


def rgb2gray(rgb):
    """
    将rgb图转换为灰度图
    :param rgb:
    :return:
    """
    r, g, b = rgb[:, :, 0], rgb[:, :, 1], rgb[:, :, 2]
    gray = 0.2989 * r + 0.5870 * g + 0.1140 * b
    return gray


def rgb2gray_2(arr):
    """
    将四张子图组成的rgb图片转换成对应的灰度图组合数组
    origin: (4, 46, 30, 3)
    target: (4, 46, 30)
    :param arr:
    :return:
    """
    res = np.zeros((im_n, im_h, w))
    for i in range(im_n):
        res[i] = rgb2gray(arr[i])
    return res


def splice_img(arr):
    """
    拼接图片
    origin: (4, 43, 30, 3)
    target: (43, 120, 3)
    :param arr: 四张子图片数组
    :return:
    """
    im = np.zeros((im_h, im_w, im_chan))
    for i in range(im_n):
        im[:, i*w:(i+1)*w, :] = arr[i]
    return im


def load_img(path):
    """
    加载某张图片,每张分割成四张图片,返回x数组
    origin: (43, 120, 3)
    target: (4, 43, 30, 3)
    :param path: 图片路径
    :return:
    """
    im = plt.imread(path)
    im.resize(im_h, im_w, im_chan)       # 压缩成标准尺寸
    x = np.zeros((im_n, im_h, w, im_chan))        # 分割成四张图片
    for i in range(im_n):
        x[i] = im[:, i*w:(i+1)*w, :]
    return x


# def load_img_2(path):
#     """
#     加载某张图片,每张分割成四张图片,返回x数组和y标签
#     origin: (43, 120, 3)
#     target: (4, 43, 30, 3)  (4,)
#     :param path:
#     :return:
#     """
#     im = plt.imread(path)
#     im.resize(im_h, im_w, im_chan)       # 压缩成标准尺寸
#     x = np.zeros((im_n, im_h, w, im_chan))        # 分割成四张图片
#     for i in range(im_n):
#         x[i] = im[:, i*w:(i+1)*w, :]
#     labels = []
#     for k in path[-11:-7]:
#         if k == '_':
#             labels.append(-1)
#         else:
#             labels.append(int(k))
#     y = np.array(labels)
#     return x, y


def load_dir_img(path):
    """
    加载目录下所有的灰度图片,每张分割成四张图片,返回x数组和y标签数组
    :param path:
    :return:
    """
    files = os.listdir(path)
    # x = np.zeros((len(files)*im_n, im_h, w, im_chan))
    x = np.zeros((len(files)*im_n, im_h, w))
    y = np.zeros(len(files)*im_n)
    for i in range(len(files)):
        file_path = os.path.join(path, files[i])
        im = plt.imread(file_path)
        labels = []
        for k in files[i][0:im_n]:
            if k == '_':
                labels.append(-1)
            else:
                labels.append(int(k))

        for j in range(im_n):
            x[i*im_n+j] = im[:, j*w:(j+1)*w]
            y[i*im_n+j] = labels[j]

    return x, y


# def load_data(train_path='../../data/train/', test_path='../../data/test/'):
#     """
#     加载训练集和测试集
#     :param train_path:
#     :param test_path:
#     :return:
#     """
#     return load_dir_img(train_path), load_dir_img(test_path)


def load_data_2(img_dir='../../data/images_gray/', npz_path='../../data/digits.npz'):
    """
    加载目录下所有图片,自动分成训练集和测试集
    :param npz_path:
    :param img_dir:
    :return:
    """
    x, y = load_dir_img(img_dir)
    print('load images finished')
    x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.1, random_state=42)
    np.savez(npz_path, x_train=x_train, y_train=y_train, x_test=x_test, y_test=y_test)
    print('data saved as ', npz_path)
    return (x_train, y_train), (x_test, y_test)


def load_data_3(path='../../data/digits.npz'):
    """
    加载已保存的数据
    :param path:
    :return:
    """
    if os.path.exists(path):
        print('load saved data')
        with np.load(path) as f:
            x_train, y_train = f['x_train'], f['y_train']
            x_test, y_test = f['x_test'], f['y_test']
        return (x_train, y_train), (x_test, y_test)
    else:
        print('initial load data')
        return load_data_2(npz_path=path)


def to_digit(cate):
    """
    y标签转化为对应的数字
    :param cate:
    :return:
    """
    return digit_list[np.argmax(cate)]


def img_2_digits_mlp(im_path, model_path='model.h5'):
    """
    使用mlp模型预测图片中的数字,返回一个对应的数字字符串
    :param model_path:
    :param im_path:
    :return:
    """
    im = load_img(im_path)
    im = rgb2gray_2(im)
    x = im.reshape(im.shape[0], -1)     # 拉平矩阵
    model = keras.models.load_model(model_path)       # 加载训练好的模型
    y = model.predict(x)        # 预测
    res = ''
    for i in range(y.shape[0]):
        res += to_digit(y[i])

    return res
#
#
# def img_2_digits_cnn(im_path, model_path='model_cnn.h5'):
#     """
#     使用cnn模型预测图片中的数字,返回一个对应的数字字符串
#     :param im_path:
#     :param model_path:
#     :return:
#     """
#     im = load_img(im_path)
#     im = rgb2gray_2(im)
#     x = im.reshape(im.shape[0], im_h, w, 1)
#     model = keras.models.load_model(model_path)       # 加载训练好的模型
#     y = model.predict(x)        # 预测
#     res = ''
#     for i in range(y.shape[0]):
#         res += to_digit(y[i])
#
#     return res


def img_2_digits(x, model):
    """
    使用训练好的模型,预测结果
    :param x:
    :param model:
    :return:
    """
    y = model.predict(x)
    res = ''
    for i in range(y.shape[0]):
        if to_digit(y[i])=='':
            res += '_'
        else:
            res += to_digit(y[i])

    return res


if __name__ == '__main__':
    x, y = load_img_2('../../data/test/728_a_0.png')
    print(x)
    print(y)
import keras
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
# import utils
import torch.utils.data as Data

import keras
from keras.models import Sequential,load_model
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
import utils

"""
数字识别cnn模型
"""

batch_size = 256
num_classes = 11
epochs = 20

# input image dimensions
img_rows, img_cols = 46, 30

(x_train, y_train), (x_test, y_test) = utils.load_data_3()
print(x_train)
print(y_train)
print('origin')
print('x_train.shape: ', x_train.shape, ' y_train.shape: ', y_train.shape)
print('x_test.shape: ', x_test.shape, 'y_test.shape: ', y_test.shape)

# channel last default
x_train = x_train.reshape(x_train.shape[0], img_rows, img_cols, 1)
x_test = x_test.reshape(x_test.shape[0], img_rows, img_cols, 1)
input_shape = (img_rows, img_cols, 1)

x_train = x_train.astype('float32')
x_test = x_test.astype('float32')

print('reshape x')
print('x_train',x_train)
print('x_train.shape: ', x_train.shape)
print('x_test.shape: ', x_test.shape)

print('by_train: ', y_train.shape)
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

print('cate y')
print(y_train)
print('ay_train: ', y_train.shape)
print('y_test: ', y_test.shape)

# Test accuracy: 0.9983770855873811
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3), activation='relu', input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))

model.summary()

model.compile(loss=keras.losses.categorical_crossentropy,
              optimizer=keras.optimizers.Adadelta(),
              metrics=['accuracy'])

model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=epochs,
          verbose=1,
          validation_split=0.1)

model.save('model_cnn.h5')
print('model saved')

model = load_model('model_cnn.h5')
score = model.evaluate(x_test, y_test, verbose=0)

print('Test loss:', score[0])
print('Test accuracy:', score[1])

 

模型测试代码:

#keras 预测
import os
import utils
import keras

"""
测试数字识别
"""

root_path = r'D:\银行卡识别系统\CardIdentify-master1\data\test_images'
im_h = 46
w = 30

model = keras.models.load_model('model_cnn.h5')
model.summary()

files = os.listdir(root_path)
for file in files:
    im_path = os.path.join(root_path, file)
    im = utils.load_img(im_path)
    im = utils.rgb2gray_2(im)
    x = im.reshape(im.shape[0], im_h, w, 1)
    # x = im.reshape(im.shape[0], -1)     # 拉平矩阵
    print('label: ', file[:-4], '   digits: ', utils.img_2_digits(x, model))

 测试结果: