文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

python如何实现RGB与YCBCR颜色空间转换

2023-06-29 11:00

关注

小编给大家分享一下python如何实现RGB与YCBCR颜色空间转换,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

1、灰度值和亮度的关系

人类能够从灰度图像中获取理解场景需要的大部分信息,所以看黑白电视机并不会严重影响人对视频中场景的理解。图像的亮度和像素值成正比,如果需要增加图像的亮度,比如从黑色逐渐过渡到白色,就可以对单通道的灰度图像素值进行增加来实现。保存灰度图像的每个像素值一般采用8个bit,像素值的范围为0-255。

下面的例子展示了灰度图像的像素值增加时亮度的变化过程,假设图像初始像素值为0:

python如何实现RGB与YCBCR颜色空间转换

上面显示了lena图像像素值增加时肤色的变化。代码的实现比较简单,读取图片,然后不断的对图像的每个像素值增加偏移量:

import numpy as npimport matplotlib.pyplot as pltimport imageioimage = imageio.imread("lena.jpg")# 设置每次循环像素的增加量shift = 6*np.ones(shape=(64, 64))plt.figure()for i in range(1, 17):    plt.subplot(4, 4, i)    plt.imshow(image/255, cmap="gray", vmin=0, vmax=1)    plt.axis("off")    image = image + shift

2、RGB颜色空间与颜色控制

RGB模型在硬件设备中被广泛的使用,通过R(红色)、G(绿色)、B(蓝色)三者进行叠加可以形成更多的颜色。RGB颜色空间和后面将要进行介绍的YCbCr颜色空间和HSV颜色空间存在线性的变换关系,所以只要拥有RGB图像就能得到其它颜色空间的图像。

一幅图像中R、G、B分别作为三个通道,如果某两个通道的值为0,图像的颜色就会被不为零的那个通道控制。

比如:

python如何实现RGB与YCBCR颜色空间转换

实现上面的效果需要三个步骤:

# 1:创建一幅3通道的空图像= np.zeros(shape=(64, 64, 3))r = imageio.imread("lena.jpg")/2# 2:给3通道空图像的R通道添加一幅单通道图像image[:, :, 0] = image[:, :, 0] + rshift = 4*np.ones(shape=(64, 64))plt.figure()for i in range(1, 17):    plt.subplot(4, 4, i)    plt.imshow(image/255, vmin=0, vmax=1)    plt.axis("off")    # (3)给3通道图像的R通道像素值不断增加偏移量    image[:, :, 0] = image[:, :, 0] + shift

但是,由于最终图像呈现出的颜色是三R\G\B三者的叠加,而现实中不仅仅是其中之一的颜色,所以很难控制最终图像的颜色,所以我们需要其它的颜色空间。

3、YCbCr颜色空间及与RGB的变换关系

YCbCr颜色空间中的Y是亮度通道,Cb是蓝色分量,Cr是红色分量。它在电视系统中比较常用,比如早期的黑白电视机使用彩色电视信号线,就可以单独使用亮度值;这种功能RGB颜色空间就做不到,因为我们不能仅仅使用RGB中某个通道作为亮度信号来使用。

由于YCbCr经常和YUV颜色空间比较相似,所以二者容易被认为是从属或者等价关系,按照维基百科的说法:YUV 是模拟信号,而YCbCr是数字信号。

YCbCr和RGB存在线性的变换关系,本文介绍的变换矩阵来自ITU.BT-601,所规定的变换矩阵Trans形式如下:

python如何实现RGB与YCBCR颜色空间转换

实现rgb2ycbcr()函数只需要两个步骤:(1)创建变换矩阵Trans;(2)遍历图像每个像素点,并对三个通道分别进行矩阵计算。

下面的代码展示了如何实现从RGB空间到YCBCR变换:

def rgb2ycbcr(rgb_image):    """convert rgb into ycbcr"""    if len(rgb_image.shape)!=3 or rgb_image.shape[2]!=3:        raise ValueError("input image is not a rgb image")    rgb_image = rgb_image.astype(np.float32)    # 1:创建变换矩阵,和偏移量    transform_matrix = np.array([[0.257, 0.564, 0.098],                                 [-0.148, -0.291, 0.439],                                 [0.439, -0.368, -0.071]])    shift_matrix = np.array([16, 128, 128])    ycbcr_image = np.zeros(shape=rgb_image.shape)    w, h, _ = rgb_image.shape    # 2:遍历每个像素点的三个通道进行变换    for i in range(w):        for j in range(h):            ycbcr_image[i, j, :] = np.dot(transform_matrix, rgb_image[i, j, :]) + shift_matrix           return ycbcr_image

如果想要求逆变换,只需要根据矩阵求逆法则进行就可以了,需要注意的是:逆变换时偏移矩阵也需要左乘变换矩阵Trans的逆!逆变换只需要将rgb2ycbcr中的transform_matrix求逆即可,再次强调:shift_matrix也需要乘以transform_matrix的逆,而不是直接减去shift_matrix!

def ycbcr2rgb(ycbcr_image):    """convert ycbcr into rgb"""    if len(ycbcr_image.shape)!=3 or ycbcr_image.shape[2]!=3:        raise ValueError("input image is not a rgb image")    ycbcr_image = ycbcr_image.astype(np.float32)    transform_matrix = np.array([[0.257, 0.564, 0.098],                                 [-0.148, -0.291, 0.439],                                 [0.439, -0.368, -0.071]])    transform_matrix_inv = np.linalg.inv(transform_matrix)    shift_matrix = np.array([16, 128, 128])    rgb_image = np.zeros(shape=ycbcr_image.shape)    w, h, _ = ycbcr_image.shape    for i in range(w):        for j in range(h):            rgb_image[i, j, :] = np.dot(transform_matrix_inv, ycbcr_image[i, j, :]) - np.dot(transform_matrix_inv, shift_matrix)    return rgb_image.astype(np.uint8)

所需要的包以及绘图代码如下,绘图用到的就是上面定义的两个函数。首先将rgb转为ycbcr,在从ycbcr转为rgb:

import numpy as npimport imageioimport matplotlib.pyplot as pltrgb_image = imageio.imread("lena.jpg")ycbcr_image = rgb2ycbcr(rgb_image)cycle_image = ycbcr2rgb(ycbcr_image)images = [rgb_image, ycbcr_image, cycle_image]titles = ["orignal", "ycbcr", "cycle"]for i in range(1, len(images)+1):    plt.subplot(1, 3, i)    plt.title(titles[i-1])    plt.imshow(images[i-1]/255)

下图中左边是原始的rgb图像,中间是转换得到的ycbcr空间图像,右边是再次转回rgb空间的图像:

python如何实现RGB与YCBCR颜色空间转换

最后,对比了opencv提供的标准库的转换效果:

import cv2rgb_image = imageio.imread("lena.jpg")ycrcb_image = cv2.cvtColor(rgb_image, cv2.COLOR_RGB2YCR_CB)cycle_image = cv2.cvtColor(ycbcr_image, cv2.COLOR_YCR_CB2RGB)images = [rgb_image, ycrcb_image, cycle_image]titles = ["orignal", "ycrcb", "cycle"]for i in range(1, len(images)+1):    plt.subplot(1, 3, i)    plt.title(titles[i-1])    plt.imshow(images[i-1]/255)

opencv得到的结果如下:

python如何实现RGB与YCBCR颜色空间转换

原始rgb效果和cycle(重构)效果很接近,而中间结果不一致是因为opencv采用的是“ycrcb”,而不是“ycbcr”。

以上是“python如何实现RGB与YCBCR颜色空间转换”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网行业资讯频道!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     807人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     351人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     314人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     433人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     221人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯