OpenCV特徵提取與影像檢索實現(附程式碼)
翻譯 | AI科技大本營(ID:rgznai100)
參與 | 張蔚敏
審校 | reason_W
“拍立淘”“一鍵識花”“街景匹配”……不知道大家在使用這些神奇的功能的時候,有沒有好奇過它們背後的技術原理?其實這些技術都離不開最基本的影像檢索技術。本篇文章我們就將對這一技術的原理進行介紹,並通過一個簡單的Python指令碼來實現一個最基本的影像檢索demo。
▌影像特徵
首先我們需要明白影像特徵是什麼以及它的使用方法。
影像特徵是一種簡單的影像模式,基於這種模式我們可以描述我們在影像上所看到的內容。 例如,在一張跟貓有關的圖片中,貓咪的眼睛就可以作為這幅影像的特徵。特徵在(包括但不限於)計算機視覺中的主要作用是將視覺資訊轉換為向量空間表示。這種向量空間表示讓我們可以利用數學運算對其進行處理,例如通過計算尋找相似向量(這可以用來尋找相似影像或影像中的相似目標)。
▌如何從影像中獲取特徵?
從影像中獲取特徵的方法有兩種,第一種是通過提取影像描述符實現(白盒演算法);第二種通過基於神經網路的方法實現(黑盒演算法)。本文主要介紹第一種方法。
特徵提取的演算法有很多,最常用的有:SURF、ORB、SIFT、BRIEF等。這些演算法大多是基於影像梯度的。為了簡化安裝需求,本教程使用的是KAZE描述符,因為其他描述符在python的基礎OpenCV庫中沒有提供。
下面是特徵提取器的實現程式碼:
import cv2
import numpy as np
import scipy
from scipy.misc import imread
import cPickle as pickle
import random
import os
import matplotlib.pyplot as plt
# Feature extractor
# 特徵提取器
def extract_features(image_path, vector_size=32):
image = imread(image_path, mode="RGB")
try:
# Using KAZE, cause SIFT, ORB and other was moved to additional module
# which is adding addtional pain during install
#此處為了簡化安裝步驟,使用KAZE,因為SIFT/ORB以及其他特徵運算元需要安
#裝額外的模組
alg = cv2.KAZE_create()
# Finding image keypoints
#尋找影像關鍵點
kps = alg.detect(image)
# Getting first 32 of them.
#計算前32個
# Number of keypoints is varies depend on image size and color pallet
#關鍵點的數量取決於影像大小以及彩色調色盤
# Sorting them based on keypoint response value(bigger is better)
#根據關鍵點的返回值進行排序(越大越好)
kps = sorted(kps, key=lambda x: -x.response)[:vector_size]
# computing descriptors vector
#計算描述符向量
kps, dsc = alg.compute(image, kps)
# Flatten all of them in one big vector - our feature vector
# 將其放在一個大的向量中,作為我們的特徵向量
dsc = dsc.flatten()
# Making descriptor of same size
# 使描述符的大小一致
# Descriptor vector size is 64
#描述符向量的大小為64
needed_size = (vector_size * 64)
if dsc.size < needed_size:
# if we have less the 32 descriptors then just adding zeros
# at the end of our feature vector
#如果少於32個描述符,則在特徵向量後面補零
dsc = np.concatenate([dsc, np.zeros(needed_size - dsc.size)])
except cv2.error as e:
print 'Error: ', e
return None
return dsc
def batch_extractor(images_path, pickled_db_path="features.pck"):
files = [os.path.join(images_path, p) for p in sorted(os.listdir(images_path))]
result = {}
for f in files:
print 'Extracting features from image %s' % f
name = f.split('/')[-1].lower()
result[name] = extract_features(f)
# saving all our feature vectors in pickled file
# 將特徵向量存於pickled 檔案
with open(pickled_db_path, 'w') as fp:
pickle.dump(result, fp)
OpenCV中的大多數特徵提取演算法的python介面都相同,所以如果你想要使用SIFT特徵,只需要用SIFT_create替換KAZE_create就行。
首先,程式會用extract_features檢測影像上的關鍵點(區域性模式的中心點)。 因為關鍵點數量隨影像的不同有所不同,因此我們需要新增一些規則,以確保所得到的特徵向量大小始終相同(這是因為在計算時,我們無法對維度不同的向量進行比較,所以必須保證相同的大小)。
然後是根據關鍵點構建向量描述符,每個描述符的大小為64,我們有32個這樣的描述符,所以我們的特徵向量是2048維。
batch_extractor是在所有的影像中批量執行特徵提取器,並將特徵向量儲存在pickled檔案中以供後續使用。
現在我們來建立類Matcher,它會將待搜尋影像和資料庫中的影像進行匹配。
class Matcher(object):
def __init__(self, pickled_db_path="features.pck"):
with open(pickled_db_path) as fp:
self.data = pickle.load(fp)
self.names = []
self.matrix = []
for k, v in self.data.iteritems():
self.names.append(k)
self.matrix.append(v)
self.matrix = np.array(self.matrix)
self.names = np.array(self.names)
def cos_cdist(self, vector):
# getting cosine distance between search image and images database
#計算待搜尋影像與資料庫影像的餘弦距離
v = vector.reshape(1, -1)
return scipy.spatial.distance.cdist(self.matrix, v, 'cosine').reshape(-1)
def match(self, image_path, topn=5):
features = extract_features(image_path)
img_distances = self.cos_cdist(features)
# getting top 5 records
# 獲得前5個記錄
nearest_ids = np.argsort(img_distances)[:topn].tolist()
nearest_img_paths = self.names[nearest_ids].tolist()
return nearest_img_paths, img_distances[nearest_ids].tolist()
這裡要載入前一步得到的特徵向量,並從它們中建立一個大矩陣,然後計算待搜尋影像的特徵向量和特徵向量資料庫之間的餘弦距離,然後輸出最近的前N個結果。
當然,這僅僅是一個demo,在實際計算中,還可以用一些演算法來快速計算數百萬影像間的餘弦距離。你可以使用簡單且執行速度相當快的Annoy Index(在1M影像中搜尋約需2ms)。
現在把它們放在一起執行一下:
def show_img(path):
img = imread(path, mode="RGB")
plt.imshow(img)
plt.show()
def run():
images_path = 'resources/images/'
files = [os.path.join(images_path, p) for p in sorted(os.listdir(images_path))]
# getting 3 random images
# 隨機獲取3張圖
sample = random.sample(files, 3)
batch_extractor(images_path)
ma = Matcher('features.pck')
for s in sample:
print 'Query image =========================================='
show_img(s)
names, match = ma.match(s, topn=3)
print 'Result images ========================================'
for i in range(3):
# we got cosine distance, less cosine distance between vectors
# more they similar, thus we subtruct it from 1 to get match value
#我們得到了餘弦距離,向量之間的餘弦距離越小表示它們越相似,因此我們從1中減去它以得到匹配值
print 'Match %s' % (1-match[i])
show_img(os.path.join(images_path, names[i]))
run()
大家可以在我的 github上下載原始碼,或者在Google Colab上執行(Google Colab是一種提供GPU線上計算的免費服務):
https://colab.research.google.com/drive/1BwdSConGugBlGzPLLkXHTz2ahkdzEhQ9
▌總結
在執行上述程式碼的過程中,你可能會發現搜尋到的相似影像並不總能達到我們想象中的那種相似程度。這是因為我們所用的這種演算法是上下文無關(context-unaware)的,所以該演算法在尋找相同(即使是被修改過的)影像方面表現更好,而不是在相似影像方面。如果是要尋找上下文相關的相似影像,那就要使用卷積神經網路了,我的下一篇文章會對這方面的知識進行詳細介紹。
作者:Andrey Nikishaev
原文連結:https://towardsdatascience.com/feature-extraction-and-similar-image-search-with-opencv-for-newbies-3c59796bf774
相關文章
- 基於ElasticSearch實現商品的全文檢索檢索Elasticsearch
- 原來CNN是這樣提取影像特徵的。。。CNN特徵
- 【數字影像處理6】python+opencv使用LBP、HOG提取特徵來分類人臉【更新中】PythonOpenCVHOG特徵
- OpenCV7影像金字塔與輪廓檢測OpenCV
- python基於opencv 實現影像時鐘PythonOpenCV
- 嵌入式程式除錯與opencv影像庫除錯OpenCV
- OpenCV計算機視覺學習(13)——影像特徵點檢測(Harris角點檢測,sift演算法)OpenCV計算機視覺特徵演算法
- php + MongoDB + Sphinx 實現全文檢索PHPMongoDB
- 特徵提取-map特徵
- 影象特徵提取之HoG特徵特徵HOG
- 【影像處理】基於OpenCV實現影像直方圖的原理OpenCV直方圖
- FoxMail 本地密碼破解(提取) ,逆向分析與實現AI密碼
- 手把手教你使用LabVIEW OpenCV dnn實現影像分類(含原始碼)ViewOpenCVDNN原始碼
- NLP詳細教程:手把手教你用ELMo模型提取文字特徵(附程式碼&論文)模型特徵
- ElasticSearch 實現分詞全文檢索 - 概述Elasticsearch分詞
- 影像篡改被動檢測技術一覽:基於特徵提取和卷積神經網路的篡改檢測特徵卷積神經網路
- opencv——輪廓發現與輪廓(二值影像)分析OpenCV
- 微信域名檢測實現機制與程式碼分享
- 使用yarGen提取Linux惡意指令碼特徵Linux指令碼特徵
- librosa 音訊特徵提取的現成文件ROS音訊特徵
- TensorFlow Lite+OpenCV實現移動端水印的檢測與去除OpenCV
- 基於Tensorflow + Opencv 實現CNN自定義影像分類OpenCVCNN
- 如何快速實現高併發短文檢索
- Go 實現 自動檢索 API 錯誤碼程式碼行 並 列印成文件,例 markDown 形式等GoAPI
- 3.SIFT特徵提取與ransac演算法特徵演算法
- 4.SIFT特徵提取與ransac演算法特徵演算法
- 40行Python程式碼,實現卷積特徵視覺化Python卷積特徵視覺化
- opencv——影像直方圖與反向投影OpenCV直方圖
- 【火爐煉AI】機器學習050-提取影像的Star特徵AI機器學習特徵
- 計算機視覺 OpenCV Android | 基本特徵檢測之 霍夫圓檢計算機視覺OpenCVAndroid特徵
- 實現【檢視更多】功能的程式碼
- 學習筆記17:DenseNet實現多分類(卷積基特徵提取)筆記SENet卷積特徵
- 流量特徵提取工具NFStream特徵NFS
- 學習OpenCV:骨架提取OpenCV
- 使用 Vyper 實現影像邊緣檢測
- 使用 Vala 實現影像邊緣檢測
- 使用 Fantom 實現影像邊緣檢測
- 基於opencv實現簡單人臉檢測OpenCV