使用 Python 構(gòu)建圖片搜索引擎
點擊上方“小白學視覺”,選擇加"星標"或“置頂”
重磅干貨,第一時間送達
本文轉(zhuǎn)自:AI算法與圖像處理
我們經(jīng)常使用搜索引擎。當我們需要查詢時,我們可以使用像 Google 這樣的搜索引擎來檢索最相關(guān)的答案。
大多數(shù)查詢格式是基于文本的。但并不是大多數(shù)時候,文本對于找到相關(guān)的答案是非常有用的。
例如,你想在互聯(lián)網(wǎng)上搜索一個產(chǎn)品,在這種情況下,是一件 t 恤,但你不知道它的名字。你怎么能找到他們?你可以把那件襯衫的描述寫下來。
使用描述的問題是你會得到各種各樣的產(chǎn)品。更糟糕的是,它們與你想要搜索的產(chǎn)品并不相似,所以你需要一個更好的方法來檢索它們。
為了解決這個問題,我們可以使用產(chǎn)品的圖像,提取其特征,并利用這些特征檢索相似的產(chǎn)品。我們稱這個概念為基于內(nèi)容的圖像檢索。
在本文中,我將向您展示如何使用 Python 構(gòu)建圖像搜索引擎。
基于內(nèi)容的圖像檢索
在我向您解釋如何使用 Python 構(gòu)建圖像檢索之前,讓我向您解釋基于內(nèi)容的圖像檢索的概念。
基于內(nèi)容的圖像檢索(CBIR)是一種基于給定圖像的相關(guān)圖像檢索系統(tǒng)。該系統(tǒng)由圖像查詢和圖像數(shù)據(jù)庫兩部分組成。
該系統(tǒng)首先對所有圖像進行特征提取,無論是查詢圖像還是圖像數(shù)據(jù)庫圖像,使用特征提取算法。然后,系統(tǒng)將計算查詢與數(shù)據(jù)庫中所有圖像之間的相似性。最后,系統(tǒng)將檢索所有與查詢有很大相似性的圖像。
圖1描述了 CBIR 的流程。

圖一 CBIR 的流程
卷積神經(jīng)網(wǎng)絡(luò)
要提取特征,有許多選項可供選擇。在這種情況下,我們可以使用卷積神經(jīng)網(wǎng)絡(luò)(CNN)來提取這些特征。
由于該模型的卷積層能夠捕獲每個數(shù)據(jù)實例的特征,因此它比其他算法具有更強的模式捕獲能力。
卷積神經(jīng)網(wǎng)絡(luò)由很多層網(wǎng)絡(luò)組成,例如卷積層用于特征提取,池層用于特征采樣,完全連接層用于預(yù)測。
在這種情況下,我們忽略了大部分的完全連接層,只關(guān)注特征提取的結(jié)果。
圖2顯示了卷積神經(jīng)網(wǎng)絡(luò)架構(gòu)的示例,即 LeNet-5。

圖2. LeNet-5架構(gòu)
歐幾里得度量
提取特征后,計算查詢與所有圖像之間的距離。為了做到這一點,我們可以使用歐幾里得度量或 l 2標準來衡量它。如果數(shù)字越來越小,那么這一對圖像就是相似的。公式是這樣的:

其中:
q = 待查詢圖像
img = 圖像
n = 特征向量元素的個數(shù)
i = 矢量的位置
在我們知道了這些概念之后,現(xiàn)在我們可以實現(xiàn)這個系統(tǒng)了。為了實現(xiàn) CBIR,我們將使用 Python 作為編程語言,Tensorflow 用于特征提取框架,Numpy 用于計算距離。如果我們總結(jié)一下,這里是我們將要做的步驟:
下載數(shù)據(jù)集
從圖像數(shù)據(jù)庫中提取特征
插入查詢圖像并提取其特征
計算所有圖像的相似性
檢索最相似的結(jié)果
對于數(shù)據(jù)集,我們將使用來自 Kaggle 的 CBIR 數(shù)據(jù)集。你可以通過這里的鏈接訪問數(shù)據(jù)集:https://www.kaggle.com/theaayushbajaj/cbir-dataset/notebooks。

Figure 3. Screenshot by me 圖3. 我的屏幕截圖
在我們檢索所有的圖像之后,現(xiàn)在我們可以使用 CNN 從所有的圖像中提取特征并將這些特征保存在 .npy 格式的文件中以供日后使用。為了指定體系結(jié)構(gòu),我們將使用 VGG-16體系結(jié)構(gòu)和來自 ImageNet 的預(yù)先訓練的權(quán)重。
另外,我們可以利用 GPU 提取圖像的特征,但是在這種情況下,我們只使用 CPU。
代碼是這樣的:
# Import the librariesfrom tensorflow.keras.preprocessing import imagefrom tensorflow.keras.applications.vgg16 import VGG16, preprocess_inputfrom tensorflow.keras.models import Modelfrom pathlib import Pathfrom PIL import Imageclass FeatureExtractor:def __init__(self):# Use VGG-16 as the architecture and ImageNet for the weightbase_model = VGG16(weights='imagenet')# Customize the model to return features from fully-connected layerself.model = Model(inputs=base_model.input, outputs=base_model.get_layer('fc1').output) def extract(self, img):# Resize the imageimg = img.resize((224, 224))# Convert the image color spaceimg = img.convert('RGB')# Reformat the imagex = image.img_to_array(img)x = np.expand_dims(x, axis=0)x = preprocess_input(x)# Extract Featuresfeature = self.model.predict(x)[0]return feature / np.linalg.norm(feature)# Iterate through images (Change the path based on your image location)for img_path in sorted("<IMAGE DATABASE PATH LIST HERE>"):print(img_path)# Extract Featuresfeature = fe.extract(img=Image.open(img_path))# Save the Numpy array (.npy) on designated pathfeature_path = "<IMAGE FEATURE PATH HERE>.npy"np.save(feature_path, feature)
在我們從所有圖像中提取特征之后,現(xiàn)在我們可以嘗試使用查詢檢索類似的圖像。在這種情況下,我們可以輸入一張看起來類似下圖的獅子:

為了檢索類似的圖像,我們使用如下代碼:
# Import the librariesimport matplotlib.pyplot as pltimport numpy as np# Insert the image queryimg = Image.open("<IMAGE QUERY PATH HERE>")# Extract its featuresquery = fe.extract(img)# Calculate the similarity (distance) between imagesdists = np.linalg.norm(features - query, axis=1)# Extract 30 images that have lowest distanceids = np.argsort(dists)[:30]scores = [(dists[id], img_paths[id]) for id in ids]# Visualize the resultaxes=[]fig=plt.figure(figsize=(8,8))for a in range(5*6):score = scores[a]axes.append(fig.add_subplot(5, 6, a+1))subplot_title=str(score[0])axes[-1].set_title(subplot_title)plt.axis('off')plt.imshow(Image.open(score[1]))fig.tight_layout()plt.show()
最終的結(jié)果如下:


總結(jié)
祝賀你!你已經(jīng)創(chuàng)建了自己的圖片搜索引擎。好吧,這并不是非常類似于谷歌,但至少你知道的概念,如何基于內(nèi)容的圖像檢索工作。
如果你對 web 開發(fā)有所了解,也許你可以使用 Flask 或 Django 這樣的框架創(chuàng)建一個 web 應(yīng)用程序來構(gòu)建你自己的搜索引擎。
交流群
歡迎加入公眾號讀者群一起和同行交流,目前有SLAM、三維視覺、傳感器、自動駕駛、計算攝影、檢測、分割、識別、醫(yī)學影像、GAN、算法競賽等微信群(以后會逐漸細分),請掃描下面微信號加群,備注:”昵稱+學校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺SLAM“。請按照格式備注,否則不予通過。添加成功后會根據(jù)研究方向邀請進入相關(guān)微信群。請勿在群內(nèi)發(fā)送廣告,否則會請出群,謝謝理解~

