关于对象检测,我们以前分享的文章都是介绍的2D的对象检测,但是我们很多使用场景下,希望检测到的对象能够以3D的影像呈现出来,本期介绍的MediaPipe Objectron便是是用于日常对象的移动实时3D对象检测解决方案。它检测2D图像中的对象,并通过在Objectron数据集上训练的机器学习(ML)模型估计其3D姿势。
3D对象检测
对象检测是一个广泛研究的计算机视觉问题,但是大多数研究都集中在2D对象预测上。虽然2D预测仅提供2D边界框,但通过将预测扩展到3D,人们可以捕获物体在世界上的大小,位置和方向,从而可以使用在机器人技术,自动驾驶汽车,图像检索和增强现实中的各种应用。尽管2D对象检测相对成熟并且已在行业中广泛使用,但是由于缺乏数据以及类别中对象的外观和形状的多样性,从2D图像进行3D对象检测仍然是一个具有挑战性的问题。
MediaPipe Objectron
用于3D对象检测的ML管道
MediaPipe建立了两个ML管道来从单个RGB图像预测对象的3D边界框:一个是两阶段的管道,另一个是单阶段的管道。两级比单级快3倍,且精度相似或更高。单级擅长检测多个对象,而两级擅长于单个对象。
两级管道
下图说明了MediaPipe的两阶模型管道。第一阶段使用对象检测器来找到对象的2D裁剪。第二阶段进行图像裁剪并估计3D边界框。同时,它还为下一帧计算对象的2D裁剪,从而使对象检测器不需要每帧都运行。
MediaPipe的两阶模型管道
单级管道
MediaPipe的单级管道 |
上图说明了MediaPipe的单级管道,该模型主干具基于MobileNetv2构建的编码器-解码器体系结构。MediaPipe采用多任务学习方法,通过检测和回归共同预测对象的形状。
当将模型应用于移动设备捕获的每个帧时,由于每个帧中估计的3D边界框的歧义性,模型可能会发生抖动。为了减轻这种情况,MediaPipe在MediaPipe Box Tracking中的2D对象检测和跟踪管道中采用了相同的检测+跟踪策略。这减轻了在每个帧上运行网络的需要,从而允许使用更重的模型,因此可以使用更准确的模型,同时在移动设备上保持管道的实时性。它还可以跨帧保留对象身份,并确保预测在时间上保持一致,从而减少了抖动。
3d对象检测
使用python代码实现MediaPipe的3D对象检测
当然在进行本期文章前,首先需要安装MediaPipe,安装MediaPipe可以直接在cmd命令框中输入如下
Python –m pip install MediaPipe,等待系统自动安装即可,这里需要提醒一下由于最新的MediaPipe版本不再支持以下的版本,所以MediaPipe的代码最好运行在以上版本
import cv2 import mediapipe as mp mp_drawing = mp. mp_objectron = mp.
# 图片检测 with m(static_image_mode=True, max_num_objects=5, min_detection_confidence=0.5, model_name='Shoe') as objectron:
代码截图
首先我们插入需要的第三方库,然后使用mp.建立一个objectron 3D对象检测模型
此模型函数主要包括如下参数:
STATIC_IMAGE_MODE
如果设置为false,则检测对象为视频流。它将尝试在最开始的图像中检测对象,并在成功检测后进一步定位3D边界框界标。在随后的图像中,一旦检测到所有max_num_objects个对象并定位了相应的3D边界框地标,它便会简单地跟踪那些地标,而无需调用另一次检测,直到失去对任何对象的跟踪为止。这减少了检测时间,是处理视频帧的理想选择。如果设置为true,则对象检测为图像,非常适合处理一批静态的,可能不相关的图像。预设为false。
MAX_NUM_OBJECTS
要检测的最大对象数。预设为5。
MIN_DETECTION_CONFIDENCE
[0.0, 1.0]对象检测模型的最小置信度值,预设为0.5。
MIN_TRACKING_CONFIDENCE
[0.0, 1.0]来自地标跟踪模型的3D边界框地标的最小置信度值,否则将在下一个输入图像上自动调用对象检测。将其设置为更高的值可以提高解决方案的健壮性,但代价是更多的代码运行时间。如果static_image_mode为true,则忽略该对象检测仅在每个图像上运行。预设为0.99。
3D对象检测
Model名称
用于预测3D边界框界标的模型的名称。目前支持{'Shoe', 'Chair', 'Cup', 'Camera'}。
焦距
(fx, fy)默认情况下,相机焦距是在NDC空间中定义的。要(fx_pixel, fy_pixel)在像素空间中使用焦距,用户应提供image_size=(image_width, image_height)以启用API内的转换。
主体点
(px, py)默认情况下,摄像机主点在NDC空间中定义。要(px_pixel, py_pixel)在像素空间中使用主点,用户应提供image_size=(image_width, image_height)来启用API内的转换。
图片大小
(可选)(image_width, image_height)输入图像的大小,仅在使用时focal_length和principal_point像素空间中需要。
3d对象检测
for idx, file in enumerate(file_list): image = cv2.imread(file) # 转换图片到RGB空间 results = objec(image, cv2.COLOR_BGR2RGB)) # 画出检测结果 if not re: continue print(f'Box landmarks of {file}:') annotated_image = image.copy()
代码截图
然后我们遍历file_list文件夹中的图片,进行图片的读取,然后使用cv2.cvtColor(image, cv2.COLOR_BGR2RGB)函数进行图片的RGB颜色空间的转换,这里是因为OpenCV的颜色空间是BGR,而后期开发的第三方库一般是RGB颜色空间,同样的mediapipe支持RGB颜色空间,因此这里我们需要转换图片的颜色空间到RGB格式
最后使用objec函数对图片进行3D对象的检测,结果保存在results中,objec函数返回值主要包括如下参数:
DETECTED_OBJECTS
检测到的3D边界框的列表。每个3D边界框都包含以下内容:
- landmarks_2d:对象3D边界框的2D地标。界标坐标分别[0.0, 1.0]通过图像的宽度和高度进行归一化。
- landmarks_3d:对象的3D边界框的3D地标。界标坐标表示在摄像机坐标系中。
- rotation :从对象坐标系到摄像机坐标系的旋转矩阵。
- translation :从对象坐标系到摄像机坐标系的平移向量。
- scale:对象的相对比例沿x,y和z方向。
获取到results后,我们就可以遍历检测的结果,使用m函数对检测到的图片进行3D对象的绘图
for detected_object in re: m( annotated_image, de, m) m(annotated_image, de, de) cv2.imwrite('/tmp/annotated_image' + str(idx) + '.png', annotated_image) cv2.imshow('annotated_image',annotated_image) cv2.waitKey(0)
代码截图
3d对象检测
当然,3D对象检测与追踪同样支持视频流的实时检测
import cv2 import mediapipe as mp mp_drawing = mp. mp_objectron = mp. # 视频检测 cap = cv2.VideoCapture(0) with m(static_image_mode=False, max_num_objects=5, min_detection_confidence=0.5, min_tracking_confidence=0.99, model_name='Shoe') as objectron:
代码截图
与图片检测类似,我们首先导入需要的第三方库以及建立一个3D对象检测模型函数,然后使用cv2.VideoCapture(0)函数打开设备的默认摄像头,这里0便是代表设备的默认的第一个摄像头,当然这里也可以传递一个视频的地址,便可以检测视频
while cap.isOpened(): success, image = cap.read() if not success: continue # BGR 图片转换到 RGB. image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # 为了提高性能,可以选择将图像标记为不可写,以便通过引用传递 image. = False results = objec(image)
代码截图
当默认摄像头被打开后,我们便可以从视频流中获取每帧的图片,然后按照图片检测的模式进行3D模型的检测,当然在视频检测时,我们为了提高检测的性能,我们需要暂时关闭图片的写权限,然后使用objec函数对视频帧中的图片进行检测,检测的结果保存在results中
# 画出检测结果 image. = True image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR) if re: for detected_object in re: m( image, de, m) m(image, de, de) cv2.imshow('MediaPipe Objectron', image) if cv2.waitKey(5) & 0xFF == ord('q'): break cap.release()
代码截图
然后我们打开图片的写权限,遍历图片检测结果,使用m与m画图函数,画出我们检测的结果
每个视频帧的检测结果加起来,便可以完整地呈现出视频检测的结果了。
其他文章参考
利用机器学习,进行人体33个2D姿态检测与评估
利用机器学习,进行人手的21个3D手关节坐标检测
利用机器学习进行人脸468点的3D坐标检测,并生成3D模型
MediaPipe 集成人脸识别,人体姿态评估,人手检测模型