OpenCV | 附代碼:使用 ORB 算法檢測和跟蹤對象
本文中,我將解釋什么是ORB,何時應該使用它?并演示如何使用ORB創建一個對象跟蹤器。文末附完整代碼及C++實現。
什么是ORB?
ORB(Oriented FAST and Rotated BRIEF)是一種用于計算機視覺的特征檢測和描述算法。ORB旨在高效地檢測和描述圖像中的關鍵點(圖像中獨特且可識別的位置),使其在對象識別、跟蹤和圖像拼接等各種任務中非常有用。ORB結合了FAST關鍵點檢測和BRIEF描述符中使用的技術:FAST(來自加速段測試的特征)和BRIEF(二進制魯棒獨立基本特征)。
在解釋FAST和BRIEF之前,讓我們簡要討論一下關鍵點檢測和特征描述符。關鍵點檢測是關于在圖像中找到特殊且易于識別的點,而特征描述符則為我們提供了這些點周圍內容的數值摘要。
現在讓我們談談FAST和BRIEF算法。FAST是一種基于強度的角點檢測算法,用于識別關鍵點,而BRIEF是一種為這些關鍵點生成二進制特征描述符的特征描述符。
ORB
ORB的優點
- 速度:ORB非常快,適用于實時應用。
- 尺度不變性:ORB還具有尺度不變性,使其能夠在圖像中檢測不同尺度的特征。這使得它對物體或場景大小的變化具有魯棒性。
- 旋轉不變性:ORB具有旋轉不變性,這意味著無論圖像中的方向如何,它都能檢測和匹配特征。這使得它對視角的變化具有魯棒性。
- ORB不像SIFT或SURF那樣受專利保護(在新的OpenCV版本中,SIFT和SURF也已經開源使用了),因此你可以在商業上使用它而無需支付費用。
ORB的缺點
- 內存消耗:盡管ORB比一些替代方案更快,但它仍然可能消耗大量內存
- 獨特性有限:ORB可能難以區分看起來相似的特征,尤其是在具有重復模式或無紋理區域的場景中
ORB
主要邏輯
FAST算法識別圖像中獨特且可識別的關鍵點,然后BRIEF算法基于這些關鍵點生成特征描述符。這些描述符使得能夠在不同圖像中匹配相似的對象。通過比較這些描述符,你可以創建自己的自定義對象跟蹤器。
對象跟蹤器如何工作?
想象一下,你想在視頻中跟蹤一架飛機。首先,獲取你的目標圖像(飛機)并找到其關鍵點和描述符。然后,對于視頻的每一幀,找到關鍵點和描述符。接下來,將目標圖像的描述符與每一幀的描述符進行比較。如果兩者之間有匹配,則在相應的坐標上繪制形狀。
使用ORB進行對象跟蹤/檢測的步驟
- 選擇一張僅包含你想要檢測和跟蹤的對象的圖像。例如,如果你想檢測一架飛機,選擇一張僅包含飛機的圖像。避免使用包含多個對象的圖像,例如機場場景,其中可能包含人、汽車和燈光等干擾物。使用這樣的圖像可能會導致FAST算法檢測到大量不相關的關鍵點,從而導致跟蹤器性能不佳。
- 選擇合適圖像后,FAST算法識別圖像中獨特且可識別的關鍵點,BRIEF算法基于這些關鍵點生成特征描述符。保存目標圖像的關鍵點和描述符。
- 現在讀取你的視頻(我將使用OpenCV),對于每一幀,將第一步中獲得的描述符與當前幀中提取的描述符進行比較。如果某些描述符之間存在匹配,則在匹配描述符對應的坐標上繪制一個圓圈。
現在,我將使用OpenCV庫中的ORB算法創建一個對象跟蹤器,但在那之前,我有一個小提醒,你需要知道何時不應該使用ORB。
在使用ORB之前
在項目中使用ORB之前,你必須意識到一些事情。如果你想使用ORB檢測或跟蹤對象,背景必須清晰,例如天空或道路。如果背景雜亂,包含行人、動物或其他對象,你的算法將找到大量關鍵點,從而顯著降低速度和FPS(每秒幀數)。這使得它在實時應用中不切實際。
使用ORB算法的對象跟蹤器
(1) 安裝相關庫
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++實現:https://github.com/siromermer/OpenCV-Projects-cpp-python/tree/master/opencv-projects-c%2B%2B/ObjectTracking-orb