当头部的滚动角度不在 -30 到 30 度之间时,dlib 68 面部标志点不准确

Posted

技术标签:

【中文标题】当头部的滚动角度不在 -30 到 30 度之间时,dlib 68 面部标志点不准确【英文标题】:dlib 68 face landmark points are inaccurate when head's roll angle is NOT between -30 to 30 degree 【发布时间】:2019-09-22 15:37:11 【问题描述】:

我正在尝试使用 dlib 从 iphone 相机(BGRA 格式)中检测面部并提取面部标志。

到目前为止,我已经从 AVMetaData 中检测出人脸矩形,并在图像的这些边界内绘制了 68 个 dlib 地标。当检测到的头部的滚动角度(滚动角度数据也是从 AVMetadata 中提取的)大约在 -30 到 30 度之间时,一切正常。但是,如果检测到的头部滚动超过 30 度,则面部标志将根本无法正确对齐。这 68 个点将不再沿头部旋转,表示我将 iPhone 保持在横向模式,Home 按钮在左侧,前置摄像头打开,68 个绘制点的脸保持在正面。

我已经用 openGL(离屏渲染)和 openCV 来渲染视频图像进行了测试,它们都产生了相同的结果。渲染方法似乎与我的问题无关。

我的问题是

    如何正确对齐那些 dlib 生成的 68 点,尽管有头部滚动角度? 或者,dlib 是否有可能准确检测任何翻转 30 度以上的人脸?

- (NSMutableArray <NSMutableArray <NSValue *> *>*)detecitonOnSampleBuffer:(CMSampleBufferRef)sampleBuffer inRects:(NSArray<NSValue *> *)rects 

    dlib::array2d<dlib::bgr_pixel> img;
    dlib::array2d<dlib::bgr_pixel> img_gray;
    // MARK: magic
    CVImageBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
    CVPixelBufferLockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);

    size_t width = CVPixelBufferGetWidth(imageBuffer);
    size_t height = CVPixelBufferGetHeight(imageBuffer);
    char *baseBuffer = (char *)CVPixelBufferGetBaseAddress(imageBuffer);

    // set_size expects rows, cols format
    img.set_size(height, width);

    // copy samplebuffer image data into dlib image format
    img.reset();


    long position = 0;
    while (img.move_next()) 
        dlib::bgr_pixel& pixel = img.element();

        // assuming bgra format here
        long bufferLocation = position * 4; //(row * width + column) * 4;
        char b = baseBuffer[bufferLocation];
        char g = baseBuffer[bufferLocation + 1];
        char r = baseBuffer[bufferLocation + 2];
        dlib::bgr_pixel newpixel(b, g, r);
        pixel = newpixel;

        position++;
    

    // unlock buffer again until we need it again
    CVPixelBufferUnlockBaseAddress(imageBuffer, kCVPixelBufferLock_ReadOnly);



    // convert the face bounds list to dlib format
    std::vector<dlib::rectangle> convertedRectangles = [self convertCGRectValueArray:rects bound:CGSizeMake(height, width)];
    dlib::assign_image(img_gray, img);

    NSMutableArray *facesLandmarks = [NSMutableArray arrayWithCapacity:0];
    for (unsigned long j = 0; j < convertedRectangles.size(); ++j) 
        /* original codes start from here */
        dlib::rectangle oneFaceRect = convertedRectangles[j];

        // detect all landmarks
        dlib::full_object_detection shape = predictor(img, oneFaceRect);
        NSMutableArray *eachFaceLandmarks = [NSMutableArray arrayWithCapacity:0];
        for (int i = 0; i < shape.num_parts(); i++) 
            dlib::point p = shape.part(i);
            [eachFaceLandmarks addObject:[NSValue valueWithCGPoint:CGPointMake(p.x(), p.y())]];
        

        //
        [facesLandmarks addObject:eachFaceLandmarks];
    

    return facesLandmarks;

【问题讨论】:

【参考方案1】:

老实说,我不清楚第一个问题。

关于第二个,根据我在过去项目中的经验。我们可以通过使用两个眼睛中心之间的线来检测脸部是正面的还是倾斜的。如果这条线是倾斜的,我们可以说面部需要对齐。 更多细节可以在下面的链接中找到,您可以在其中找到非常清晰的步骤和步骤Face alignment

【讨论】:

以上是关于当头部的滚动角度不在 -30 到 30 度之间时,dlib 68 面部标志点不准确的主要内容,如果未能解决你的问题,请参考以下文章

角度单位换算 度分秒之间怎么换算?

react-native FlatList 滚动到底部的聊天应用程序

(七十一)关于UITableView退出崩溃的问题和滚动究竟部的方法

windows操作系统unicode文本编码格式是UTF-8还是UTF-16??现在的系统

C#怎么判断一个文件的编码格式是UTF-8 without BOM的啊

关于使用Vue判断页面是否滚动到底部的事件监听