来自 AVDepthData 的深度图不同于 Photoshop 中的 HEIC 文件深度数据
Depth map from AVDepthData different from HEIC file depth data in 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打开,进入Channels,选择深度图如下:
结果如下:
这是一张更高 resolution/quality、方向正确的深度图。为什么代码(实际上是 https://developer.apple.com/documentation/avfoundation/avdepthdata/2881221-depthdatafromdictionaryrepresent?language=objc 处的 Apple 自己的代码)导致质量较低的结果?
我发现了问题。实际上,它隐藏在众目睽睽之下。 +[AVDepthData depthDataFromDictionaryRepresentation:error:]
方法得到的是returnsdisparity数据。我已使用以下代码将其转换为 depth:
if(depthData.depthDataType != kCVPixelFormatType_DepthFloat32){
depthData = [depthData depthDataByConvertingToDepthDataType:kCVPixelFormatType_DepthFloat32];
}
(没试过,但 16 位深度,kCVPixelFormatType_DepthFloat16
,应该也能正常工作)
将视差转换为深度后,图像与 Photoshop 中的图像完全相同。我应该在使用 CGImageSourceCopyAuxiliaryDataInfoAtIndex(imageSource, 0, kCGImageAuxiliaryDataTypeDisparity);
时醒来(注意最后的 "disparity")并且 Photoshop 清楚地说 "depth map",将视差转换为深度(或者只是以某种方式读取深度,我老实说不知道物理编码,也许 iOS 在我首先复制辅助数据时正在将深度转换为视差)。
旁注: 我还通过直接从 [PHAsset requestContentEditingInputWithOptions:completionHandler:]
方法创建图像源并将 contentEditingInput.fullSizeImageURL
传递给 [= 解决了方向问题16=] 方法。它负责方向。
我正在使用以下代码提取深度图(按照 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打开,进入Channels,选择深度图如下:
结果如下:
这是一张更高 resolution/quality、方向正确的深度图。为什么代码(实际上是 https://developer.apple.com/documentation/avfoundation/avdepthdata/2881221-depthdatafromdictionaryrepresent?language=objc 处的 Apple 自己的代码)导致质量较低的结果?
我发现了问题。实际上,它隐藏在众目睽睽之下。 +[AVDepthData depthDataFromDictionaryRepresentation:error:]
方法得到的是returnsdisparity数据。我已使用以下代码将其转换为 depth:
if(depthData.depthDataType != kCVPixelFormatType_DepthFloat32){
depthData = [depthData depthDataByConvertingToDepthDataType:kCVPixelFormatType_DepthFloat32];
}
(没试过,但 16 位深度,kCVPixelFormatType_DepthFloat16
,应该也能正常工作)
将视差转换为深度后,图像与 Photoshop 中的图像完全相同。我应该在使用 CGImageSourceCopyAuxiliaryDataInfoAtIndex(imageSource, 0, kCGImageAuxiliaryDataTypeDisparity);
时醒来(注意最后的 "disparity")并且 Photoshop 清楚地说 "depth map",将视差转换为深度(或者只是以某种方式读取深度,我老实说不知道物理编码,也许 iOS 在我首先复制辅助数据时正在将深度转换为视差)。
旁注: 我还通过直接从 [PHAsset requestContentEditingInputWithOptions:completionHandler:]
方法创建图像源并将 contentEditingInput.fullSizeImageURL
传递给 [= 解决了方向问题16=] 方法。它负责方向。