OpenCV | 附代码:使用 ORB 算法检测和跟踪对象

本文中,我将解释什么是ORB,何时应该使用它? 并演示如何使用ORB创建一个对象跟踪器。 文末附完整代码及C 实现。

本文中,我将解释什么是ORB,何时应该使用它?并演示如何使用ORB创建一个对象跟踪器。文末附完整代码及C++实现。

OpenCV | 附代码:使用 ORB 算法检测和跟踪对象

什么是ORB?

ORB(Oriented FAST and Rotated BRIEF)是一种用于计算机视觉的特征检测和描述算法。ORB旨在高效地检测和描述图像中的关键点(图像中独特且可识别的位置),使其在对象识别、跟踪和图像拼接等各种任务中非常有用。ORB结合了FAST关键点检测和BRIEF描述符中使用的技术:FAST(来自加速段测试的特征)和BRIEF(二进制鲁棒独立基本特征)。

在解释FAST和BRIEF之前,让我们简要讨论一下关键点检测和特征描述符。关键点检测是关于在图像中找到特殊且易于识别的点,而特征描述符则为我们提供了这些点周围内容的数值摘要。

现在让我们谈谈FAST和BRIEF算法。FAST是一种基于强度的角点检测算法,用于识别关键点,而BRIEF是一种为这些关键点生成二进制特征描述符的特征描述符。

OpenCV | 附代码:使用 ORB 算法检测和跟踪对象

ORB

ORB的优点

  • 速度:ORB非常快,适用于实时应用。
  • 尺度不变性:ORB还具有尺度不变性,使其能够在图像中检测不同尺度的特征。这使得它对物体或场景大小的变化具有鲁棒性。
  • 旋转不变性:ORB具有旋转不变性,这意味着无论图像中的方向如何,它都能检测和匹配特征。这使得它对视角的变化具有鲁棒性。
  • ORB不像SIFT或SURF那样受专利保护(在新的OpenCV版本中,SIFT和SURF也已经开源使用了),因此你可以在商业上使用它而无需支付费用。

ORB的缺点

  • 内存消耗:尽管ORB比一些替代方案更快,但它仍然可能消耗大量内存
  • 独特性有限:ORB可能难以区分看起来相似的特征,尤其是在具有重复模式或无纹理区域的场景中

OpenCV | 附代码:使用 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)

OpenCV | 附代码:使用 ORB 算法检测和跟踪对象

复制
# 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)

OpenCV | 附代码:使用 ORB 算法检测和跟踪对象

复制
# 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()

OpenCV | 附代码:使用 ORB 算法检测和跟踪对象

ORB

OpenCV | 附代码:使用 ORB 算法检测和跟踪对象

ORB官方论文中的图像

C++实现:https://github.com/siromermer/OpenCV-Projects-cpp-python/tree/master/opencv-projects-c%2B%2B/ObjectTracking-orb

相关资讯