本文中,我将解释什么是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