【问题标题】:sws_scale, YUV to RGB conversionsws_scale,YUV 到 RGB 的转换
【发布时间】:2021-05-28 17:48:44
【问题描述】:

我需要将 YUV 转换为 RGB。我还需要 RGB 值在有限范围内(16-235)。 我尝试使用 sws_scale 函数来完成这项任务。

您可以在下面看到我的代码。但转换后我得到的黑色像素是 (0, 0, 0) 而不是 (16, 16, 16)。

也许有一些选项可以告诉 sws_scale 函数计算有限范围。

AVFrame* frameRGB = avFrameConvertPixelFormat(_decodedBuffer[i].pAVFrame, AV_PIX_FMT_RGB24);
AVFrame* Decoder::avFrameConvertPixelFormat(const AVFrame* src, AVPixelFormat dstFormat) {
    int width = src->width;
    int height = src->height;

    AVFrame* dst = allocPicture(dstFormat, width, height);

    SwsContext* conversion = sws_getContext(width,
                                            height,
                                            (AVPixelFormat)src->format,
                                            width,
                                            height,
                                            dstFormat,
                                            SWS_FAST_BILINEAR,
                                            NULL,
                                            NULL,
                                            NULL);
    sws_scale(conversion, src->data, src->linesize, 0, height, dst->data, dst->linesize);
    sws_freeContext(conversion);

    dst->format = dstFormat;
    dst->width = src->width;
    dst->height = src->height;

    return dst;
}

我还尝试使用公式手动将 YUV 像素转换为 RGB 像素,我得到了正确的结果。从 YUV (16, 128, 128) 我得到 (16, 16, 16) 的 RGB。

cmpR = y + 1.402 * (v - 128);
cmpG = y - 0.3441 * (u - 128) - 0.7141 * (v - 128);
cmpB = y + 1.772 * (u - 128);

【问题讨论】:

    标签: c++ rgb yuv libav swscale


    【解决方案1】:

    您可以将源格式设置为“全尺寸”YUVJ

    据我所知,sws_scale 没有选择Studio RGB 作为输出格式的选项。
    更改输入格式是我能想到的最佳解决方案。

    “JPEG: YUV -> RGB”的颜色转换formula和你帖子里的公式是一样的

    设置源格式示例:

    • 如果src->formatPIX_FMT_YUV420P,则将格式设置为PIX_FMT_YUVJ420P
    • 如果src->formatPIX_FMT_YUV422P,则将格式设置为PIX_FMT_YUVJ422P
    • 如果src->formatPIX_FMT_YUV444P,则将格式设置为PIX_FMT_YUVJ444P
    • 如果PIX_FMT_YUV440P,请使用PIX_FMT_YUVJ440P

    我知道解决方案并没有涵盖所有的可能性,并且可能有一些输出像素超出 [16, 235] 的范围,所以这不是最通用的解决方案...

    【讨论】:

    • 你好@Rotem,谢谢!这个解决方案似乎对我有用。你能解释一下为什么这个解决方案有效吗?它基于什么原理?并且似乎“AV_PIX_FMT_YUVJ420P”已弃用“平面 YUV 4:2:0、12bpp、全尺寸 (JPEG),弃用了 AV_PIX_FMT_YUV420P 并设置 color_range”
    • 正如我在帖子中提到的,我的解决方案基于您问题中的转换公式。该公式与 JPEG YUV 转换(在 Wikipedia 中描述)相同。 YUVJJ 字母应用 JPEG 转换(JPEG 使用全范围 YUV,而不是常见的视频转换公式 Y 限制为 [16, 235])。
    • 我的解决方案并不理想,部分原因是“AV_PIX_FMT_YUVJ420P”已被弃用。我认为你最好使用sws_setColorspaceDetails()。将srcRange 设置为1。可能有更好的解决方案(注意:我从未直接使用 sws_scale - 仅使用 FFmpeg 命令行)。请发布您找到的解决方案。
    • 感谢您的回复。我看见你。我接受您的回答作为解决方案。这绝对有效,但也许我会尝试手动获取公式 YUV 到 RGB 对话(对于主要标准 BT.601、BT.709 和 BT.2020,以及 8、10 和 12 位深度),以获得更多控制。我遇到了一个有趣的文档,其中以易于理解的形式描述了这些公式的结论poynton.ca/ColorFAQ.html
    猜你喜欢
    • 2012-01-19
    • 1970-01-01
    • 2014-01-25
    • 2012-11-25
    • 1970-01-01
    • 2013-07-27
    • 2017-04-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多