gpt4 book ai didi

c - 如何使用 IPP 将 8 位灰度图像转换为 NV12(有限范围)颜色空间

转载 作者:太空宇宙 更新时间:2023-11-04 04:29:32 25 4
gpt4 key购买 nike

英特尔® 媒体 SDK 等视频编码器不接受 8 位灰度图像作为输入格式。
8 位 Grayscale format 在 [0, 255] 范围内每个像素应用一个字节。

问题上下文中的 8 位 YUV 格式适用 YCbCr (BT.601 或 BT.709)。
虽然有全范围的 YUV 标准,但常用的格式是“有限范围”YUV,其中 Y 的范围是 [16, 235],U,V 的范围是 [16, 240]。

NV12 format是这种情况下的通用输入格式。
NV12 格式是 YUV 4:2:0 格式,在内存中排序,首先是 Y 平面,然后是交错 UV 平面中的打包色度样本:
YYYYYY
YYYYYY
紫外线UV紫外线

enter image description here

灰度图像将被称为“I 平面”:
IIIIII
IIIIII

enter image description here

设置 UV 平面很简单:将所有 U、V 元素设置为 128 值。

但是 Y 平面呢?

在全范围 YUV 的情况下,我们可以简单地将“I 平面”作为 Y 平面(即 Y = I)。

如果是“有限”的 YUV 格式,则需要进行转换:
在转换公式中设置 R=G=B 结果:Y = round(I*0.859 + 16)。

使用 IPP 进行上述转换的有效方法是什么? ?

最佳答案

我正在为我自己的问题添加一个答案。
我希望看到一个更好的答案......

我找到了一个使用两个 IPP 函数的解决方案:

为了获得更好的性能,我选择了使用定点数学的函数。

  • 定点实现0.859缩放是通过扩展、缩放和移动来执行的。示例:b = (a*scale + (1<<7)) >> 8; [当 scale = (0.859)*2^8 ].
    val参数 ippsMulC_8u_Sfs设置为 round(0.859*2^8) = 220 .
    scaleFactor参数 ippsMulC_8u_Sfs设置为 8 (将缩放后的结果除以 2^8 )。

代码示例:

void GrayscaleToNV12(const unsigned char I[],
int image_width,
int image_height,
unsigned char J[])
{
IppStatus ipp_status;
const int image_size = image_width*image_height;

unsigned char *UV = &J[image_size]; //In NV12 format, UV plane starts below Y.

const Ipp8u expanded_scaling = (Ipp8u)(0.859 * 256.0 + 0.5);

//J[x] = (expanded_scaling * I[x] + 128u) >> 8u;
ipp_status = ippsMulC_8u_Sfs(I, //const Ipp8u* pSrc,
expanded_scaling, //Ipp8u val,
J, //Ipp8u* pDst,
image_size, //int len,
8); //int scaleFactor);

//Check ipp_status, and handle errors...

//J[x] += 16;
//ippsAddC_8u_ISfs is deprecated, I used it to keep the code simple.
ipp_status = ippsAddC_8u_ISfs(16, //Ipp8u val,
J, //Ipp8u* pSrcDst,
image_size, //int len,
0); //int scaleFactor);

//Check ipp_status, and handle errors...

//2. Fill all UV plane with 128 value - "gray color".
memset(UV, 128, image_width*image_height/2);
}

题外话:
有一种方法可以将视频流标记为“全范围”(其中 Y 范围是 [0, 255] 而不是 [ 16 , 235 ],并且 U , V 范围也是 [ 0, 255]).
使用“全范围”标准允许放置 I代替 Y (即 Y = I)。

使用英特尔媒体 SDK 将流标记为“全范围”是可能的(但没有很好的记录)。
将 H.264 流标记为“全范围”需要添加指向 mfxExtBuffer **ExtParam 的指针列表(在结构 mfxVideoParam 中):
指向 mfxExtVideoSignalInfo 类型结构的指针应添加以下值:

typedef struct {
mfxExtBuffer Header; //MFX_EXTBUFF_VIDEO_SIGNAL_INFO and sizeof(mfxExtVideoSignalInfo)
mfxU16 VideoFormat; //Most likely 5 ("Unspecified video format")
mfxU16 VideoFullRange; //1 (video_full_range_flag is equal to 1)
mfxU16 ColourDescriptionPresent; //0 (description_present_flag equal to 0)
mfxU16 ColourPrimaries; //0 (no affect when ColourDescriptionPresent = 0)
mfxU16 TransferCharacteristics; //0 (no affect when ColourDescriptionPresent = 0)
mfxU16 MatrixCoefficients; //0 (no affect when ColourDescriptionPresent = 0)
} mfxExtVideoSignalInfo;

VideoFullRange = 1是设置“全范围”视频的唯一相关参数,但我们必须填充整个结构。

关于c - 如何使用 IPP 将 8 位灰度图像转换为 NV12(有限范围)颜色空间,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37978479/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com