Tensorflow 进行图片分类

本贴最后更新于 1988 天前,其中的信息可能已经时过境迁

Tensorflow 进行图片分类

一、准备图片(最好分辨率一致,如果不一致,用以下脚本可处理成分辨率一致)

#按照指定图像大小调整尺寸 def resize_image(image, height = IMAGE_SIZE_WIDTH, width = IMAGE_SIZE_HEIGHT): top, bottom, left, right = (0, 0, 0, 0) #获取图像尺寸 h, w, _ = image.shape #对于长宽不相等的图片,找到最长的一边 longest_edge = max(h, w) #计算短边需要增加多上像素宽度使其与长边等长 if h < longest_edge: dh = longest_edge - h top = dh // 2 bottom = dh - top elif w < longest_edge: dw = longest_edge - w left = dw // 2 right = dw - left else: pass #RGB颜色 BLACK = [0, 0, 0] #给图像增加边界,是图片长、宽等长,cv2.BORDER_CONSTANT指定边界颜色由value指定 constant = cv2.copyMakeBorder(image, top , bottom, left, right, cv2.BORDER_CONSTANT, value = BLACK) #调整图像大小并返回 return cv2.resize(constant, (height, width))

二、图片读取(转成 tensorflow 能识别的格式)

PS:代码中的 GHHZZ、GHJK、GHQSZ 等是图片所在文件夹的名称,我将它转成数字存储在数组中
#读取训练数据 images = [] labels = [] def read_path(path_name): for dir_item in os.listdir(path_name): #从初始路径开始叠加,合并成可识别的操作路径 full_path = os.path.abspath(os.path.join(path_name, dir_item)) if os.path.isdir(full_path): #如果是文件夹,继续递归调用 read_path(full_path) else: #文件 if dir_item.lower().endswith('.jpg'): # try: # image = cv2.imread(full_path) # image = resize_image(image, IMAGE_SIZE, IMAGE_SIZE) # except Exception as e: # print('error_path:{0}'.format(full_path)) # break image = cv2.imread(full_path) image = resize_image(image, IMAGE_SIZE_WIDTH, IMAGE_SIZE_HEIGHT) #放开这个代码,可以看到resize_image()函数的实际调用效果 #cv2.imwrite('1.jpg', image) images.append(image) #labels.append(path_name) if path_name.endswith('GHHZZ'): labels.append(0) elif path_name.endswith('GHJK'): labels.append(1) elif path_name.endswith('GHQSZ'): labels.append(2) elif path_name.endswith('GHYBB'): labels.append(3) elif path_name.endswith('GHYKB'): labels.append(4) # elif path_name.endswith('GJJK'): # labels.append(6) # elif path_name.endswith('GJMWB'): # labels.append(7) # elif path_name.endswith('GJQSZ'): # labels.append(8) # elif path_name.endswith('GJQYC'): # labels.append(9) else: labels.append(0) return images,labels #从指定路径读取训练数据 def load_dataset(path_name): images,labels = read_path(path_name) #print(labels) #将输入的所有图片转成四维数组,尺寸为(图片数量*IMAGE_SIZE*IMAGE_SIZE*3) #图片为64 * 64像素,一个像素3个颜色值(RGB) images = np.array(images) print(images.shape) return images, labels if __name__ == '__main__': if len(sys.argv) != 1: print("Usage:%s path_name\r\n" % (sys.argv[0])) else: images, labels = load_dataset("./data")

三、准备图片识别 CNN 模型

# coding = utf-8 import numpy as np import tensorflow as tf from tensorflow import keras from load_data import load_dataset, resize_image, IMAGE_SIZE_WIDTH,IMAGE_SIZE_HEIGHT #CNN网络模型类 class Model: def __init__(self): self.model = None #建立模型 def build_model(self, dataset, nb_classes = 5): #构建一个空的网络模型,它是一个线性堆叠模型,各神经网络层会被顺序添加,专业名称为序贯模型或线性堆叠模型 self.model =tf.keras.Sequential() # 添加神经网络层 self.model.add(keras.layers.Convolution2D(filters=32, kernel_size=(3, 3),padding='same', activation='relu', input_shape = dataset.input_shape)) self.model.add(keras.layers.Convolution2D(filters=32, kernel_size=(3, 3), activation='relu')) self.model.add(keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2))) self.model.add(keras.layers.Dropout(0.25)) self.model.add(keras.layers.Convolution2D(filters=64, kernel_size=(3, 3),padding='same', activation='relu')) self.model.add(keras.layers.Convolution2D(filters=64, kernel_size=(3, 3), activation='relu')) self.model.add(keras.layers.MaxPooling2D(pool_size=(2, 2), strides=(2, 2))) self.model.add(keras.layers.Dropout(0.25)) self.model.add(keras.layers.Flatten()) self.model.add(keras.layers.Dense(512,activation='relu')) self.model.add(keras.layers.Dropout(0.5)) self.model.add(keras.layers.Dense(nb_classes,activation='softmax')) #输出模型概况 self.model.summary() #训练模型 def train(self, dataset, batch_size = 32, nb_epoch = 20, data_augmentation = True): # sgd =keras.optimizers.SGD(lr = 0.01, decay = 1e-6, # momentum = 0.9, nesterov = True) #采用SGD+momentum的优化器进行训练,首先生成一个优化器对象 adad= keras.optimizers.Adadelta(lr = 0.01,rho=0.95,epsilon=1e-08,decay = 1e-6) self.model.compile(loss='categorical_crossentropy', optimizer=adad, metrics=['accuracy']) #完成实际的模型配置工作 callbacks = [ # Interrupt training if `val_loss` stops improving for over 2 epochs keras.callbacks.EarlyStopping(patience=2, monitor='val_loss'), # Write TensorBoard logs to `./logs` directory keras.callbacks.TensorBoard(log_dir='./logs') ] #不使用数据提升,所谓的提升就是从我们提供的训练数据中利用旋转、翻转、加噪声等方法创造新的 #训练数据,有意识的提升训练数据规模,增加模型训练量 if not data_augmentation: self.model.fit(dataset.train_images, dataset.train_labels, batch_size = batch_size, nb_epoch = nb_epoch, validation_data = (dataset.valid_images, dataset.valid_labels), shuffle = True, callbacks=callbacks ) #使用实时数据提升 else: #定义数据生成器用于数据提升,其返回一个生成器对象datagen,datagen每被调用一 #次其生成一组数据(顺序生成),节省内存,其实就是python的数据生成器 datagen =keras.preprocessing.image.ImageDataGenerator( featurewise_center = False, #是否使输入数据去中心化(均值为0), samplewise_center = False, #是否使输入数据的每个样本均值为0 featurewise_std_normalization = False, #是否数据标准化(输入数据除以数据集的标准差) samplewise_std_normalization = False, #是否将每个样本数据除以自身的标准差 zca_whitening = False, #是否对输入数据施以ZCA白化 rotation_range = 20, #数据提升时图片随机转动的角度(范围为0~180) width_shift_range = 0.2, #数据提升时图片水平偏移的幅度(单位为图片宽度的占比,0~1之间的浮点数) height_shift_range = 0.2, #同上,只不过这里是垂直 horizontal_flip = True, #是否进行随机水平翻转 vertical_flip = False) #是否进行随机垂直翻转 #计算整个训练样本集的数量以用于特征值归一化、ZCA白化等处理 datagen.fit(dataset.train_images) #利用生成器开始训练模型 self.model.fit_generator(datagen.flow(dataset.train_images, dataset.train_labels, batch_size = batch_size), steps_per_epoch = dataset.train_images.shape[0]/batch_size, epochs = nb_epoch, validation_data = (dataset.valid_images, dataset.valid_labels), callbacks=callbacks) MODEL_PATH = './calvin.model.h5' def save_model(self, file_path = MODEL_PATH): self.model.save(file_path) def load_model(self, file_path = MODEL_PATH): self.model = keras.models.load_model(file_path) def evaluate(self, dataset): score = self.model.evaluate(dataset.test_images, dataset.test_labels, verbose = 1) print("%s: %.2f%%" % (self.model.metrics_names[1], score[1] * 100)) # def predict(self, image): #依然是根据后端系统确定维度顺序 if image.shape != (1, IMAGE_SIZE_WIDTH, IMAGE_SIZE_HEIGHT, 3): image = resize_image(image) image = image.reshape((1, IMAGE_SIZE_WIDTH, IMAGE_SIZE_HEIGHT, 3)) #浮点并归一化 image = image.astype('float32') image /= 255 #给出输入属于各个类别的概率,我们是二值类别,则该函数会给出输入图像属于0和1的概率各为多少 result = self.model.predict_proba(image) print('result:', result) #给出类别预测:0或者1 result = self.model.predict_classes(image) #返回类别预测结果 return result[0]

四、开启识别模式并随机取样验证数据集的准确性

import random from load_data import load_dataset, resize_image, IMAGE_SIZE_WIDTH,IMAGE_SIZE_HEIGHT from tf_dataset import Dataset from tf_model import Model if __name__ == '__main__': dataset = Dataset('./data/') dataset.load() model = Model() model.build_model(dataset) model.train(dataset) model.save_model(file_path = './model/calvin.model.h5') if __name__ == '__main__': dataset = Dataset('./data/') dataset.load() #评估模型 model = Model() model.load_model(file_path = './model/calvin.model.h5') model.evaluate(dataset)
  • Python

    Python 是一种面向对象、直译式电脑编程语言,具有近二十年的发展历史,成熟且稳定。它包含了一组完善而且容易理解的标准库,能够轻松完成很多常见的任务。它的语法简捷和清晰,尽量使用无异义的英语单词,与其它大多数程序设计语言使用大括号不一样,它使用缩进来定义语句块。

    557 引用 • 675 回帖
  • TensorFlow

    TensorFlow 是一个采用数据流图(data flow graphs),用于数值计算的开源软件库。节点(Nodes)在图中表示数学操作,图中的线(edges)则表示在节点间相互联系的多维数据数组,即张量(tensor)。

    20 引用 • 19 回帖 • 5 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...