牟曉東
通過對攝像頭所捕獲的畫面內(nèi)容進(jìn)行處理和分析的圖像識別,通常又稱為“圖像分類”任務(wù)。TensorFlow Lite 是深度神經(jīng)網(wǎng)絡(luò)圖像識別解決方案中的一種,它提供了經(jīng)過優(yōu)化計(jì)算的若干預(yù)訓(xùn)練模型數(shù)據(jù)和標(biāo)簽文件,下載保存至本地后通過Python 編程調(diào)用即可實(shí)現(xiàn)畫面內(nèi)容的快速圖像識別。
以Python 3.8 為例, 在本地安裝對應(yīng)版本的TensorFlow, 通過在WindowsPowerShell 窗口中執(zhí)行“pipinstall tensorflow==2.3.1 -i https://pypi.tuna.tsinghua.edu.cn/simple” 命令來實(shí)現(xiàn);然后下載預(yù)訓(xùn)練模型(mobilenet_v1_1.0_224_quant.tflite)和中英文標(biāo)簽文件(labels_mobilenet_quant_v1_224.txt、labels_mobilenet_quant_v1_224_cn_baidu.txt),兩個(gè)txt 標(biāo)簽文件內(nèi)容是一一對應(yīng)的,分別保存了包括“背景”在內(nèi)的1001 種常見的動(dòng)植物和生活辦公類物品,比如金魚(goldfish)、鴕鳥(ostrich)和酒瓶(wine bottle)等等,每種物品名稱均占單獨(dú)的一行(如圖1)。
(1)庫模塊的導(dǎo)入與標(biāo)簽文件的讀取
首先,導(dǎo)入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”“l(fā)a be ls_mobile n e t _qua n t _v1_224_cn_baidu.txt”, 分別對應(yīng)分類模型和中文標(biāo)簽(如果想加載英文標(biāo)簽文件則將變量file_label 賦值為“l(fā)abels_mobilenet_quant_v1_224.txt”);再進(jìn)行標(biāo)簽文件的讀取操作:“with open(file_label, 'r',encoding='utf-8') as f:labels =[line.strip() for line in f.readlines()]”。
(2)分類模型的加載預(yù)處理
建立變量Max_number 并賦值為3,作用是控制輸出概率最高的分類結(jié)果數(shù)量為3 個(gè);建立變量interpreter,賦值為“tflite.Interpreter(model_path=file_model)”,再通過語句“interpreter.allocate_tensors()” 進(jìn)行分類模型的加載; 建立變量Input_Details 和Output_Details,分別賦值為“interpreter.get_input_details()” 和“interpreter.get_output_details()”,作用是實(shí)現(xiàn)輸入數(shù)據(jù)和輸出數(shù)據(jù)的讀取; 此處可通過“print(Input_Details)” 和“print(Output_Details)”分別打印輸出二者的具體信息,均是包含了“'shape':array([1,224,224,3])” 和“'quantization':(0.0078125,128)” 等數(shù)據(jù)在內(nèi)的列表;建立變量height 和width,賦值為“Input_Details[0]['shape'][1]”和“Input_Details[0]['shape'][2]”,即從列表Input_Details 取出輸入圖像的高度和寬度值,均為224(通道數(shù)為3);建立變量cap,賦值為“cv2.VideoCapture(0)”,準(zhǔn)備讀取攝像頭的畫面數(shù)據(jù)(如圖2)。
(3)“whileTrue:”循環(huán)體部分建立變量success 和img 并賦值為“capture.read()”, 進(jìn)行攝像頭一幀圖像數(shù)據(jù)的讀??; 建立變量img_rgb, 賦值為“cv2.cvtColor(img, cv2.COLOR_BGR2RGB)”, 進(jìn)行顏色模式從BGR 到RGB 的轉(zhuǎn)換; 建立變量img_resize, 賦值為“cv2.resize(img_rgb,(width,height))”,進(jìn)行圖像寬度與高度縮放;建立變量Input_Data,賦值為“np.expand_dims(img_resize,axis=0)”,作用是根據(jù)列表Input_Details 中的“'shape':array([1,224,224,3])” 內(nèi)容格式增加一個(gè)維度;接著,通過語句“interpreter.set_tensor(Input_Details[0]['index'],Input_Data)”和“interpreter.invoke()”分別完成數(shù)據(jù)的輸入并進(jìn)行識別;建立變量Output,賦值為“np.squeeze(interpreter.get_tensor(Output_Details[0]['index'])[0])”,獲取數(shù)據(jù)的輸出;“if Output_Details[0]['dtype'] == np.uint8:”部分完成的功能是根據(jù)圖像識別的量化對輸出數(shù)據(jù)進(jìn)行還原,并且找出數(shù)目為Max_number 個(gè)“ 最大值”: 建立變量Ordered, 賦值為“np.argpartition(-Output,Max_number-1)”。
在“for i in range(Max_number):”中進(jìn)行Max_number 次循環(huán),依次執(zhí)行以下操作:建立變量Notes,賦值為“"%s:%.1f%%"%(labels[Ordered[i]],Output[Ordered[i]]*100)”, 其內(nèi)容為待輸出顯示的文字信息內(nèi)容;建立變量position,賦值為“(400,1+i*30)”,對應(yīng)的是文字信息的起始坐標(biāo)值; 建立變量img_PIL, 賦值為“Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))”,仍是進(jìn)行顏色模式的轉(zhuǎn)換;建立變量font,賦值為“ImageFont.truetype(r'C:\Windows\Fonts\Microsoft YaHei UI\msyhl.ttc',28,encoding="utf-8")”,作用是設(shè)置待顯示文字信息的字體,可根據(jù)自己Windows 操作系統(tǒng)字體目錄位置及內(nèi)容來設(shè)置;建立變量draw 并賦值為“ImageDraw.Draw(img_PIL)”,作用是創(chuàng)建Draw 繪畫對象,通過語句“draw.text(position,Notes,(0,255,0),font)”在圖像上對應(yīng)的位置用綠色添加文字信息;最后,仍是進(jìn)行顏色模式轉(zhuǎn)換、畫面信息的顯示、熱鍵退出響應(yīng)、攝像頭資源的釋放及窗口的關(guān)閉等操作(如圖3)。
將程序保存為Recognize_image.py,按F5 鍵進(jìn)行測試。先在攝像頭前展示三張電腦屏幕圖片,分別是大熊貓、金魚和波斯貓,程序均正確進(jìn)行了圖像識別,各自的識別度分別是99.6%、99.6% 和84.4%;再來嘗試識別一組實(shí)物,分別是螺絲刀、鼠標(biāo)和兩支圓珠筆,識別度也分別達(dá)到了97.3%、96.9% 和80.9%, 效果確實(shí)相當(dāng)不錯(cuò),而且識別的速度也非??欤ㄈ鐖D4)。