利用深度學習手把手教你實現一個「以圖搜圖」

文中源碼可在微信公衆號「01二進制」後臺回覆「圖像檢索」獲取。

前言

在上一篇文章《圖像檢索系列——利用 Python 檢測圖像類似度》中,咱們介紹了一個在圖像檢索領域很是經常使用的算法——感知哈希算法。這是一個很簡單且快速的算法,其原理在於針對每一張圖片都生成一個特定的「指紋」,而後採起一種類似度的度量方式得出兩張圖片的近似程度。html

然而隨着深度學習的崛起,極大的推進了圖像領域的發展,在提取特徵這方面而言,神經網絡目前有着不可替代的優點。在上一篇文章中咱們也介紹了圖像檢索每每是基於圖像的特徵比較,看特徵匹配的程度有多少,從而檢索出類似度高的圖片。而檢測圖像特徵,VGG16具備得天獨厚的優點。python

接下來本文將會經過一個簡單的案例來實現一個基於深度學習的圖像檢索小工具。git

準備工做

老樣子,先來準備好咱們這次須要使用到的工具:github

  • IDE:Pycharm
  • Python:3.7
  • Packages:Keras + TensorFlow + Pillow + Numpy

kerasweb

Keras是一個高層神經網絡API,Keras由純Python編寫而成並基TensorflowTheano以及CNTK後端。簡單來講,keras就是對TF等框架的再一次封裝,使得使用起來更加方便。算法

基於vgg16網絡提取圖像特徵
咱們都知道,vgg網絡在圖像領域有着普遍的應用,後續許多層次更深,網絡更寬的模型都是基於此擴展的,vgg網絡能很好的提取到圖片的有用特徵,本次實現是基於Keras實現的,提取的是最後一層卷積特徵。數據庫

思路

主要思路是基於CVPR2015的論文《Deep Learning of Binary Hash Codes for Fast Image Retrieval》實現的海量數據下的基於內容圖片檢索系統。簡單說來就是對圖片數據庫的每張圖片抽取特徵(通常形式爲特徵向量),存儲於數據庫中,對於待檢索圖片,抽取一樣的特徵向量,而後並對該向量和數據庫中向量的距離(類似度計算),找出最接近的一些特徵向量,其對應的圖片即爲檢索結果。以下圖所示:後端

用戶請求和預處理部分主要是Web服務端應該作的,這裏不加以討論,接下來咱們主要進行紅線標註部分的實現。數組

實操

提取圖片特徵

keras在其中文文檔中提供了一個利用VGG16提取特徵的demo微信

from keras.applications.vgg16 import VGG16
from keras.preprocessing import image
from keras.applications.vgg16 import preprocess_input
import numpy as np

model = VGG16(weights='imagenet', include_top=False)

img_path = 'elephant.jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

features = model.predict(x)

這裏咱們須要對其進行簡單修改,封裝成一個類以便後期調用。以下圖所示:

考慮到篇幅,文中代碼圖片已刪除較多註釋,如需瞭解詳細註釋信息,可在微信公衆號「01二進制」後臺回覆「圖像檢索」獲取源代碼。下同

將特徵以及對應的文件名保存爲h5文件

什麼是 h5 文件

h5文件是層次數據格式第5代的版本(Hierarchical Data Format,HDF5),用以存儲和組織大規模數據。

H5將文件結構簡化成兩個主要的對象類型:

  1. 數據集dataset,就是同一類型數據的多維數組
  2. 組group,是一種容器結構,能夠包含數據集和其餘組,若一個文件中存放了不一樣種類的數據集,這些數據集的管理就用到了group

直觀的理解,能夠參考咱們的文件系統,不一樣的文件存放在不一樣的目錄下:

目錄就是 hdf5 文件中的 group,描述了數據集 DataSet 的分類信息,經過 group 有效的將多種 dataset 進行管理和劃分。文件就是 hdf5 文件中的 dataset,表示具體的數據

下圖就是數據集和組的關係:

在 Python 中,咱們一般使用 h5py 庫對 .h5 文件進行操做,具體的讀寫方法自行百度,這裏不在演示。

抽取數據集中的圖像特徵保存到 h5 文件中

咱們在項目根目錄下命名一個database文件夾做爲數據集,而後編寫一個獲取文件夾內圖片的方法:

def get_imlist(path):
    return [os.path.join(path, f) for f in os.listdir(path) if f.endswith('.jpg')]

隨後咱們即可以依次讀取數據而後,一一提取其特徵保存到文件中了。以下圖:

至此,咱們就已經算是完成了模型的訓練了。

選一張測試圖片測試檢索效果

通過上述操做,咱們已經將數據集中的全部圖片的特徵保存到模型中了,剩下的就是抽取待測圖片的特徵,而後和特徵集中的特徵一一比較向量間的類似度(餘弦類似度),而後按照類似度排序返回給用戶便可。

Tips:各類類似度的 Python 表示能夠參考 Python Numpy計算各種距離

以某一個包包爲測試圖片,輸出結果以下所示:

在PyCharm中能夠很方便的查看matplotlib生成的圖片,第一張爲測試圖片,後面三張爲檢索圖片,能夠看出效果至關好了。

Tips:若是想用Resnet或者Densenet提取特徵,只需針對上述代碼作出相應的修改,去掉註釋修改部分代碼便可。詳見源碼。

最後

至此咱們已經利用深度學習實現了一個圖片檢索的小工具了,如何將其和web/app結合到一塊兒就不在本文的討論範圍了,有興趣能夠下載本文源碼自行更改,也可掃描下方二維碼關注微信公衆號「01二進制」與我取得聯繫。

參考

  1. 深度學習與計算機視覺(11)_基於deep learning的快速圖像檢索系統
  2. 基於VGG-16的海量圖像檢索系統(以圖搜圖升級版)
  3. 基於深度學習實現以圖搜圖功能
  4. 各類類似度計算的python實現
  5. Application應用
  6. Python Numpy計算各種距離
  7. h5文件簡介
相關文章
相關標籤/搜索