OpenCV | 附代碼:使用 ORB 算法檢測(cè)和跟蹤對(duì)象
本文中,我將解釋什么是ORB,何時(shí)應(yīng)該使用它?并演示如何使用ORB創(chuàng)建一個(gè)對(duì)象跟蹤器。文末附完整代碼及C++實(shí)現(xiàn)。
什么是ORB?
ORB(Oriented FAST and Rotated BRIEF)是一種用于計(jì)算機(jī)視覺的特征檢測(cè)和描述算法。ORB旨在高效地檢測(cè)和描述圖像中的關(guān)鍵點(diǎn)(圖像中獨(dú)特且可識(shí)別的位置),使其在對(duì)象識(shí)別、跟蹤和圖像拼接等各種任務(wù)中非常有用。ORB結(jié)合了FAST關(guān)鍵點(diǎn)檢測(cè)和BRIEF描述符中使用的技術(shù):FAST(來自加速段測(cè)試的特征)和BRIEF(二進(jìn)制魯棒獨(dú)立基本特征)。
在解釋FAST和BRIEF之前,讓我們簡要討論一下關(guān)鍵點(diǎn)檢測(cè)和特征描述符。關(guān)鍵點(diǎn)檢測(cè)是關(guān)于在圖像中找到特殊且易于識(shí)別的點(diǎn),而特征描述符則為我們提供了這些點(diǎn)周圍內(nèi)容的數(shù)值摘要。
現(xiàn)在讓我們談?wù)凢AST和BRIEF算法。FAST是一種基于強(qiáng)度的角點(diǎn)檢測(cè)算法,用于識(shí)別關(guān)鍵點(diǎn),而BRIEF是一種為這些關(guān)鍵點(diǎn)生成二進(jìn)制特征描述符的特征描述符。
ORB
ORB的優(yōu)點(diǎn)
- 速度:ORB非???,適用于實(shí)時(shí)應(yīng)用。
- 尺度不變性:ORB還具有尺度不變性,使其能夠在圖像中檢測(cè)不同尺度的特征。這使得它對(duì)物體或場(chǎng)景大小的變化具有魯棒性。
- 旋轉(zhuǎn)不變性:ORB具有旋轉(zhuǎn)不變性,這意味著無論圖像中的方向如何,它都能檢測(cè)和匹配特征。這使得它對(duì)視角的變化具有魯棒性。
- ORB不像SIFT或SURF那樣受專利保護(hù)(在新的OpenCV版本中,SIFT和SURF也已經(jīng)開源使用了),因此你可以在商業(yè)上使用它而無需支付費(fèi)用。
ORB的缺點(diǎn)
- 內(nèi)存消耗:盡管ORB比一些替代方案更快,但它仍然可能消耗大量內(nèi)存
- 獨(dú)特性有限:ORB可能難以區(qū)分看起來相似的特征,尤其是在具有重復(fù)模式或無紋理區(qū)域的場(chǎng)景中
ORB
主要邏輯
FAST算法識(shí)別圖像中獨(dú)特且可識(shí)別的關(guān)鍵點(diǎn),然后BRIEF算法基于這些關(guān)鍵點(diǎn)生成特征描述符。這些描述符使得能夠在不同圖像中匹配相似的對(duì)象。通過比較這些描述符,你可以創(chuàng)建自己的自定義對(duì)象跟蹤器。
對(duì)象跟蹤器如何工作?
想象一下,你想在視頻中跟蹤一架飛機(jī)。首先,獲取你的目標(biāo)圖像(飛機(jī))并找到其關(guān)鍵點(diǎn)和描述符。然后,對(duì)于視頻的每一幀,找到關(guān)鍵點(diǎn)和描述符。接下來,將目標(biāo)圖像的描述符與每一幀的描述符進(jìn)行比較。如果兩者之間有匹配,則在相應(yīng)的坐標(biāo)上繪制形狀。
使用ORB進(jìn)行對(duì)象跟蹤/檢測(cè)的步驟
- 選擇一張僅包含你想要檢測(cè)和跟蹤的對(duì)象的圖像。例如,如果你想檢測(cè)一架飛機(jī),選擇一張僅包含飛機(jī)的圖像。避免使用包含多個(gè)對(duì)象的圖像,例如機(jī)場(chǎng)場(chǎng)景,其中可能包含人、汽車和燈光等干擾物。使用這樣的圖像可能會(huì)導(dǎo)致FAST算法檢測(cè)到大量不相關(guān)的關(guān)鍵點(diǎn),從而導(dǎo)致跟蹤器性能不佳。
- 選擇合適圖像后,F(xiàn)AST算法識(shí)別圖像中獨(dú)特且可識(shí)別的關(guān)鍵點(diǎn),BRIEF算法基于這些關(guān)鍵點(diǎn)生成特征描述符。保存目標(biāo)圖像的關(guān)鍵點(diǎn)和描述符。
- 現(xiàn)在讀取你的視頻(我將使用OpenCV),對(duì)于每一幀,將第一步中獲得的描述符與當(dāng)前幀中提取的描述符進(jìn)行比較。如果某些描述符之間存在匹配,則在匹配描述符對(duì)應(yīng)的坐標(biāo)上繪制一個(gè)圓圈。
現(xiàn)在,我將使用OpenCV庫中的ORB算法創(chuàng)建一個(gè)對(duì)象跟蹤器,但在那之前,我有一個(gè)小提醒,你需要知道何時(shí)不應(yīng)該使用ORB。
在使用ORB之前
在項(xiàng)目中使用ORB之前,你必須意識(shí)到一些事情。如果你想使用ORB檢測(cè)或跟蹤對(duì)象,背景必須清晰,例如天空或道路。如果背景雜亂,包含行人、動(dòng)物或其他對(duì)象,你的算法將找到大量關(guān)鍵點(diǎn),從而顯著降低速度和FPS(每秒幀數(shù))。這使得它在實(shí)時(shí)應(yīng)用中不切實(shí)際。
使用ORB算法的對(duì)象跟蹤器
(1) 安裝相關(guān)庫
import cv2
import matplotlib.pyplot as plt
import numpy as np
import time
image = cv2.imread("helicopter_roi.png")
gray_image = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
rgb_image =cv2.cvtColor(image,cv2.COLOR_BGR2RGB)
plt.imshow(rgb_image)
# Initiate ORB
orb = cv2.ORB_create()
# find the keypoints with ORB
keypoints_1, descriptors_1 = orb.detectAndCompute(gray_image, None)
# draw only keypoints location,not size and orientation
img2 = cv2.drawKeypoints(rgb_image,keypoints,None,color=(0,255,0), flags=0)
plt.imshow(img2)
# path to video
video_path="helicopter_2.mp4"
video = cv2.VideoCapture(video_path)
# Initialize variables for FPS calculation
t0 = time.time()
n_frames = 1
# Initiate
orb = cv2.ORB_create()
# matcher object
bf = cv2.BFMatcher()
while True :
# reading video
ret,frame=video.read()
if ret:
# convert frame to gray scale
frame_gray=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
# compute the descriptors with BRIEF
keypoints_2, descriptors_2 = orb.detectAndCompute(frame_gray, None)
"""
Compare the keypoints/descriptors extracted from the
first frame(from target object) with those extracted from the current frame.
"""
matches =bf.match(descriptors_1, descriptors_2)
for match in matches:
# queryIdx gives keypoint index from target image
query_idx = match.queryIdx
# .trainIdx gives keypoint index from current frame
train_idx = match.trainIdx
# take coordinates that matches
pt1 = keypoints_1[query_idx].pt
# current frame keypoints coordinates
pt2 = keypoints_2[train_idx].pt
# draw circle to pt2 coordinates , because pt2 gives current frame coordinates
cv2.circle(frame,(int(pt2[0]),int(pt2[1])),2,(255,0,0),2)
elapsed_time = time.time() - t0
avg_fps = (n_frames / elapsed_time)
print("Average FPS: " + str(avg_fps))
cv2.putText(frame, str(avg_fps) , (50,50) , cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0), 1, cv2.LINE_AA)
n_frames += 1
#cv2.putText(frame,f"FPS :{str(avg_fps)}" , (50,50) , cv2.FONT_HERSHEY_SIMPLEX,1,(255,255,0), 2, cv2.LINE_AA)
cv2.imshow("coordinate_screen",frame)
k = cv2.waitKey(5) & 0xFF # after drawing rectangle press esc
if k == 27:
cv2.destroyAllWindows()
break
else:
break
cv2.destroyAllWindows()
ORB
ORB官方論文中的圖像
C++實(shí)現(xiàn):https://github.com/siromermer/OpenCV-Projects-cpp-python/tree/master/opencv-projects-c%2B%2B/ObjectTracking-orb