牟晓东
通过对摄像头所捕获的画面内容进行处理和分析的图像识别,通常又称为“图像分类”任务。TensorFlow Lite 是深度神经网络图像识别解决方案中的一种,它提供了经过优化计算的若干预训练模型数据和标签文件,下载保存至本地后通过Python 编程调用即可实现画面内容的快速图像识别。
以Python 3.8 为例, 在本地安装对应版本的TensorFlow, 通过在WindowsPowerShell 窗口中执行“pipinstall tensorflow==2.3.1 -i https://pypi.tuna.tsinghua.edu.cn/simple” 命令来实现;然后下载预训练模型(mobilenet_v1_1.0_224_quant.tflite)和中英文标签文件(labels_mobilenet_quant_v1_224.txt、labels_mobilenet_quant_v1_224_cn_baidu.txt),两个txt 标签文件内容是一一对应的,分别保存了包括“背景”在内的1001 种常见的动植物和生活办公类物品,比如金鱼(goldfish)、鸵鸟(ostrich)和酒瓶(wine bottle)等等,每种物品名称均占单独的一行(如图1)。
(1)库模块的导入与标签文件的读取
首先,导入OpenCV、Numpy、tflite和PIL 库模块:“import cv2”“importnumpy as np”“import tflite_runtime.interpreter as tflite”“from PIL importImage,ImageFont,ImageDraw”; 接着, 建立变量file_model 和file_label,赋值为“mobilenet_v1_1.0_224_quant.t f lite”“la be ls_mobile n e t _qua n t _v1_224_cn_baidu.txt”, 分别对应分类模型和中文标签(如果想加载英文标签文件则将变量file_label 赋值为“labels_mobilenet_quant_v1_224.txt”);再进行标签文件的读取操作:“with open(file_label, 'r',encoding='utf-8') as f:labels =[line.strip() for line in f.readlines()]”。
(2)分类模型的加载预处理
建立变量Max_number 并赋值为3,作用是控制输出概率最高的分类结果数量为3 个;建立变量interpreter,赋值为“tflite.Interpreter(model_path=file_model)”,再通过语句“interpreter.allocate_tensors()” 進行分类模型的加载; 建立变量Input_Details 和Output_Details,分别赋值为“interpreter.get_input_details()” 和“interpreter.get_output_details()”,作用是实现输入数据和输出数据的读取; 此处可通过“print(Input_Details)” 和“print(Output_Details)”分别打印输出二者的具体信息,均是包含了“'shape':array([1,224,224,3])” 和“'quantization':(0.0078125,128)” 等数据在内的列表;建立变量height 和width,赋值为“Input_Details[0]['shape'][1]”和“Input_Details[0]['shape'][2]”,即从列表Input_Details 取出输入图像的高度和宽度值,均为224(通道数为3);建立变量cap,赋值为“cv2.VideoCapture(0)”,准备读取摄像头的画面数据(如图2)。
(3)“whileTrue:”循环体部分建立变量success 和img 并赋值为“capture.read()”, 进行摄像头一帧图像数据的读取; 建立变量img_rgb, 赋值为“cv2.cvtColor(img, cv2.COLOR_BGR2RGB)”, 进行颜色模式从BGR 到RGB 的转换; 建立变量img_resize, 赋值为“cv2.resize(img_rgb,(width,height))”,进行图像宽度与高度缩放;建立变量Input_Data,赋值为“np.expand_dims(img_resize,axis=0)”,作用是根据列表Input_Details 中的“'shape':array([1,224,224,3])” 内容格式增加一个维度;接着,通过语句“interpreter.set_tensor(Input_Details[0]['index'],Input_Data)”和“interpreter.invoke()”分别完成数据的输入并进行识别;建立变量Output,赋值为“np.squeeze(interpreter.get_tensor(Output_Details[0]['index'])[0])”,获取数据的输出;“if Output_Details[0]['dtype'] == np.uint8:”部分完成的功能是根据图像识别的量化对输出数据进行还原,并且找出数目为Max_number 个“ 最大值”: 建立变量Ordered, 赋值为“np.argpartition(-Output,Max_number-1)”。
在“for i in range(Max_number):”中进行Max_number 次循环,依次执行以下操作:建立变量Notes,赋值为“"%s:%.1f%%"%(labels[Ordered[i]],Output[Ordered[i]]*100)”, 其内容为待输出显示的文字信息内容;建立变量position,赋值为“(400,1+i*30)”,对应的是文字信息的起始坐标值; 建立变量img_PIL, 赋值为“Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))”,仍是进行颜色模式的转换;建立变量font,赋值为“ImageFont.truetype(r'C:\Windows\Fonts\Microsoft YaHei UI\msyhl.ttc',28,encoding="utf-8")”,作用是设置待显示文字信息的字体,可根据自己Windows 操作系统字体目录位置及内容来设置;建立变量draw 并赋值为“ImageDraw.Draw(img_PIL)”,作用是创建Draw 绘画对象,通过语句“draw.text(position,Notes,(0,255,0),font)”在图像上对应的位置用绿色添加文字信息;最后,仍是进行颜色模式转换、画面信息的显示、热键退出响应、摄像头资源的释放及窗口的关闭等操作(如图3)。
将程序保存为Recognize_image.py,按F5 键进行测试。先在摄像头前展示三张电脑屏幕图片,分别是大熊猫、金鱼和波斯猫,程序均正确进行了图像识别,各自的识别度分别是99.6%、99.6% 和84.4%;再来尝试识别一组实物,分别是螺丝刀、鼠标和两支圆珠笔,识别度也分别达到了97.3%、96.9% 和80.9%, 效果确实相当不错,而且识别的速度也非常快(如图4)。