Карта глубины из AVDepthData отличается от данных глубины файла HEIC в Photoshop

Я использую следующий код для извлечения карты глубины (следуя собственному примеру Apple):

- (nullable AVDepthData *)depthDataFromImageData:(nonnull NSData *)imageData orientation:(CGImagePropertyOrientation)orientation {
    AVDepthData *depthData = nil;

    CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL);
    if (imageSource) {
        NSDictionary *auxDataDictionary = (__bridge NSDictionary *)CGImageSourceCopyAuxiliaryDataInfoAtIndex(imageSource, 0, kCGImageAuxiliaryDataTypeDisparity);
        if (auxDataDictionary) {
            depthData = [[AVDepthData depthDataFromDictionaryRepresentation:auxDataDictionary error:NULL] depthDataByApplyingExifOrientation:orientation];
        }

        CFRelease(imageSource);
    }

    return depthData;
}

И я называю это от:

[[PHAssetResourceManager defaultManager] requestDataForAssetResource:[PHAssetResource assetResourcesForAsset:asset].firstObject options:nil dataReceivedHandler:^(NSData * _Nonnull data) {
    AVDepthData *depthData = [self depthDataFromImageData:data orientation:[self CGImagePropertyOrientationForUIImageOrientation:pickedUiImageOrientation]];
    CIImage *image = [CIImage imageWithDepthData:depthData];
    UIImage *uiImage = [UIImage imageWithCIImage:image];
    UIGraphicsBeginImageContext(uiImage.size);
    [uiImage drawInRect:CGRectMake(0, 0, uiImage.size.width, uiImage.size.height)];
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    NSData *pngData = UIImagePNGRepresentation(newImage);
    UIImage* pngImage = [UIImage imageWithData:pngData];    // rewrap
    UIImageWriteToSavedPhotosAlbum(pngImage, nil, nil, nil);
} completionHandler:^(NSError * _Nullable error) {

}];

Вот результат: это изображение низкого качества (и повернутое, но давайте пока отложим ориентацию):

Затем я перенес исходный файл HEIC, открыл его в Photoshop, перешел на каналы и выбрал карту глубины, как показано ниже:

Вот результат:

Это более высокое разрешение / качество, правильно ориентированная карта глубины. Почему код (фактически собственный код Apple по адресу https://developer.apple.com/documentation/avfoundation/avdepthdata/2881221-depthdatafromdictionaryrepresent?language=objc) приводит к снижению качества результата?

1 ответ

Решение

Я нашел проблему. На самом деле, он скрывался на виду. Что получается из +[AVDepthData depthDataFromDictionaryRepresentation:error:] метод возвращает данные о несоответствии. Я преобразовал его в глубину, используя следующий код:

if(depthData.depthDataType != kCVPixelFormatType_DepthFloat32){
    depthData = [depthData depthDataByConvertingToDepthDataType:kCVPixelFormatType_DepthFloat32];
}

(Не пробовал, но 16-битная глубина, kCVPixelFormatType_DepthFloat16, тоже должно хорошо сработать)

После преобразования несоответствия в глубину изображение точно такое же, как в Photoshop. Я должен был проснуться, как я использовал CGImageSourceCopyAuxiliaryDataInfoAtIndex(imageSource, 0, kCGImageAuxiliaryDataTypeDisparity); (обратите внимание на "несоответствие" в конце), и Photoshop четко говорил "карта глубины", преобразуя несоответствие в глубину (или просто считывая глубину, я, честно говоря, не знаю физического кодирования, возможно, iOS преобразовывала глубину в несоответствие, когда Я копировал вспомогательные данные в первую очередь) на лету.

Примечание: я также решил проблему ориентации, создав источник изображения непосредственно из [PHAsset requestContentEditingInputWithOptions:completionHandler:] метод и прохождение contentEditingInput.fullSizeImageURL в CGImageSourceCreateWithURL метод. Он позаботился об ориентации.

Другие вопросы по тегам