卷积神经网络(Convolutional Neural Networks, CNN)是深度学习的常见算法,具有强大的特征提取功能,不需要做特征工程就可以运用到图像分类这类操作中。
本文主要讲一下用CNN做图像分类的一些较为简单的实践。
这类操作主要是基于一个预先训练好的模型进行微调和重训练。
-
在线服务
微软的Azure Custom Vision提供用户自行训练图像分类模型的功能,只需上传图片并标上分类即可,能够提供多种格式的模型供下载。百度、谷歌等公司也有类似的服务。
-
Tensorflow提供的图像分类工具
Tensorflow提供了一个能基于预训练模型进行重训练的脚本:https://github.com/tensorflow/hub/blob/master/examples/image_retraining/retrain.py,只需提供图像即可完成训练,不用写代码,预训练模型可以使用inception v3,或者准确率相对较低但运行更快的mobilenet。
目前这个脚本已经有了针对tensorflow 2.0的更新版本:make_image_classifier.py
通过以下命令即可完成在几分钟内完成训练:
$ make_image_classifier \ --image_dir my_image dir \ --tfhub_module https://tfhub.dev/google/tf2-preview/mobilenet_v2/feature_vector/4 \ --image_size 224 \ --saved_model_dir my_dir/new_model \ --labels_output_file class_labels.txt \ --tflite_output_file new_mobile_model.tflite
下面讲下参数。
--image_dir
,存放训练图像的目录,结构如下:my image_dir |-- cat | |-- a_feline_photo.jpg | |-- another_cat_pic.jpg | `-- ... |-- dog | |-- PuppyInBasket.JPG | |-- walking_the_dog.jpeg | `-- ... `-- rabbit |-- IMG87654321.JPG |-- my_fluffy_rabbit.JPEG `-- ...
--tfhub_module
,指定使用的预训练模型,可以在tfhub上搜索到可以用的各种模型。--image_size
,图像会被缩放以满足模型的输入要求,这个参数应该和预训练模型的吻合。--saved_model_dir
,将模型保存为Tensorflow Savedmodel格式,可以用于Tensorflow Serving服务器。--tflite_output_file
,将模型保存为Tensorflow Lite格式。我用它训练了一个文字图像识别器,主要有两个类别:文字图像、非文字图像。因为有的文字图像并不是规则的正方形,还需要进行适当的裁剪。
下面是调用生成的Tensorflow Lite模型进行识别的Python脚本。
"""label_image for tflite.""" from __future__ import absolute_import from __future__ import division from __future__ import print_function import cv2 import argparse import numpy as np import tensorflow as tf # TF2 def imgData(filename,new_size): image = cv2.imread(filename) h=image.shape[0] w=image.shape[1] centerX=int(w/2) centerY=int(h/2) if h/w>1.5: image=image[int(centerY-w/2):int(centerY+w/2)] if w/h>1.5: image=image[:,int(centerX-h/2):int(centerX+h/2)] data=cv2.resize(image, new_size, interpolation = cv2.INTER_LINEAR) input_data=data[np.newaxis,:,:,:] return input_data def load_labels(filename): with open(filename, 'r') as f: return [line.strip() for line in f.readlines()] if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument( '-i', '--image', default='/tmp/grace_hopper.bmp', help='image to be classified') parser.add_argument( '-m', '--model_file', default='/tmp/mobilenet_v1_1.0_224_quant.tflite', help='.tflite model to be executed') parser.add_argument( '-l', '--label_file', default='/tmp/labels.txt', help='name of file containing labels') parser.add_argument( '--input_mean', default=127.5, type=float, help='input_mean') parser.add_argument( '--input_std', default=127.5, type=float, help='input standard deviation') args = parser.parse_args() interpreter = tf.lite.Interpreter(model_path=args.model_file) interpreter.allocate_tensors() input_details = interpreter.get_input_details() output_details = interpreter.get_output_details() # check the type of the input tensor floating_model = input_details[0]['dtype'] == np.float32 # NxHxWxC, H:1, W:2 height = input_details[0]['shape'][1] width = input_details[0]['shape'][2] new_size = (height, width) input_data=imgData(args.image,new_size) if floating_model: input_data = (np.float32(input_data) - args.input_mean) / args.input_std interpreter.set_tensor(input_details[0]['index'], input_data) interpreter.invoke() output_data = interpreter.get_tensor(output_details[0]['index']) results = np.squeeze(output_data) top_k = results.argsort()[-5:][::-1] labels = load_labels(args.label_file) for i in top_k: if floating_model: print('{:08.6f}: {}'.format(float(results[i]), labels[i])) else: print('{:08.6f}: {}'.format(float(results[i] / 255.0), labels[i]))
用法:
python label_image.py \ --input_mean 0 --input_std 255 \ --model_file new_mobile_model.tflite --label_file class_labels.txt \ --image my_image_dir/cat/a_feline_photo.jpg
其它
我写的基于bottle的服务器脚本:https://github.com/xulihang/text-image-classifier
训练好的文字图像识别模型:https://pan.baidu.com/s/1AqWvsFIPnr4KVGuAAsnsYA