詳解如何使用opencv實(shí)現(xiàn)圖片相似度檢測(cè)
1.為什么學(xué)這個(gè),我對(duì)圖像處理非常感興趣,我聯(lián)想到海爾的指紋識(shí)別門(mén)鎖是如何進(jìn)行檢測(cè)的,我在想不應(yīng)該呀,單片機(jī)性能這么差,應(yīng)該是使用了訓(xùn)練后的數(shù)據(jù)去檢測(cè)圖片的,如果我要實(shí)現(xiàn)草莓檢測(cè),知道它是不是草莓,我覺(jué)得單純使用圖片處理是不夠的,我考慮過(guò)使用指紋模塊來(lái)接觸草莓從而實(shí)現(xiàn)判斷他是不是草莓,從而聯(lián)想到學(xué)習(xí)圖像相似度檢測(cè),我們?nèi)祟?lèi)的手指事實(shí)上是有大量的傳感器的,機(jī)器如果想要實(shí)現(xiàn)那科技含量太高了,而且成本高,就算實(shí)現(xiàn)了也只能放在家里自己玩…
2.代碼基于python3.1 opencv,先使用直方圖判斷是否是簡(jiǎn)單的圖形(運(yùn)算快)如果不是在判斷是否是復(fù)雜的圖形(運(yùn)算慢)
import cv2
def calculate_complexity_similarity(img1str, img2str):
# 加載兩張圖片
img1 = cv2.imread(img1str)
img2 = cv2.imread(img2str)
# 將圖片轉(zhuǎn)換為灰度圖像
gray_img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray_img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 創(chuàng)建ORB特征檢測(cè)器
orb = cv2.ORB_create()
# 檢測(cè)特征點(diǎn)和描述符
kp1, des1 = orb.detectAndCompute(gray_img1, None)
kp2, des2 = orb.detectAndCompute(gray_img2, None)
# 創(chuàng)建暴力匹配器
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
# 進(jìn)行特征匹配
matches = bf.match(des1, des2)
similarity=0.0
# 根據(jù)特征點(diǎn)匹配結(jié)果計(jì)算相似度
if len(matches) > 0:
similarity = sum([match.distance for match in matches]) / len(matches)
print('圖片相似度為:', similarity)
else:
print('未找到匹配的特征點(diǎn)')
# 調(diào)用函數(shù)進(jìn)行圖片相似度計(jì)算,計(jì)算簡(jiǎn)單的圖片相似度
return similarity
def calculate_histogram_similarity(img1_path, img2_path):
# 讀取兩張圖片
img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)
# 計(jì)算直方圖
hist1 = cv2.calcHist([img1], [0], None, [256], [0, 256])
hist2 = cv2.calcHist([img2], [0], None, [256], [0, 256])
# 歸一化直方圖
cv2.normalize(hist1, hist1, 0, 1, cv2.NORM_MINMAX)
cv2.normalize(hist2, hist2, 0, 1, cv2.NORM_MINMAX)
# 比較直方圖
similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)
if similarity<0.6:
similarity=calculate_complexity_similarity(img1str, img2str)
return similarity
if __name__ == '__main__':
img1str='straw1.png'
img2str='straw3.png'
sim = calculate_histogram_similarity(img1str, img2str)
print('圖片相似度為:', sim)
3.測(cè)試效果
簡(jiǎn)單的圖片使用直方圖歸一化處理


不同的圖片之間比較

2和22比較

2和23無(wú)法檢測(cè)出來(lái),可能是2個(gè)2顏色不一樣,2和24也一樣

straw1和straw2 這兩張是在一張圖片的兩顆草莓
圖片相似度為: 0.8582924959300794
traw1和straw3,不同圖片的草莓

圖片相似度為: 69.67826086956522
與倒立的草莓

圖片相似度為: 68.84821428571429

圖片相似度為: 73.10416666666667
帶有草莓花的草莓,比較符合實(shí)際情況

圖片相似度為: 0.7757366241694935
啊這汽車(chē)和草莓是相似的?而且是多個(gè)草莓,改了下代碼 如果形狀都不同了,similarity<0直接返回


4.改進(jìn)后的代碼
import cv2
def calculate_complexity_similarity(img1str, img2str):
# 加載兩張圖片
img1 = cv2.imread(img1str)
img2 = cv2.imread(img2str)
# 將圖片轉(zhuǎn)換為灰度圖像
gray_img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray_img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 創(chuàng)建ORB特征檢測(cè)器
orb = cv2.ORB_create()
# 檢測(cè)特征點(diǎn)和描述符
kp1, des1 = orb.detectAndCompute(gray_img1, None)
kp2, des2 = orb.detectAndCompute(gray_img2, None)
# 創(chuàng)建暴力匹配器
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
# 進(jìn)行特征匹配
matches = bf.match(des1, des2)
similarity=0.0
# 根據(jù)特征點(diǎn)匹配結(jié)果計(jì)算相似度
if len(matches) > 0:
similarity = sum([match.distance for match in matches]) / len(matches)
print('圖片相似度為:', similarity)
else:
print('未找到匹配的特征點(diǎn)')
# 調(diào)用函數(shù)進(jìn)行圖片相似度計(jì)算,計(jì)算簡(jiǎn)單的圖片相似度
return similarity
def calculate_histogram_similarity(img1_path, img2_path):
# 讀取兩張圖片
img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)
# 計(jì)算直方圖
hist1 = cv2.calcHist([img1], [0], None, [256], [0, 256])
hist2 = cv2.calcHist([img2], [0], None, [256], [0, 256])
# 歸一化直方圖
cv2.normalize(hist1, hist1, 0, 1, cv2.NORM_MINMAX)
cv2.normalize(hist2, hist2, 0, 1, cv2.NORM_MINMAX)
# 比較直方圖
similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)
print(similarity)
#30%的幾率是那應(yīng)該不是一個(gè)東西
if similarity <0.3:
return similarity
if similarity<0.6:
similarity=calculate_complexity_similarity(img1str, img2str)
return similarity
if __name__ == '__main__':
img1str='straw4.png'
img2str='straw7.png'
sim = calculate_histogram_similarity(img1str, img2str)
print('圖片相似度為:', sim)
改進(jìn)后的結(jié)果

不同的形狀的都返回負(fù)數(shù)
圖片相似度為: -0.07563206074940822
5.根據(jù)評(píng)論區(qū)網(wǎng)友的建議進(jìn)行測(cè)試
1.白描、素描、水彩 均不能識(shí)別
2.顯微鏡(基本識(shí)別得出)和草莓醬(有幾率識(shí)別70%,顏色太深識(shí)別不出,需要大數(shù)據(jù)來(lái)對(duì)比)
3.一堆草莓 可以識(shí)別出來(lái)


能識(shí)別顯微鏡下

不能識(shí)別,添加了很多其他材料,或者是放太久果醬顏色變深

可以識(shí)別

加個(gè)干擾因素,和多個(gè)草莓 64%識(shí)別出來(lái)

5.以后改進(jìn)的地方,上面的代碼可以簡(jiǎn)單的檢測(cè)顏色相同形狀相同的問(wèn)題,但是也面臨著檢測(cè)精度的不精確,我們可以錄入多個(gè)圖片如果取相似度最高的一張,當(dāng)然性能不大好, 識(shí)別蘋(píng)果和草莓達(dá)到40%相似率
其實(shí)我們不需要自己下載所有圖片來(lái)提高精確度,我們只需要和網(wǎng)絡(luò)上的1000張圖片對(duì)比,基本可以確定這個(gè)圖片是不是我們要的草莓,這個(gè)思路也可以用在識(shí)別其他物體…
- 使用模糊的圖片識(shí)別工具,識(shí)別圖片是什么
- 使用我的代碼,假設(shè)上面識(shí)別出草莓,就拿原來(lái)圖片和百度的大量圖片進(jìn)行對(duì)比,取準(zhǔn)確率最高的值在1000張圖片中
- 假設(shè)上面識(shí)別錯(cuò)誤,識(shí)別為人,也按照2的方法對(duì)比,返回錯(cuò)誤結(jié)果,并且使用一個(gè)關(guān)鍵字文本寫(xiě)上生活中常見(jiàn)的物體,一一查詢(xún)
- 其實(shí)最重要的是防止重復(fù)性的工作,還是需要圖片訓(xùn)練,生成模型文件…
6.結(jié)論,這個(gè)案例僅僅只能實(shí)現(xiàn)簡(jiǎn)單的圖片識(shí)別功能,并不能識(shí)別物體的區(qū)域,其實(shí)我們可以通過(guò)逐步縮小圖片的范圍來(lái)確定物體的位置,我發(fā)現(xiàn)使用多維數(shù)組來(lái)處理圖片不是一個(gè)明智的選擇,還得發(fā)現(xiàn)他們函數(shù)關(guān)系,多個(gè)圖片又有多個(gè)函數(shù)關(guān)系…,一個(gè)圖片有多個(gè)草莓怎么辦…
7.改進(jìn),可以任意尺寸圖片進(jìn)行識(shí)別
import cv2
import numpy as np
def calculate_complexity_similarity(img1_path, img2_path):
# 加載兩張圖片
img1 = cv2.imread(img1_path)
img2 = cv2.imread(img2_path)
# 將圖片轉(zhuǎn)換為灰度圖像
gray_img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray_img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 創(chuàng)建ORB特征檢測(cè)器
orb = cv2.ORB_create()
# 檢測(cè)特征點(diǎn)和描述符
kp1, des1 = orb.detectAndCompute(gray_img1, None)
kp2, des2 = orb.detectAndCompute(gray_img2, None)
# 將描述符類(lèi)型轉(zhuǎn)換為CV_8U
des1 = np.uint8(des1)
des2 = np.uint8(des2)
# 創(chuàng)建暴力匹配器
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
# 進(jìn)行特征匹配
matches = bf.match(des1, des2)
similarity = 0.0
# 根據(jù)特征點(diǎn)匹配結(jié)果計(jì)算相似度
if len(matches) > 0:
similarity = sum([match.distance for match in matches]) / len(matches)
print('圖片相似度為:', similarity)
else:
print('未找到匹配的特征點(diǎn)')
return similarity
def calculate_histogram_similarity(img1_path, img2_path):
# 讀取兩張圖片
img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)
# 計(jì)算直方圖
hist1 = cv2.calcHist([img1], [0], None, [256], [0, 256])
hist2 = cv2.calcHist([img2], [0], None, [256], [0, 256])
# 歸一化直方圖
cv2.normalize(hist1, hist1, 0, 1, cv2.NORM_MINMAX)
cv2.normalize(hist2, hist2, 0, 1, cv2.NORM_MINMAX)
# 比較直方圖
similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)
if similarity < 0.2:
return similarity
if similarity < 0.6:
# 檢查ORB描述符是否可用,若不可用則直接返回較低的相似度值
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)
if des1 is None or des2 is None:
print('未找到足夠的特征點(diǎn)')
return 0.1
# 轉(zhuǎn)換描述符類(lèi)型
des1 = np.uint8(des1)
des2 = np.uint8(des2)
# 進(jìn)行特征匹配
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2)
orb_similarity = 0.0
if len(matches) > 0:
orb_similarity = sum([match.distance for match in matches]) / len(matches)
print('ORB圖片相似度為:', orb_similarity)
else:
print('未找到匹配的特征點(diǎn)')
return orb_similarity
return similarity
if __name__ == '__main__':
img1_path = 'pic/straw1.png'
img2_path = 'pic/smstraw1.png'
sim = calculate_histogram_similarity(img1_path, img2_path)
print('圖片相似度為:', sim)
8.識(shí)別多顆草莓,就需要把一張圖片分為多個(gè)區(qū)域,然后分別識(shí)別,比如我下面草莓分為4個(gè)區(qū)域去識(shí)別

代碼
import cv2
import numpy as np
def calculate_complexity_similarity(img1_path, img2_path):
# 加載兩張圖片
img1 = cv2.imread(img1_path)
img2 = cv2.imread(img2_path)
# 將圖片轉(zhuǎn)換為灰度圖像
gray_img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
gray_img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# 創(chuàng)建ORB特征檢測(cè)器
orb = cv2.ORB_create()
# 檢測(cè)特征點(diǎn)和描述符
kp1, des1 = orb.detectAndCompute(gray_img1, None)
kp2, des2 = orb.detectAndCompute(gray_img2, None)
# 將描述符類(lèi)型轉(zhuǎn)換為CV_8U
des1 = np.uint8(des1)
des2 = np.uint8(des2)
# 創(chuàng)建暴力匹配器
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
# 進(jìn)行特征匹配
matches = bf.match(des1, des2)
similarity = 0.0
# 根據(jù)特征點(diǎn)匹配結(jié)果計(jì)算相似度
if len(matches) > 0:
similarity = sum([match.distance for match in matches]) / len(matches)
print('圖片相似度為:', similarity)
else:
print('未找到匹配的特征點(diǎn)')
return similarity
def calculate_histogram_similarity(img1_path, img2_path):
# 讀取兩張圖片
img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)
# 計(jì)算直方圖
hist1 = cv2.calcHist([img1], [0], None, [256], [0, 256])
hist2 = cv2.calcHist([img2], [0], None, [256], [0, 256])
# 歸一化直方圖
cv2.normalize(hist1, hist1, 0, 1, cv2.NORM_MINMAX)
cv2.normalize(hist2, hist2, 0, 1, cv2.NORM_MINMAX)
# 比較直方圖
similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)
if similarity < 0.2:
return similarity
# 將第二個(gè)圖片切割為4個(gè)區(qū)域并分別計(jì)算相似度
h, w = img2.shape[:2]
img2_1 = img2[:h // 2, :w // 2]
img2_2 = img2[:h // 2, w // 2:]
img2_3 = img2[h // 2:, :w // 2]
img2_4 = img2[h // 2:, w // 2:]
sim_list = []
# 創(chuàng)建ORB特征檢測(cè)器
orb = cv2.ORB_create()
kp1, des1 = orb.detectAndCompute(img1, None)
# 計(jì)算四個(gè)區(qū)域的相似度
for img in [img2_1, img2_2, img2_3, img2_4]:
kp2, des2 = orb.detectAndCompute(img, None)
if des1 is None or des2 is None:
print('未找到足夠的特征點(diǎn)')
sim_list.append(0.1)
else:
des1 = np.uint8(des1)
des2 = np.uint8(des2)
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2)
orb_similarity = 0.0
if len(matches) > 0:
orb_similarity = sum([match.distance for match in matches]) / len(matches)
sim_list.append(orb_similarity)
max_sim = max(sim_list)
print('圖片相似度為:', max_sim)
return max_sim
if __name__ == '__main__':
img1_path = 'pic/straw1.png'
img2_path = 'pic/straw2.png'
# 加載兩張圖片
img1 = cv2.imread(img1_path)
img2 = cv2.imread(img2_path)
# 計(jì)算ORB特征相似度
orb_similarity = calculate_complexity_similarity(img1_path, img2_path)
# 計(jì)算直方圖相似度
hist_similarity = calculate_histogram_similarity(img1_path, img2_path)
# 將第二張圖片切割為4個(gè)區(qū)域
h, w = img2.shape[:2]
img2_1 = img2[:h // 2, :w // 2]
img2_2 = img2[:h // 2, w // 2:]
img2_3 = img2[h // 2:, :w // 2]
img2_4 = img2[h // 2:, w // 2:]
# 在圖片上繪制綠色框和相似度
cv2.rectangle(img2, (0, 0), (w // 2, h // 2), (0, 255, 0), 2)
cv2.putText(img2, f" {orb_similarity:.2f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.rectangle(img2, (w // 2, 0), (w, h // 2), (0, 255, 0), 2)
cv2.putText(img2, f" {hist_similarity:.2f}", (w // 2 + 10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.rectangle(img2, (0, h // 2), (w // 2, h), (0, 255, 0), 2)
cv2.putText(img2, f" {orb_similarity:.2f}", (10, h // 2 + 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
cv2.rectangle(img2, (w // 2, h // 2), (w, h), (0, 255, 0), 2)
cv2.putText(img2, f" {hist_similarity:.2f}", (w // 2 + 10, h // 2 + 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
# 顯示結(jié)果圖片
cv2.namedWindow('Image', cv2.WINDOW_NORMAL)
cv2.resizeWindow('Image', 800, 600)
cv2.imshow('Image', cv2.resize(img2, (0, 0), fx=0.5, fy=0.5))
cv2.waitKey(0)
cv2.destroyAllWindows()
以上就是詳解如何使用opencv實(shí)現(xiàn)圖片相似度檢測(cè)的詳細(xì)內(nèi)容,更多關(guān)于opencv圖片相似度檢測(cè)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解Python圖像處理中內(nèi)存泄漏的問(wèn)題解決方法
在Python編程中,尤其是在圖像處理領(lǐng)域,內(nèi)存泄漏是一個(gè)不容忽視的問(wèn)題,本文將深入探討Python為何容易發(fā)生內(nèi)存泄漏,以及如何有效檢測(cè)和解決,希望對(duì)大家有所幫助2025-02-02
詳解基于Jupyter notebooks采用sklearn庫(kù)實(shí)現(xiàn)多元回歸方程編程
這篇文章主要介紹了詳解基于Jupyter notebooks采用sklearn庫(kù)實(shí)現(xiàn)多元回歸方程編程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
基于Python開(kāi)發(fā)一個(gè)現(xiàn)代化Markdown編輯器
在這個(gè)內(nèi)容為王的時(shí)代,Markdown已經(jīng)成為技術(shù)寫(xiě)作的標(biāo)準(zhǔn)格式,從GitHub的README文件到技術(shù)博客,從API文檔到學(xué)術(shù)論文,Markdown以其簡(jiǎn)潔的語(yǔ)法和強(qiáng)大的表現(xiàn)力征服了無(wú)數(shù)開(kāi)發(fā)者和內(nèi)容創(chuàng)作者,本文介紹了如何基于Python開(kāi)發(fā)一個(gè)現(xiàn)代化Markdown編輯器,需要的朋友可以參考下2025-09-09
python機(jī)器學(xué)習(xí)混淆矩陣及confusion?matrix函數(shù)使用
這篇文章主要為大家介紹了python機(jī)器學(xué)習(xí)混淆矩陣confusion_matrix函數(shù)使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
理解深度學(xué)習(xí)之深度學(xué)習(xí)簡(jiǎn)介
這篇文章主要是關(guān)于深度學(xué)習(xí)的簡(jiǎn)介,對(duì)大家學(xué)習(xí)了解機(jī)器深度學(xué)習(xí)有一定的幫助,以后會(huì)持續(xù)更新本系列,希望能為大家?guī)?lái)一些收貨,讓我們一起來(lái)看看下面的文章吧2021-04-04
基于Python實(shí)現(xiàn)多語(yǔ)言朗讀與單詞選擇測(cè)驗(yàn)
在數(shù)字化教育日益普及的今天,開(kāi)發(fā)一款能夠支持多語(yǔ)言朗讀和單詞選擇測(cè)驗(yàn)的程序,對(duì)于語(yǔ)言學(xué)習(xí)者來(lái)說(shuō)無(wú)疑是一個(gè)巨大的福音,下面我們就來(lái)用Python實(shí)現(xiàn)一個(gè)這樣的小程序吧2025-03-03
Python requests HTTP驗(yàn)證登錄實(shí)現(xiàn)流程
這篇文章主要介紹了Python requests HTTP驗(yàn)證登錄實(shí)現(xiàn)流程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-11-11
基于Python實(shí)現(xiàn)在控制臺(tái)查看excel的內(nèi)容
這篇文章主要為大家詳細(xì)介紹了如何基于Python實(shí)現(xiàn)在控制臺(tái)查看excel的內(nèi)容,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-12-12

