带有面部检测和形状预测的 Dlib 网络摄像头捕获速度很慢
Dlib webcam capture with face detection and shape prediction is slow
我正在用 C++ 开发一个程序,它应该从网络摄像头流中检测人脸,而不是使用人脸界标裁剪它们并交换它们。
我使用 OpenCV 和 Viola-Jones 人脸检测对人脸检测进行了编程。工作正常。比我搜索如何从 ROI 中分割面孔。我尝试了一些皮肤检测实现,但 none 成功了。
比我发现了 dlib 面部标志。我决定试一试。刚开始我遇到了问题,因为我必须将 cv::Mat
转换为 cv_image
,将 Rect 转换为 rectangle 等。所以我尝试只使用 dlib 来完成。我只是使用 cv::VideoCapture
获取流,而不是我想显示使用 dlib image_window
捕获的内容。但问题是它真的很慢。下面是使用过的代码。注释行是执行相同但使用 OpenCV 的行。 OpenCV 比没有注释的代码更快、更流畅、更连续,大约 5 FPS。那太糟了。我无法想象当我应用人脸检测和人脸标志时会有多慢。
我做错了什么吗?我怎样才能让它更快?或者我应该使用 OpenCV 进行视频捕获和显示?
cv::VideoCapture cap;
image_window output_frame;
if (!cap.open(0))
{
cout << "ERROR: Opening video device 0 FAILED." << endl;
return -1;
}
cv::Mat cap_frame;
//HWND hwnd;
do
{
cap >> cap_frame;
if (!cap_frame.empty())
{
cv_image<bgr_pixel> dlib_frame(cap_frame);
output_frame.set_image(dlib_frame);
//cv::imshow("output",dlib::toMat(dlib_frame));
}
//if (27 == char(cv::waitKey(10)))
//{
// return 0;
//}
//hwnd = FindWindowA(NULL, "output");
} while(!output_frame.is_closed())//while (hwnd != NULL);
编辑:
切换到 Release 模式后,显示捕获的帧变得很好。
但我继续尝试使用 dlib 进行 面部检测 和 形状预测 就像这里的示例一样http://dlib.net/face_landmark_detection_ex.cpp.html。这是相当滞后。所以我关闭了形状预测。仍然“滞后。
所以我假设人脸检测正在减慢它的速度。所以我 尝试使用 OpenCV 进行人脸检测,因为它 明显优于 dlib 检测器 。我需要将检测到的 cv::Rect 转换为 dlib::rectangle。我用过这个。
std::vector<dlib::rectangle> dlib_rois;
long l, t, r, b;
for (int i = cv_rois.size() - 1; i >= 0; i--)
{
l = cv_rois[i].x;
t = cv_rois[i].y;
r = cv_rois[i].x + cv_rois[i].width;
b = cv_rois[i].y + cv_rois[i].height;
dlib_rois.push_back(dlib::rectangle(l, t, r, b));
}
但是 OpenCV 人脸检测 和 dlib 形状预测 的组合变得非常迟钝。处理单帧大约需要4s。
我不明白为什么。 OpenCV 人脸检测非常好,dlib 形状预测似乎并不难处理。有人可以帮我吗?
在假设它很慢之前,您可以采取一些措施使 Dlib 运行 更快。您只需要阅读更多文档并尝试即可。
Dlib 能够在非常小的区域(80x80 像素)检测人脸。您可能发送分辨率约为 1280x720 的原始网络摄像头帧,这不是必需的。根据我的经验,我建议将帧减少到原始分辨率的四分之一左右。是的,320x180 适合 Dlib。因此,您将获得 4 倍的速度。
正如评论中提到的,通过在构建 Dlib 时打开编译优化,您将获得显着的速度提升。
Dlib 处理灰度图像的速度更快。您不需要网络摄像头框架上的颜色。您可以使用 OpenCV 将之前缩小尺寸的帧转换为灰度。
Dlib 需要时间来寻找人脸,但在人脸上寻找地标的速度非常快。仅当您的网络摄像头提供高帧率 (24-30fps) 时,您才可以跳过一些帧,因为面部通常不会移动太多。
鉴于优化,我相信您的检测速度至少会提高 12 倍。
我正在用 C++ 开发一个程序,它应该从网络摄像头流中检测人脸,而不是使用人脸界标裁剪它们并交换它们。
我使用 OpenCV 和 Viola-Jones 人脸检测对人脸检测进行了编程。工作正常。比我搜索如何从 ROI 中分割面孔。我尝试了一些皮肤检测实现,但 none 成功了。
比我发现了 dlib 面部标志。我决定试一试。刚开始我遇到了问题,因为我必须将 cv::Mat
转换为 cv_image
,将 Rect 转换为 rectangle 等。所以我尝试只使用 dlib 来完成。我只是使用 cv::VideoCapture
获取流,而不是我想显示使用 dlib image_window
捕获的内容。但问题是它真的很慢。下面是使用过的代码。注释行是执行相同但使用 OpenCV 的行。 OpenCV 比没有注释的代码更快、更流畅、更连续,大约 5 FPS。那太糟了。我无法想象当我应用人脸检测和人脸标志时会有多慢。
我做错了什么吗?我怎样才能让它更快?或者我应该使用 OpenCV 进行视频捕获和显示?
cv::VideoCapture cap;
image_window output_frame;
if (!cap.open(0))
{
cout << "ERROR: Opening video device 0 FAILED." << endl;
return -1;
}
cv::Mat cap_frame;
//HWND hwnd;
do
{
cap >> cap_frame;
if (!cap_frame.empty())
{
cv_image<bgr_pixel> dlib_frame(cap_frame);
output_frame.set_image(dlib_frame);
//cv::imshow("output",dlib::toMat(dlib_frame));
}
//if (27 == char(cv::waitKey(10)))
//{
// return 0;
//}
//hwnd = FindWindowA(NULL, "output");
} while(!output_frame.is_closed())//while (hwnd != NULL);
编辑: 切换到 Release 模式后,显示捕获的帧变得很好。 但我继续尝试使用 dlib 进行 面部检测 和 形状预测 就像这里的示例一样http://dlib.net/face_landmark_detection_ex.cpp.html。这是相当滞后。所以我关闭了形状预测。仍然“滞后。
所以我假设人脸检测正在减慢它的速度。所以我 尝试使用 OpenCV 进行人脸检测,因为它 明显优于 dlib 检测器 。我需要将检测到的 cv::Rect 转换为 dlib::rectangle。我用过这个。
std::vector<dlib::rectangle> dlib_rois;
long l, t, r, b;
for (int i = cv_rois.size() - 1; i >= 0; i--)
{
l = cv_rois[i].x;
t = cv_rois[i].y;
r = cv_rois[i].x + cv_rois[i].width;
b = cv_rois[i].y + cv_rois[i].height;
dlib_rois.push_back(dlib::rectangle(l, t, r, b));
}
但是 OpenCV 人脸检测 和 dlib 形状预测 的组合变得非常迟钝。处理单帧大约需要4s。
我不明白为什么。 OpenCV 人脸检测非常好,dlib 形状预测似乎并不难处理。有人可以帮我吗?
在假设它很慢之前,您可以采取一些措施使 Dlib 运行 更快。您只需要阅读更多文档并尝试即可。
Dlib 能够在非常小的区域(80x80 像素)检测人脸。您可能发送分辨率约为 1280x720 的原始网络摄像头帧,这不是必需的。根据我的经验,我建议将帧减少到原始分辨率的四分之一左右。是的,320x180 适合 Dlib。因此,您将获得 4 倍的速度。
正如评论中提到的,通过在构建 Dlib 时打开编译优化,您将获得显着的速度提升。
Dlib 处理灰度图像的速度更快。您不需要网络摄像头框架上的颜色。您可以使用 OpenCV 将之前缩小尺寸的帧转换为灰度。
Dlib 需要时间来寻找人脸,但在人脸上寻找地标的速度非常快。仅当您的网络摄像头提供高帧率 (24-30fps) 时,您才可以跳过一些帧,因为面部通常不会移动太多。
鉴于优化,我相信您的检测速度至少会提高 12 倍。