如何正确保存DLIB物体检测芯片?

How to save DLIB object detection chips properly?

我在保存由 DLIB 的人脸检测模型生成的图像芯片时遇到问题。下面的代码详细说明了我的工作流程。我尝试保存整个图像,如下 d_image,效果很好。然而,当我尝试保存每个芯片时,我得到了失真的输出(见下面的例子)。我在 Ubuntu 16.04.

上使用 dlib 19.4
// object to store raw image data
cv::Mat rawImage;

// initialize the detector
dlib::frontal_face_detector detector = dlib::get_frontal_face_detector();

// using shape predictor object to create dull_object_detections
dlib::shape_predictor sp;
dlib::deserialize(argv[1]) >> sp;

// for writing out images 
int image_id = 1;

while (true){
    
    // retrieve image size
    sockt.getData(&image_size, 4, NULL);
    
    if (image_size > 0) {
    
        rawImage.create(1, image_size, CV_8UC1);

        // load incoming data from a stream 
        sockt.getData(rawImage.data, image_size, MSG_WAITALL);
        
        // reshape and correct orientation 
        dlib::cv_image<dlib::bgr_pixel> d_image = utils::process_frame(rawImage);
        
        // find the daces!
        std::vector<dlib::rectangle> detections = detector(d_image);
        
        if (detections.size() > 0){

            // generate additional detection data so we can use 
            // dlib's extract_image_chips function
            std::vector<dlib::full_object_detection> shapes;
            for (int idx = 0; idx < detections.size(); idx++){
                dlib::full_object_detection shape = sp(d_image, detections[idx]);
                shapes.push_back(shape);
            }

            // write each chip to disk
            dlib::array<dlib::array2d<dlib::bgr_pixel>> face_chips;
            dlib::extract_image_chips(d_image, dlib::get_face_chip_details(shapes), face_chips);
            for (int idx = 0; idx < face_chips.size(); idx++){
                std::string fname = argv[2] + std::to_string(image_id) + ".jpg";
                dlib::save_jpeg(face_chips[idx], fname);
                image_id++;
            }

        }

保存筹码示例:

编辑:向 utils::process_frame 添加了评论。此函数接受 1xN 数组并使用 OpenCV

解码为 JPEG

您使用的图像格式有问题:

这是 OpenCV 的灰度(1 通道)图像

rawImage.create(1, image_size, CV_8UC1);

这是 BGR(3 通道)图像 dlib::cv_image<dlib::bgr_pixel> d_image = utils::process_frame(rawImage);

如果图像的通道数不正确,Dlib 应该会抛出异常,但在您的情况下不会抛出异常。这意味着在 utils::process_frame(rawImage) 中的某处,图像格式首先更改为 3 通道-检查图像格式

并且此构造代码 rawImage.create(1, image_size, CV_8UC1); 构造 1 行和 image_size 列图像。 图片大小和格式不正确

另请注意,dlib 不会将图像数据复制到 dlib::cv_image<dlib::bgr_pixel> d_image 并且 rawImage 应在处理完成之前由其他线程保持不变

无论如何,你可以调用dlib::toMat,获取OpenCV Mat并用OpenCV函数保存它

更新: 这里还有一件事:

dlib::cv_image<dlib::bgr_pixel> d_image = utils::process_frame(rawImage);

看起来像 utils::process_frame returns 一些临时对象,在 d_image 构造后被销毁。 d_image 不保留返回的数据,它可能会丢失 所以我建议您像这样更改代码:

cv::Mat uncompressed;
tils::process_frame(rawImage, uncompressed);
dlib::cv_image<dlib::bgr_pixel> d_image(uncompressed);;

其中 process_frame 应该引用 cv::Mat 并将其输出保存到其中