使用 Accelerate 缩放 Ycbcr (420f) 时的伪影

Posted

技术标签:

【中文标题】使用 Accelerate 缩放 Ycbcr (420f) 时的伪影【英文标题】:Artifacts when scaling Ycbcr (420f) with Accelerate 【发布时间】:2015-09-25 23:56:03 【问题描述】:

我找不到任何关于如何调整 Ycbcr biplanar 大小的文档或示例,据推测,这是您应该在 ios 上使用的主要格式。我尝试像这样调整两个平面的大小:

    // resize luma
    vImage_Buffer originalYBuffer =  CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0), CVPixelBufferGetHeightOfPlane(pixelBuffer, 0), CVPixelBufferGetWidthOfPlane(pixelBuffer, 0), CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0) ;
    vImage_Buffer resizedYBuffer;
    vImageBuffer_Init(&resizedYBuffer, IMAGE_HEIGHT, IMAGE_WIDTH, 8 * sizeof(Pixel_8), kvImageNoFlags);
    error = vImageScale_Planar8(&originalYBuffer, &resizedYBuffer, NULL, kvImageNoFlags);
    assert(!error);
    cv::Mat grey(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1, resizedYBuffer.data);

    // resize chroma
    vImage_Buffer originalUVBuffer =  CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1), CVPixelBufferGetHeightOfPlane(pixelBuffer, 1), CVPixelBufferGetWidthOfPlane(pixelBuffer, 1), CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1) ;
    vImage_Buffer resizedUVBuffer;
    vImageBuffer_Init(&resizedUVBuffer, IMAGE_HEIGHT / 2, IMAGE_WIDTH / 2, 8 * sizeof(Pixel_16U), kvImageNoFlags);
    error = vImageScale_Planar8(&originalUVBuffer, &resizedUVBuffer, NULL, kvImageNoFlags);
    assert(!error);

但是颜色完全不合时宜。亮度通道自己工作,所以它是色度的问题。这种格式应该使用 2 个字节来表示色度,尽管并不完全确定。如果我使用vImageScale_Planar8,我会得到一半的屏幕绿色,否则如果我使用vImageScale_Planar16U,我会在整个图像上得到蓝色/黄色噪点。

【问题讨论】:

【参考方案1】:

您可以使用vImageScale_CbCr8 作为 UV 缓冲区,但它仅适用于 iOS 10+:

// resize luma
vImage_Buffer originalYBuffer =  CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 0), CVPixelBufferGetHeightOfPlane(pixelBuffer, 0), CVPixelBufferGetWidthOfPlane(pixelBuffer, 0), CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 0) ;
vImage_Buffer resizedYBuffer;
vImageBuffer_Init(&resizedYBuffer, IMAGE_HEIGHT, IMAGE_WIDTH, 8 * sizeof(Pixel_8), kvImageNoFlags);
error = vImageScale_Planar(&originalYBuffer, &resizedYBuffer, NULL, kvImageNoFlags);
assert(!error);
cv::Mat grey(IMAGE_HEIGHT, IMAGE_WIDTH, CV_8UC1, resizedYBuffer.data);

// resize chroma
vImage_Buffer originalUVBuffer =  CVPixelBufferGetBaseAddressOfPlane(pixelBuffer, 1), CVPixelBufferGetHeightOfPlane(pixelBuffer, 1), CVPixelBufferGetWidthOfPlane(pixelBuffer, 1), CVPixelBufferGetBytesPerRowOfPlane(pixelBuffer, 1) ;
vImage_Buffer resizedUVBuffer;
vImageBuffer_Init(&resizedUVBuffer, IMAGE_HEIGHT / 2, IMAGE_WIDTH / 2, 8 * sizeof(Pixel_16U), kvImageNoFlags);
error = vImageScale_CbCr8(&originalUVBuffer, &resizedUVBuffer, NULL, kvImageNoFlags);
assert(!error);

【讨论】:

@fathy:你知道吗,如何将缩放后的结果合并回一个新的像素缓冲区? @decades 你知道如何组合规模结果吗?【参考方案2】:

从苹果人那里得到了安德威尔:vImageScale_Planar8 不能在 UV 平面上操作,因为它是交错的。唯一的解决办法是拆分成两个独立的平面。

【讨论】:

以上是关于使用 Accelerate 缩放 Ycbcr (420f) 时的伪影的主要内容,如果未能解决你的问题,请参考以下文章

如何将 Accelerate Framework 与 Core Graphics 一起使用?

YUV 和 YCbCr 辨析

在 Matlab 中,当图像在 YCbCr 中时,如何使用色度二次采样将 4:4:4 图像缩小为 4:1:1?

RGB,YCBCR在HDMI传输线是数据排列

使用 Accelerate 框架对向量进行编码

OSX Accelerate 框架上浮动选择的 4 路 SIMD 版本是啥?