王新民編譯自DeepLearningSandbox博客
量子位出品|公眾號QbitAI
在計算機視覺領域裡,有3個最受歡迎且影響非常大的學術競賽:ImageNetILSVRC(大規模視覺識別挑戰賽),PASCALVOC(關於模式分析,統計建模和計算學習的研究)和微軟COCO圖像識別大賽。這些比賽大大地推動了在計算機視覺研究中的多項發明和創新,其中很多都是免費開源的。
博客DeepLearningSandbox作者GregChu打算通過一篇文章,教你用Keras和TensorFlow,實現對ImageNet數據集中日常物體的識別。
量子位翻譯了這篇文章:
你想識別什麼?
看看ILSVRC競賽中包含的物體對象。如果你要研究的物體對象是該列表1001個對象中的一個,運氣真好,可以獲得大量該類別圖像數據!以下是這個數據集包含的部分類別:
狗
熊
椅子
汽車
鍵盤
箱子
嬰兒床
旗杆
iPod播放器
輪船
麵包車
項鍊
降落傘
枕頭
桌子
錢包
球拍
步槍
校車
薩克斯管
足球
襪子
舞臺
火爐
火把
吸塵器
自動售貨機
眼鏡
紅綠燈
菜餚
盤子
西蘭花
紅酒
△表1ImageNetILSVRC的類別摘錄
完整類別列表見:https://gist.github.com/gregchu/134677e041cd78639fea84e3e619415b
如果你研究的物體對象不在該列表中,或者像醫學圖像分析中具有多種差異較大的背景,遇到這些情況該怎麼辦?可以藉助遷移學習(transferlearning)和微調(fine-tuning),我們以後再另外寫文章講。
圖像識別
圖像識別,或者說物體識別是什麼?它回答了一個問題:「這張圖像中描繪了哪幾個物體對象?」如果你研究的是基於圖像內容進行標記,確定盤子上的食物類型,對癌症患者或非癌症患者的醫學圖像進行分類,以及更多的實際應用,那麼就能用到圖像識別。
Keras和TensorFlow
Keras是一個高級神經網絡庫,能夠作為一種簡單好用的抽象層,接入到數值計算庫TensorFlow中。另外,它可以通過其keras.applications模塊獲取在ILSVRC競賽中獲勝的多個卷積網絡模型,如由MicrosoftResearch開發的ResNet50網絡和由GoogleResearch開發的InceptionV3網絡,這一切都是免費和開源的。具體安裝參照以下說明進行操作:
Keras安裝:https://keras.io/#installation
TensorFlow安裝:https://www.tensorflow.org/install/
實現過程
我們的最終目標是編寫一個簡單的python程序,只需要輸入本地圖像文件的路徑或是圖像的URL連結就能實現物體識別。
以下是輸入非洲大象照片的示例:
1.pythonclassify.py--imageAfrican_Bush_Elephant.jpg2.pythonclassify.py--image_urlhttp://i.imgur.com/wpxMwsR.jpg
想了解ResNet50的原理,可以閱讀論文《基於深度殘差網絡的圖像識別》。地址:https://arxiv.org/pdf/1512.03385.pdf
importnumpyasnpfromkeras.preprocessingimportimagefromkeras.applications.resnet50importResNet50,preprocess_input,decode_predictionsmodel=ResNet50(weights='imagenet')
接下來定義一個預測函數:
defpredict(model,img,target_size,top_n=3):"""RunmodelpredictiononimageArgs:model:kerasmodelimg:PILformatimagetarget_size:(width,height)tupletop_n:#oftoppredictionstoreturnReturns:listofpredictedlabelsandtheirprobabilities"""ifimg.size!=target_size:img=img.resize(target_size)x=image.img_to_array(img)x=np.expand_dims(x,axis=0)x=preprocess_input(x)preds=model.predict(x)returndecode_predictions(preds,top=top_n)[0]
在使用ResNet50網絡結構時需要注意,輸入大小target_size必須等於(224,224)。許多CNN網絡結構具有固定的輸入大小,ResNet50正是其中之一,作者將輸入大小定為。
image.img_to_array:將PIL格式的圖像轉換為numpy數組。
np.expand_dims:將我們的(3,224,224)大小的圖像轉換為(1,3,224,224)。因為model.predict函數需要4維數組作為輸入,其中第4維為每批預測圖像的數量。這也就是說,我們可以一次性分類多個圖像。
preprocess_input:使用訓練數據集中的平均通道值對圖像數據進行零值處理,即使得圖像所有點的和為0。這是非常重要的步驟,如果跳過,將大大影響實際預測效果。這個步驟稱為數據歸一化。
:對我們的數據分批處理並返回預測值。
decode_predictions:採用與函數相同的編碼標籤,並從ImageNetILSVRC集返回可讀的標籤。
模塊還提供4種結構:ResNet50、InceptionV3、VGG16、VGG19和XCeption,你可以用其中任何一種替換ResNet50。更多信息可以參考https://keras.io/applications/。
繪圖
我們可以使用matplotlib函數庫將預測結果做成柱狀圖,如下所示:
defplot_preds(image,preds):"""Displaysimageandthetop-npredictedprobabilitiesinabargraphArgs:image:PILimagepreds:listofpredictedlabelsandtheirprobabilities"""#imageplt.imshow(image)plt.axis('off')#bargraphplt.figure()order=list(reversed(range(len(preds))))bar_preds=[pr[2]forprinpreds]labels=(pr[1]forprinpreds)plt.barh(order,bar_preds,alpha=0.5)plt.yticks(order,labels)plt.xlabel('Probability')plt.xlim(0,1.01)plt.tight_layout()plt.show()
主體部分
為了實現以下從網絡中加載圖片的功能:
我們將定義主函數如下:
if__name__=="__main__":a=argparse.ArgumentParser()a.add_argument("--image",help="pathtoimage")a.add_argument("--image_url",help="urltoimage")args=a.parse_args()ifargs.imageisNoneandargs.image_urlisNone:a.print_help()sys.exit(1)ifargs.imageisnotNone:img=Image.open(args.image)print_preds(predict(model,img,target_size))ifargs.image_urlisnotNone:response=requests.get(args.image_url)img=Image.open(BytesIO(response.content))print_preds(predict(model,img,target_size))
其中在寫入image_url功能後,用python中的Requests庫就能很容易地從URL連結中下載圖像。
完工
將上述代碼組合起來,你就創建了一個圖像識別系統。項目的完整程序和示例圖像請查看GitHub連結:
招聘