Python 進行目標檢測

来源:https://www.cnblogs.com/zhj-Szu/archive/2020/02/15/12311082.html
-Advertisement-
Play Games

一、前言 從學單片機開始鼓搗C語言,到現在為了學CV鼓搗Python,期間在CSDN、簡書、博客園和github這些地方得到了很多幫助,所以也想把自己做的一些小東西分享給大家,希望能幫助到別人。記錄人生的第一篇博客,mark。 二、圖像檢測步驟 1. 讀取兩張圖片 第一張是需要檢測的小物體,第二章圖 ...


一、前言

  從學單片機開始鼓搗C語言,到現在為了學CV鼓搗Python,期間在CSDN、簡書、博客園和github這些地方得到了很多幫助,所以也想把自己做的一些小東西分享給大家,希望能幫助到別人。記錄人生的第一篇博客,mark。

二、圖像檢測步驟

1. 讀取兩張圖片

  第一張是需要檢測的小物體,第二章圖片是小物體放置在大場景中。代碼與輸出結果如下所示:

import numpy as np
import matplotlib.pyplot as plt
import cv2

def my_show(img):
    plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    return 

# 讀取圖片
img_small=cv2.imread('small.jpg',1)
img_big=cv2.imread('big.jpg',1)

# 顯示圖片
plt.figure(figsize=(10,10))
plt.subplot(121)
my_show(img_small)
plt.subplot(122)
my_show(img_big)

 

2. 提取圖片中的特征點

  這一步就像我們在區分不同的人的時候,一眼看到外貌就知道此人是誰,而外貌就是這個人的特征。我們希望提取該物體的特征點,以便在不同的場景中識別出來。圖片是由像素點構成,但是像素點包含的信息太零散了,一般是識別物體的邊緣或者角點作為特征信息。常用的特征描述演算法如下:

  SIFThttps://blog.csdn.net/zddblog/article/details/7521424

  harris corner detection: https://www.jianshu.com/p/efc81fdb8afb

  Hog: https://lear.inrialpes.fr/people/triggs/pubs/Dalal-cvpr05.pdf

  SURF: https://www.vision.ee.ethz.ch/~surf/eccv06.pdf

  BRISK: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.371.1343&rep=rep1&type=pdf

  Orb: http://www.willowgarage.com/sites/default/files/orb_final.pdf

  我們項目中用到的是SIFT演算法,SIFT精確度高,對尺度、亮度以及旋轉的魯棒性強,不過計算時間長,所需的計算資源較多。SURF是SIFT的加速版本,有興趣的小伙伴可以瞭解一下。SIFT演算法運行後,可以得到的特征點的位置以及特征向量。(PS:SIFT演算法申請了專利,所以在opencv3.4.2版本後不能使用了,需要用SIFT的請安裝3.4.2的opencv)

import numpy as np
import matplotlib.pyplot as plt
import cv2

def my_show(img):
    plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    return 

# 讀取圖片
img_small=cv2.imread('small.jpg',1)
img_big=cv2.imread('big.jpg',1)

# 提取特征點
sift=cv2.xfeatures2d.SIFT_create()
kp1,des1=sift.detectAndCompute(img_small,None)
kp2,des2=sift.detectAndCompute(img_big,None)

# 在圖中顯示特征點
img_small_sift=cv2.drawKeypoints(img_small,kp1,outImage=np.array([]),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
img_big_sift=cv2.drawKeypoints(img_big,kp2,outImage=np.array([]),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)

plt.figure(figsize=(15,15))
plt.subplot(121)
my_show(img_small_sift)
plt.subplot(122)
my_show(img_big_sift)

 

3.特征點匹配

  在分別提取了兩張圖的特征點後,就需要進行特征點匹配啦。這裡需要註意的是,兩張圖的特征點數量一般情況下是不一樣的,opencv演算法里預設用第一張圖的特征點來匹配,所以匹配矩陣的行數與第一張圖特征點的行數一致。常用的匹配方法:

  Brute-Force: 暴力搜索,用圖1的特征點逐一與圖二的特征點比較,找到歐式距離最小的點作為匹配點。不過這樣匹配的錯誤點就會很多,所以常用交叉匹配法消除錯誤匹配。交叉匹配法指的是,反過來匹配一次,用匹配到圖2的點反過來匹配圖1的點,如果匹配結果與原來相同,則認為是正確匹配。

  KNN: K近鄰匹配,在匹配的時候選擇K個和特征點最相似的點,如果這K個點之間的區別足夠大,則選擇最相似的那個點作為匹配點,通常選擇K = 2。KNN匹配也會出現一些誤匹配,這時候需要對比第一鄰近與第二鄰近之間的距離大小,假如 distance_1< (0.5~0.7)*distance_2, 則認為是正確匹配。

  FLANN: FLANN是快速最近鄰搜索包(Fast Library for Approximate Nearest Neighbors)的簡稱,是最近鄰搜索的演算法的集合。

  一般我們會選擇調用cv2.Brute-Force或者cv2.FlannBasedMatcher來進行特征點匹配,FLANN裡邊就包含的KNN、KD樹還有其他的最近鄰演算法。

 

4.計算單應性矩陣

  這裡我們需要在大場景中用矩形框出匹配的小物體,所以就要計算單應性矩陣,然後做投影變換。RANSAC(Random Sample Consensus隨機抽樣一致性演算法是計算單應性矩陣的有效方法,並且在尋找單應性矩陣的過程中可以進一步剔除錯誤匹配點。RANSAC演算法的步驟如下:

  •  隨機抽取四個匹配點對計算投影矩陣,需要檢驗四個點是否共線
  •  圖片1特征點坐標齊次變換後(3,1)乘上投影矩陣(3,3),然後計算變換後的特征點坐標與圖片2特征點坐標的歐氏距離,小於設定的閾值則記錄為內點,反之則為內點
  •  判斷此次內點的數量是否比以往記錄的內點最大值多,如果是,則更新投影矩陣,如果不是,則不更新
  •  判定迴圈次數是夠達到設定次數或內點數占全部匹配點的比例達到設定比例,則跳出迴圈,否則跳到步驟1繼續迴圈

  尋找到最優的單應性矩陣後,將框住物體一的矩陣經投影變換後在圖片二上畫出來,完成目標檢測框選。以下代碼摘自Brook@CV的博客並修改,如有侵權,請通知刪除

import numpy as np
import cv2
from matplotlib import pyplot as plt

MIN_MATCH_COUNT = 10

img1 = cv2.imread('small.jpg',1)
img2 = cv2.imread('big.jpg',1)

# 使用SIFT檢測角點
sift = cv2.xfeatures2d.SIFT_create()
# 獲取關鍵點和描述符
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)

# 定義FLANN匹配器
index_params = dict(algorithm = 1, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
# 使用KNN演算法匹配
matches = flann.knnMatch(des1,des2,k=2)

# 去除錯誤匹配
good = []
for m,n in matches:
    if m.distance <= 0.7*n.distance:
        good.append(m)

# 單應性
if len(good)>MIN_MATCH_COUNT:
    # 改變數組的表現形式,不改變數據內容,數據內容是每個關鍵點的坐標位置
    src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
    dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
    # findHomography 函數是計算變換矩陣
    # 參數cv2.RANSAC是使用RANSAC演算法尋找一個最佳單應性矩陣H,即返回值M
    # 返回值:M 為變換矩陣,mask是掩模
    M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
    # ravel方法將數據降維處理,最後並轉換成列表格式
    matchesMask = mask.ravel().tolist()
    # 獲取img1的圖像尺寸
    h,w,dim = img1.shape
    # pts是圖像img1的四個頂點
    pts = np.float32([[0,0],[0,h-1],[w-1,h-1],[w-1,0]]).reshape(-1,1,2)
    # 計算變換後的四個頂點坐標位置
    dst = cv2.perspectiveTransform(pts,M)

    # 根據四個頂點坐標位置在img2圖像畫出變換後的邊框
    img2 = cv2.polylines(img2,[np.int32(dst)],True,(0,0,255),3, cv2.LINE_AA)

else:
    print("Not enough matches are found - %d/%d") % (len(good),MIN_MATCH_COUNT)
    matchesMask = None

# 顯示匹配結果
draw_params = dict(matchColor = (0,255,0), # draw matches in green color
                   singlePointColor = None,
                   matchesMask = matchesMask, # draw only inliers
                   flags = 2)
img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
plt.figure(figsize=(20,20))
plt.imshow(cv2.cvtColor(img3,cv2.COLOR_BGR2RGB))
plt.show()

最後給大家放上原圖可以跑一下程式!

 

 

 

 

 

 

 

      

 

 

 

 

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • javaSE學習筆記(15) 緩衝流、轉換流、序列化流 緩衝流 昨天複習了基本的一些流,作為IO流的入門,今天我們要見識一些更強大的流。比如能夠高效讀寫的緩衝流,能夠轉換編碼的轉換流,能夠持久化存儲對象的序列化流等等。這些功能更為強大的流,都是在基本的流對象基礎之上創建而來的,相當於是對基本流對象的 ...
  • 楔子 假如我現在有一個列表l=['a','b','c','d','e'],我想取列表中的內容,有幾種方式? 首先,我可以通過索引取值l[0],其次我們是不是還可以用for迴圈來取值呀? 你有沒有仔細思考過,用索引取值和for迴圈取值是有著微妙區別的。 如果用索引取值,你可以取到任意位置的值,前提是你 ...
  • 楔子 作為一個會寫函數的python開發,我們從今天開始要去公司上班了。寫了一個函數,就交給其他開發用了。 def func1(): print('in func1') 季度末,公司的領導要給大家發績效獎金了,就提議對這段日子所有人開發的成果進行審核,審核的標準是什麼呢?就是統計每個函數的執行時間。 ...
  • 楔子 假如有一個函數,實現返回兩個數中的較大值: def my_max(x,y): m = x if x>y else y return mbigger = my_max(10,20)print(bigger) 之前是不是我告訴你們要把結果return回來你們就照做了?可是你們有沒有想過,我們為什麼 ...
  • 好久時間沒有做Django的項目了,今天創建項目竟然報Non-zero exit code(1)錯誤 查明原因是因為pip不是最新版本,需要執行以下命令:python -m pip install --upgrade pip 但還是沒有成功,提示超時,估計源有問題 使用豆瓣源進行安裝,問題解決了 命 ...
  • 前言最近由於疫情被困在家,於是準備每天看點專業知識,準備寫成博客,不定期發佈。博客大概會寫5~7篇,主要是“解剖”一些深度學習的底層技術。關於深度學習,電腦專業的人多少都會瞭解,知道Conv\Pool的過程,也看過論文,做過實驗或是解決方案。在寫的各種捲積網路 時候,有沒有問問自己:這些網路到底是... ...
  • 為什麼要用函數 現在python屆發生了一個大事件,len方法突然不能直接用了。。。 然後現在有一個需求,讓你計算'hello world'的長度,你怎麼計算? 這個需求對於現在的你其實不難,我們一起來寫一下。 s1 = "hello world" length = 0 for i in s1: l ...
  • 慕課網-悟空-玩轉Java併發工具,精通JUC,成為併發多面手-筆記 微雲:https://share.weiyun.com/81aa12bb98016e200add31fb8e191cdf百度網盤:鏈接:https://pan.baidu.com/s/1IiClTkQwFJgBL2NqlptKbA ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...