詳解如何使用opencv實現(xiàn)圖片相似度檢測
1.為什么學這個,我對圖像處理非常感興趣,我聯(lián)想到海爾的指紋識別門鎖是如何進行檢測的,我在想不應(yīng)該呀,單片機性能這么差,應(yīng)該是使用了訓練后的數(shù)據(jù)去檢測圖片的,如果我要實現(xiàn)草莓檢測,知道它是不是草莓,我覺得單純使用圖片處理是不夠的,我考慮過使用指紋模塊來接觸草莓從而實現(xiàn)判斷他是不是草莓,從而聯(lián)想到學習圖像相似度檢測,我們?nèi)祟惖氖种甘聦嵣鲜怯写罅康膫鞲衅鞯?機器如果想要實現(xiàn)那科技含量太高了,而且成本高,就算實現(xiàn)了也只能放在家里自己玩…
2.代碼基于python3.1 opencv,先使用直方圖判斷是否是簡單的圖形(運算快)如果不是在判斷是否是復雜的圖形(運算慢)
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特征檢測器 orb = cv2.ORB_create() # 檢測特征點和描述符 kp1, des1 = orb.detectAndCompute(gray_img1, None) kp2, des2 = orb.detectAndCompute(gray_img2, None) # 創(chuàng)建暴力匹配器 bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) # 進行特征匹配 matches = bf.match(des1, des2) similarity=0.0 # 根據(jù)特征點匹配結(jié)果計算相似度 if len(matches) > 0: similarity = sum([match.distance for match in matches]) / len(matches) print('圖片相似度為:', similarity) else: print('未找到匹配的特征點') # 調(diào)用函數(shù)進行圖片相似度計算,計算簡單的圖片相似度 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) # 計算直方圖 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.測試效果
簡單的圖片使用直方圖歸一化處理
不同的圖片之間比較
2和22比較
2和23無法檢測出來,可能是2個2顏色不一樣,2和24也一樣
straw1和straw2 這兩張是在一張圖片的兩顆草莓
圖片相似度為: 0.8582924959300794
traw1和straw3,不同圖片的草莓
圖片相似度為: 69.67826086956522
與倒立的草莓
圖片相似度為: 68.84821428571429
圖片相似度為: 73.10416666666667
帶有草莓花的草莓,比較符合實際情況
圖片相似度為: 0.7757366241694935
啊這汽車和草莓是相似的?而且是多個草莓,改了下代碼 如果形狀都不同了,similarity<0直接返回
4.改進后的代碼
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特征檢測器 orb = cv2.ORB_create() # 檢測特征點和描述符 kp1, des1 = orb.detectAndCompute(gray_img1, None) kp2, des2 = orb.detectAndCompute(gray_img2, None) # 創(chuàng)建暴力匹配器 bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) # 進行特征匹配 matches = bf.match(des1, des2) similarity=0.0 # 根據(jù)特征點匹配結(jié)果計算相似度 if len(matches) > 0: similarity = sum([match.distance for match in matches]) / len(matches) print('圖片相似度為:', similarity) else: print('未找到匹配的特征點') # 調(diào)用函數(shù)進行圖片相似度計算,計算簡單的圖片相似度 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) # 計算直方圖 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)該不是一個東西 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)
改進后的結(jié)果
不同的形狀的都返回負數(shù)
圖片相似度為: -0.07563206074940822
5.根據(jù)評論區(qū)網(wǎng)友的建議進行測試
1.白描、素描、水彩 均不能識別
2.顯微鏡(基本識別得出)和草莓醬(有幾率識別70%,顏色太深識別不出,需要大數(shù)據(jù)來對比)
3.一堆草莓 可以識別出來
能識別顯微鏡下
不能識別,添加了很多其他材料,或者是放太久果醬顏色變深
可以識別
加個干擾因素,和多個草莓 64%識別出來
5.以后改進的地方,上面的代碼可以簡單的檢測顏色相同形狀相同的問題,但是也面臨著檢測精度的不精確,我們可以錄入多個圖片如果取相似度最高的一張,當然性能不大好, 識別蘋果和草莓達到40%相似率
其實我們不需要自己下載所有圖片來提高精確度,我們只需要和網(wǎng)絡(luò)上的1000張圖片對比,基本可以確定這個圖片是不是我們要的草莓,這個思路也可以用在識別其他物體…
- 使用模糊的圖片識別工具,識別圖片是什么
- 使用我的代碼,假設(shè)上面識別出草莓,就拿原來圖片和百度的大量圖片進行對比,取準確率最高的值在1000張圖片中
- 假設(shè)上面識別錯誤,識別為人,也按照2的方法對比,返回錯誤結(jié)果,并且使用一個關(guān)鍵字文本寫上生活中常見的物體,一一查詢
- 其實最重要的是防止重復性的工作,還是需要圖片訓練,生成模型文件…
6.結(jié)論,這個案例僅僅只能實現(xiàn)簡單的圖片識別功能,并不能識別物體的區(qū)域,其實我們可以通過逐步縮小圖片的范圍來確定物體的位置,我發(fā)現(xiàn)使用多維數(shù)組來處理圖片不是一個明智的選擇,還得發(fā)現(xiàn)他們函數(shù)關(guān)系,多個圖片又有多個函數(shù)關(guān)系…,一個圖片有多個草莓怎么辦…
7.改進,可以任意尺寸圖片進行識別
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特征檢測器 orb = cv2.ORB_create() # 檢測特征點和描述符 kp1, des1 = orb.detectAndCompute(gray_img1, None) kp2, des2 = orb.detectAndCompute(gray_img2, None) # 將描述符類型轉(zhuǎn)換為CV_8U des1 = np.uint8(des1) des2 = np.uint8(des2) # 創(chuàng)建暴力匹配器 bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) # 進行特征匹配 matches = bf.match(des1, des2) similarity = 0.0 # 根據(jù)特征點匹配結(jié)果計算相似度 if len(matches) > 0: similarity = sum([match.distance for match in matches]) / len(matches) print('圖片相似度為:', similarity) else: print('未找到匹配的特征點') 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) # 計算直方圖 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('未找到足夠的特征點') return 0.1 # 轉(zhuǎn)換描述符類型 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) print('ORB圖片相似度為:', orb_similarity) else: print('未找到匹配的特征點') 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.識別多顆草莓,就需要把一張圖片分為多個區(qū)域,然后分別識別,比如我下面草莓分為4個區(qū)域去識別
代碼
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特征檢測器 orb = cv2.ORB_create() # 檢測特征點和描述符 kp1, des1 = orb.detectAndCompute(gray_img1, None) kp2, des2 = orb.detectAndCompute(gray_img2, None) # 將描述符類型轉(zhuǎn)換為CV_8U des1 = np.uint8(des1) des2 = np.uint8(des2) # 創(chuàng)建暴力匹配器 bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) # 進行特征匹配 matches = bf.match(des1, des2) similarity = 0.0 # 根據(jù)特征點匹配結(jié)果計算相似度 if len(matches) > 0: similarity = sum([match.distance for match in matches]) / len(matches) print('圖片相似度為:', similarity) else: print('未找到匹配的特征點') 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) # 計算直方圖 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 # 將第二個圖片切割為4個區(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:] sim_list = [] # 創(chuàng)建ORB特征檢測器 orb = cv2.ORB_create() kp1, des1 = orb.detectAndCompute(img1, None) # 計算四個區(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('未找到足夠的特征點') 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) # 計算ORB特征相似度 orb_similarity = calculate_complexity_similarity(img1_path, img2_path) # 計算直方圖相似度 hist_similarity = calculate_histogram_similarity(img1_path, img2_path) # 將第二張圖片切割為4個區(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實現(xiàn)圖片相似度檢測的詳細內(nèi)容,更多關(guān)于opencv圖片相似度檢測的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python實現(xiàn)json對值進行模糊搜索的示例詳解
我經(jīng)常使用json進行存儲配置,于是常常遇到這樣的問題:如果想要對某個數(shù)組里的值進行模糊搜索,同時輸出相關(guān)的其他數(shù)組相同位置的的值該如何實現(xiàn)呢?本文就來和大家詳細聊聊2023-01-01pandas讀取文件夾下所有excel文件的實現(xiàn)
最近需要做一個需求,要求匯總一個文件夾所有的excel文件,所以本文就來介紹一下pandas讀取文件夾下所有excel文件的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2023-09-09Python日期格式和字符串格式相互轉(zhuǎn)換的方法
這篇文章主要介紹了Python日期格式和字符串格式相互轉(zhuǎn)換的方法,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2020-02-02python 基本數(shù)據(jù)類型占用內(nèi)存空間大小的實例
今天小編就為大家分享一篇python 基本數(shù)據(jù)類型占用內(nèi)存空間大小的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-06-06