本文介绍: 将sRGB格式图片转换为BT.2020格式涉及到两个步骤:首先将sRGB转换线性RGB,然后线性RGB转换到BT.2020。这是因为sRGB图像通常使用伽马校正,而BT.2020工作线性色彩空间中。:sRGB图像首先需要进行伽马校正解码转换为线性RGB。这个过程通常不是通过一个简单线性矩阵实现的,而是通过以下公式:其中 (C_{linear}) 是线性RGB中的颜色分量值(红、绿、蓝),(C_{sRGB}) 是sRGB颜色空间中的对应分量值。

将sRGB格式的图片转换为BT.2020格式涉及到两个步骤:首先将sRGB转换到线性RGB,然后线性RGB转换到BT.2020。这是因为sRGB图像通常使用伽马校正,而BT.2020工作在线性色彩空间中。

  1. 从sRGB到线性RGB:sRGB图像首先需要进行伽马校正解码转换为线性RGB。这个过程通常不是通过一个简单的线性矩阵实现的,而是通过以下公式

    [
    C_{linear} = begin{cases}
    frac{C_{sRGB}}{12.92}, & text{if } C_{sRGB} leq 0.04045
    left(frac{C_{sRGB} + 0.055}{1.055}right)^{2.4}, & text{otherwise}
    end{cases}
    ]

    其中 (C_{linear}) 是线性RGB中的颜色分量值(红、绿、蓝),(C_{sRGB}) 是sRGB颜色空间中的对应分量值。

  2. 从线性RGB到BT.2020接下来,您可以应用一个3x3的线性转换矩阵将线性RGB转换为BT.2020色彩空间。这个矩阵通常如下所示

    [
    begin{bmatrix}
    R_{BT.2020}
    G_{BT.2020}
    B_{BT.2020}
    end{bmatrix}

    begin{bmatrix}
    0.6274 & 0.3293 & 0.0433
    0.0691 & 0.9195 & 0.0114
    0.0164 & 0.0880 & 0.8956
    end{bmatrix}
    cdot
    begin{bmatrix}
    R_{linear}
    G_{linear}
    B_{linear}
    end{bmatrix}
    ]

在实际应用中,你首先需要编写代码将sRGB图像转换为线性RGB,然后应用上述矩阵进行色彩空间的转换。以下是使用OpenCV在C++中实现这一过程示例代码
在这里插入图片描述

#include <opencv2/opencv.hpp>
#include <cmath>

cv::Mat sRGBToLinearRGB(const cv::Mat& srgbImage) {
    cv::Mat linearRGB(srgbImage.size(), srgbImage.type());
    // cv::Vec3b,static_cast<uchar> 这2个要根据图片格式选择合适的值
    srgbImage.forEach<cv::Vec3b>([&amp;](cv::Vec3b &amp;pixel, const int * position) -> void {
        for (int i = 0; i < 3; ++i) {
            float c = pixel[i] / 255.0f;
            c = c <= 0.04045f ? c / 12.92f : std::pow((c + 0.055f) / 1.055f, 2.4f);
            linearRGB.at<cv::Vec3b>(position)[i] = static_cast<uchar>(std::round(c * 255.0f));
        }
    });
    return linearRGB;
}

int main() {
    // 假设你已经有了一个sRGB格式cv::Mat对象 srgbImage
    cv::Mat srgbImage; // 加载你的sRGB图像

    // 将sRGB转换为线性RGB
    cv::Mat linearRGB = sRGBToLinearRGB(srgbImage);

    // 定义从线性RGB到BT.2020的转换矩阵
    cv::Matx33f transformMatrix(
        0.6274, 0.3293, 0.0433,
        0.0691, 0.9195, 0.0114,
        0.0164, 0.0880, 0.8956
    );

    // 应用转换矩阵
    cv::Mat bt2020Image;
    cv::transform(linearRGB, bt2020Image, transformMatrix);

    // bt2020Image现在包含转换后的图像

    return 0;
}
 cv::Mat sRGBToLinearRGB(const cv::Mat&amp; srgbImage) {
        cv::Mat linearRGB(srgbImage.size(), srgbImage.type());
        srgbImage.forEach<cv::Vec3f>([&amp;](cv::Vec3f &amp;pixel, const int * position) -> void {
            for (int i = 0; i < 3; ++i) {
                float c = pixel[i] / 255.0f;
                auto c2 = (c <= 0.04045f) ? (c / 12.92f) : std::pow((c + 0.055f) / 1.055f, 2.4f);
                auto val = static_cast<float>(std::round(c2 * 255.0f));
                qDebug() << QString("pixel[i] = %1, c1 = %2, c2 = %3, val = %4").arg(pixel[i]).arg(c).arg(c2).arg(val);
                linearRGB.at<cv::Vec3f>(position)[i] = val;
            }
        });
        return linearRGB;
    }

    cv::Mat Image_sRGB_BT2020(const cv::Mat &amp;src)
    {
        cv::Mat dst = src;
        // 确保使用浮点数
        src.convertTo(dst, CV_32F);

        // 将sRGB转换为线性RGB
        cv::Mat linearRGB = sRGBToLinearRGB(dst);

        // 定义从线性RGB到BT.2020的转换矩阵
        cv::Matx33f transformMatrix(
            0.6274, 0.3293, 0.0433,
            0.0691, 0.9195, 0.0114,
            0.0164, 0.0880, 0.8956
        );

        // 应用转换矩阵
        cv::Mat bt2020Image;
        cv::transform(linearRGB, bt2020Image, transformMatrix);

        return bt2020Image;
    }

原文地址:https://blog.csdn.net/qq_37377257/article/details/134675558

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_27176.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注