OpenCV-Python实战(16)——人脸追踪详解

x33g5p2x  于2021-11-09 转载在 Python  
字(5.3k)|赞(0)|评价(0)|浏览(948)

0. 前言

人脸处理是人工智能中的一个热门话题,人脸处理可以使用计算机视觉算法从人脸中自动提取大量信息,例如身份、意图和情感;而目标跟踪试图估计目标在整个视频序列中的轨迹,其中只有目标的初始位置是已知的,将这两者进行结合将产生许多有趣的应用。由于外观变化、遮挡、快速运动、运动模糊和比例变化等多种因素,人脸追踪非常具有挑战性。

1. 人脸追踪技术简介

基于判别相关滤波器 (discriminative correlation filter, DCF) 的视觉跟踪器具有优异的性能和较高的计算效率,可用于实时应用程序。DCF 跟踪器是一种非常流行的基于边界框跟踪的方法。
dlib 库中实现了基于 DCF 的跟踪器,可以很方便的将其用于对象跟踪。在本文中,我们将介绍如何使用此跟踪器进行人脸和用户选择对象的跟踪,这种方法也称为判别尺度空间跟踪器 (Discriminative Scale Space Tracker, DSST),追踪器仅需要输入原始视频和目标初始位置的边界框,然后跟踪器自动预测目标的轨迹。

2. 使用基于 dlib DCF 的跟踪器进行人脸跟踪

在进行人脸追踪时,我们首先使用 dlib 人脸检测器进行初始化,然后使用基于 dlib DCF 的跟踪器 DSST 进行人脸跟踪。调用以下函数初始化相关跟踪器:

  1. tracker = dlib.correlation_tracker()

这将使用默认值 (filter_size = 6, num_scale_levels = 5, scale_window_size = 23, regularizer_space = 0.001, nu_space = 0.025, regularizer_scale = 0.001, nu_scale = 0.025, scale_pyramid_alpha = 1.020) 初始化跟踪器。 filter_sizenum_scale_levels 的值越大,跟踪精度越高,但它需要算力也更大;filter_size 的推荐使用值为 567num_scale_levels 的推荐使用值为 456
使用 tracker.start_track() 可以开始跟踪。在开始追踪前,我们需要先执行人脸检测,并将检测到的人脸位置传递给这个方法:

  1. if tracking_face is False:
  2. gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  3. # 尝试检测人脸以初始化跟踪器
  4. rects = detector(gray, 0)
  5. # 检查是否检测到人脸
  6. if len(rects) > 0:
  7. # 开始追踪
  8. tracker.start_track(frame, rects[0])
  9. tracking_face = True

当检测到人脸后,人脸跟踪器将开始跟踪边界框内的内容。为了更新被跟踪对象的位置,需要调用 tracker.update() 方法:

  1. tracker.update(frame)

tracker.update() 方法更新跟踪器并返回衡量跟踪器置信度的指标,此指标可用于使用人脸检测重新初始化跟踪器。
要获取被跟踪对象的位置,需要调用 tracker.get_position() 方法:

  1. pos = tracker.get_position()

tracker.get_position() 方法返回被跟踪对象的位置。最后,绘制人脸的预测位置:

  1. cv2.rectangle(frame, (int(pos.left()), int(pos.top())), (int(pos.right()), int(pos.bottom())), (0, 255, 0), 3)

下图中,显示了人脸跟踪算法的跟踪效果过程:

在上图中,可以看到算法当前正在跟踪检测到的人脸,同时还可以按数字 1 以重新初始化跟踪。

2.1 完整代码

完整代码如下所示,同时我们需要提供按下数字 1 时重新初始化跟踪器的选项。

  1. import cv2
  2. import dlib
  3. def draw_text_info():
  4. # 绘制文本的位置
  5. menu_pos_1 = (10, 20)
  6. menu_pos_2 = (10, 40)
  7. # 绘制菜单信息
  8. cv2.putText(frame, "Use '1' to re-initialize tracking", menu_pos_1, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255))
  9. if tracking_face:
  10. cv2.putText(frame, "tracking the face", menu_pos_2, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0))
  11. else:
  12. cv2.putText(frame, "detecting a face to initialize tracking...", menu_pos_2, cv2.FONT_HERSHEY_SIMPLEX, 0.5,
  13. (0, 0, 255))
  14. # 创建视频捕获对象
  15. capture = cv2.VideoCapture(0)
  16. # 加载人脸检测器
  17. detector = dlib.get_frontal_face_detector()
  18. # 初始化追踪器
  19. tracker = dlib.correlation_tracker()
  20. # 当前是否在追踪人脸
  21. tracking_face = False
  22. while True:
  23. # 捕获视频帧
  24. ret, frame = capture.read()
  25. # 绘制基本信息
  26. draw_text_info()
  27. if tracking_face is False:
  28. gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
  29. # 尝试检测人脸以初始化跟踪器
  30. rects = detector(gray, 0)
  31. # 通过判断是否检测到人脸来决定是否启动追踪
  32. if len(rects) > 0:
  33. # Start tracking:
  34. tracker.start_track(frame, rects[0])
  35. tracking_face = True
  36. if tracking_face is True:
  37. # 更新跟踪器并打印测量跟踪器的置信度
  38. print(tracker.update(frame))
  39. # 获取被跟踪对象的位置
  40. pos = tracker.get_position()
  41. # 绘制被跟踪对象的位置
  42. cv2.rectangle(frame, (int(pos.left()), int(pos.top())), (int(pos.right()), int(pos.bottom())), (0, 255, 0), 3)
  43. # 捕获键盘事件
  44. key = 0xFF & cv2.waitKey(1)
  45. # 按 1 初始化追踪器
  46. if key == ord("1"):
  47. tracking_face = False
  48. # 按 q 退出
  49. if key == ord('q'):
  50. break
  51. # 显示结果
  52. cv2.imshow("Face tracking using dlib frontal face detector and correlation filters for tracking", frame)
  53. # 释放所有资源
  54. capture.release()
  55. cv2.destroyAllWindows()

3. 使用基于 dlib DCF 的跟踪器进行对象跟踪

除了人脸外,基于 dlib DCF 的跟踪器可以用于跟踪任意对象。接下来,我们使用鼠标选择要跟踪的对象,并监听键盘事件,如果按 1,将开始跟踪预定义边界框内的对象;如果按 2,预定义的边界框将被清空,跟踪算法将停止,并等待用户选择另一个边界框。
例如,我们对检测小姐姐并不感兴趣,而更喜欢猫,那么我们可以首先用鼠标绘制矩形框选择喵咪,然后按 1 开始追踪小猫咪,如果我们想要追踪其他物体,可以按 2 重新绘制矩形框并进行追踪。如下所示,我们可以看到算法跟踪对象并进行实时输出:

3.2 完整代码

完整代码如下所示:

  1. import cv2
  2. import dlib
  3. def draw_text_info():
  4. # 绘制文本的位置
  5. menu_pos_1 = (10, 20)
  6. menu_pos_2 = (10, 40)
  7. menu_pos_3 = (10, 60)
  8. # 菜单项
  9. info_1 = "Use left click of the mouse to select the object to track"
  10. info_2 = "Use '1' to start tracking, '2' to reset tracking and 'q' to exit"
  11. # 绘制菜单信息
  12. cv2.putText(frame, "Use '1' to re-initialize tracking", menu_pos_1, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255))
  13. cv2.putText(frame, info_2, menu_pos_2, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255))
  14. if tracking_state:
  15. cv2.putText(frame, "tracking", menu_pos_3, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0))
  16. else:
  17. cv2.putText(frame, "not tracking", menu_pos_3, cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255))
  18. # 用于保存要跟踪的对象坐标的结构
  19. points = []
  20. def mouse_event_handler(event, x, y, flags, param):
  21. # 对全局变量的引用
  22. global points
  23. # 添加要跟踪的对象的左上角坐标
  24. if event == cv2.EVENT_LBUTTONDOWN:
  25. points = [(x, y)]
  26. # 添加要跟踪的对象的右下角坐标:
  27. elif event == cv2.EVENT_LBUTTONUP:
  28. points.append((x, y))
  29. # 创建视频捕获对象
  30. capture = cv2.VideoCapture(0)
  31. # 窗口名
  32. window_name = "Object tracking using dlib correlation filter algorithm"
  33. # 创建窗口
  34. cv2.namedWindow(window_name)
  35. # 绑定鼠标事件
  36. cv2.setMouseCallback(window_name, mouse_event_handler)
  37. # 初始化跟踪器
  38. tracker = dlib.correlation_tracker()
  39. tracking_state = False
  40. while True:
  41. # 捕获视频帧
  42. ret, frame = capture.read()
  43. # 绘制菜单项
  44. draw_text_info()
  45. # 设置并绘制一个矩形,跟踪矩形框内的对象
  46. if len(points) == 2:
  47. cv2.rectangle(frame, points[0], points[1], (0, 0, 255), 3)
  48. dlib_rectangle = dlib.rectangle(points[0][0], points[0][1], points[1][0], points[1][1])
  49. if tracking_face is True:
  50. # 更新跟踪器并打印测量跟踪器的置信度
  51. print(tracker.update(frame))
  52. # 获取被跟踪对象的位置
  53. pos = tracker.get_position()
  54. # 绘制被跟踪对象的位置
  55. cv2.rectangle(frame, (int(pos.left()), int(pos.top())), (int(pos.right()), int(pos.bottom())), (0, 255, 0), 3)
  56. # 捕获键盘事件
  57. key = 0xFF & cv2.waitKey(1)
  58. # 按下 1 键,开始追踪
  59. if key == ord("1"):
  60. if len(points) == 2:
  61. # Start tracking:
  62. tracker.start_track(frame, dlib_rectangle)
  63. tracking_state = True
  64. points = []
  65. # 按下 2 键,停止跟踪
  66. if key == ord("2"):
  67. points = []
  68. tracking_state = False
  69. # 按下 q 键,返回
  70. if key == ord('q'):
  71. break
  72. # 展示结果图像
  73. cv2.imshow(window_name, frame)
  74. # 释放资源
  75. capture.release()
  76. cv2.destroyAllWindows()

小结

dlib 库实现了基于 DCF 的跟踪器,非常适合用于进行人脸追踪,使用 dlib.correlation_tracker() 函数初始化跟踪器,tracker.start_track() 函数用于开始追踪对象,tracker.update() 函数更新追踪器并且返回追踪器置信度,若要获取被跟踪对象的位置需要使用 tracker.get_position() 函数。

相关文章