我使用Apple的为用户提供的图像中的人创建了一个无光泽的图像。我想分析来自VNGeneratePersonSegmentationRequest的结果来理解,例如,如果请求已经找到了一个人,如果是的话,结果掩码相对于源图像的大小(或者掩码的范围或不透明像素的数量)。
VNGeneratePersonSegmentationRequest的结果是VNPixelBufferObservation,显然它不支持信任级别(confidence总是1.0)或结果计数(如numberOfFoundPeople )。
我尝试的是直接分析结果的CVPixelBuffer。我是这样得到的:
let personSegmentationRequest = VNGeneratePersonSegmentationRequest()
personSegmentationRequest.outputPixelFormat = kCVPixelFormatType_OneComponent8
let requestHandler = VNImageRequestHandler(url: imageUrl)
try requestHandler.perform([personSegmentationRequest])
let mask = personSegmentationRequest.results![0]
let maskBuffer = mask.pixelBuffer
CVPixelBufferLockBaseAddress(maskBuffer, .readOnly)
defer {
CVPixelBufferUnlockBaseAddress(maskBuffer, .readOnly)
}我现在的想法是查看缓冲区的单个像素值。我假设我可以用CVPixelBufferGetWidth和CVPixelBufferGetHeight获得掩码的大小,每像素得到一个字节,而0值表示“完全透明”,而255表示“完全不透明”。
显然,这是不正确的:像素缓冲区的大小总是2016x1512或1512x2016,但是CVPixelBufferGetBytesPerRow返回2048或1536,所以每行都有一些额外的字节。这是如何加起来的?CVPixelBufferGetExtendedPixels返回所有方向的0,所以没有填充。
另外,如果我查看缓冲区中的前几个值,它们不是我所期望的。下面是打印缓冲区前10个值的代码:
let baseAddress = CVPixelBufferGetBaseAddress(maskBuffer)!
let pointer = baseAddress.assumingMemoryBound(to: UInt8.self)
print((0...10).map({ String(pointer[$0]) }).joined(separator: ","))下面是图像的示例输出,这些图像要么包含,一个位于图像中心的人,要么包含,根本没有人在中。
1,0,0,0,0,0,0,0,0,0,0
4,1,0,0,0,0,0,0,0,0,0
9,4,1,1,1,0,0,0,0,0,0
2,1,1,1,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0这些值应该对应于源图像一角的像素,并且我总是期望示例图像的所有零。
奇怪的是,当我忽略这些结果,简单地用这个CVPixelBuffer创建一个CVPixelBuffer,再用CoreImage (在苹果的示例代码中)将它作为掩码应用,结果看起来是正确的,而且我看不到角落中的半透明像素。
到底怎么回事?我是否误解了CVPixelBufferGet*方法?像素缓冲区中的数据是否包含元数据?
发布于 2022-08-04 14:50:19
经过进一步的研究,我认为每行字节数与像素缓冲区宽度之间的差异来自核心视频中所需的字节对齐(参见this answer)。
当缓冲区作为图像掩码应用时,这些小的非零值实际上是可见的,但是这些值足够小,影响几乎不明显。我假设它们是ML模型的工件,可以忽略它们。
https://stackoverflow.com/questions/73234238
复制相似问题