RGB转YCbCr——Python(1)


前言

  本系列课程结合软件与硬件,以图像为主要研究对象。课程素材来源于《基于MATLAB与FPGA的图像处理教程》,并将MATLAB改成Python。


一、RGB转YCbCr

  RGB转YCbCr有以下几个标准,标准不同,转换公式不同,本文只给出标准3的转换公式。

  1. 标准清晰度电视(SDTV)
  2. 清晰度电视(HDTV)
  3. full range 或者 pc range

  full range 或者 pc range公式如下:
[ Y C b C r ] = [ 0 128 128 ] + [ 0.299 0.587 0.114 − 0.169 − 0.331 0.500 0.500 − 0.419 − 0.081 ] × [ R G B ] , 其中 { R / G / B ∈ [ 0 , 255 ] Y / C b / C r ∈ [ 0 , 255 ] (1) \begin{bmatrix} Y\\ Cb\\ Cr\\ \end{bmatrix} = \begin{bmatrix} 0\\ 128\\ 128\\ \end{bmatrix} + \begin{bmatrix} 0.299&0.587&0.114\\ -0.169&-0.331&0.500\\ 0.500&-0.419&-0.081\\ \end{bmatrix} \times \begin{bmatrix} R\\ G\\ B\\ \end{bmatrix},其中 \begin{cases} R/G/B \in &[0, 255]\\ Y/Cb/Cr \in &[0, 255] \end{cases}\tag{1} YCbCr = 0128128 + 0.2990.1690.5000.5870.3310.4190.1140.5000.081 × RGB ,其中{R/G/BY/Cb/Cr[0,255][0,255](1)

  为了方便FPGA硬件设计,需要对公式(1)进行稍微的转变。

Y = R × 0.299 + G × 0.587 + B × 0.114 (2) Y = R\times0.299 + G\times0.587+B\times0.114\tag{2} Y=R×0.299+G×0.587+B×0.114(2)
  将公式(2)扩大 2 8 2^8 28=256倍。
256 × Y = R × 76.544 + G × 150.272 + B × 29.184 ≈ R × 76 + G × 150 + B × 29 (3) 256 \times Y = R \times 76.544 + G \times 150.272 + B \times 29.184 \approx R\times76 + G \times150 + B \times 29\tag{3} 256×Y=R×76.544+G×150.272+B×29.184R×76+G×150+B×29(3)
  结果不能四舍五入,去掉小数即可,算出结果再通过向右移动8位缩小256倍得到Y。Cb,Cr同样的操作,如公式(4)所示。
{ Y = ( R × 76 + G × 150 + B × 29 ) > > 8 C b = ( − R × 43 − G × 84 + B × 128 + 32768 ) > > 8 C b = ( R × 128 − G × 107 − B × 20 + 32768 ) > > 8 (4) \begin{cases} Y = (R\times76 + G \times150 + B \times 29)>>8\\ Cb = (-R\times43 - G \times84 + B \times 128 + 32768)>>8\\ Cb = (R\times128 - G \times107 - B \times 20 + 32768)>>8\end{cases}\tag{4} Y=(R×76+G×150+B×29)>>8Cb=(R×43G×84+B×128+32768)>>8Cb=(R×128G×107B×20+32768)>>8(4)

二、Python端代码

import matplotlib.pyplot as plt
import numpy as np
img = plt.imread("girl.jpg")#读取图像
h, w, _ = img.shape#获取高宽通道
img_ycbcr = np.zeros(img.shape)
for i in range(h):
    for j in range(w):
        img_ycbcr[i, j, 0] = (img[i, j, 0] * 76 + img[i, j, 1] * 150 + img[i, j, 2] * 29) >> 8
        img_ycbcr[i, j, 1] = ((-img[i, j, 0]) * 43 - img[i, j, 1] * 84 + img[i, j, 2] * 128 + 32768) >> 8
        img_ycbcr[i, j, 2] = (img[i, j, 0] * 128 - img[i, j, 1] * 107 - img[i, j, 2] * 20 + 32768) >> 8
#画图
plt.figure(figsize=(10, 10))
plt.subplot(221)
plt.title("RGB image")
plt.imshow(img)
plt.subplot(222)
plt.title("y channel")
plt.imshow(img_ycbcr[:, :, 0], cmap='gray')
plt.subplot(223)
plt.title("cb channel")
plt.imshow(img_ycbcr[:, :, 1], cmap='gray')
plt.subplot(224)
plt.title("cr channel")
plt.imshow(img_ycbcr[:, :, 2], cmap='gray')

在这里插入图片描述
  保存YCbCr图像。

img_ycbcr = img_ycbcr.astype(np.uint8)#float to int
plt.imsave("ycbcr.jpg", img_ycbcr)#保存转换后的图像

在这里插入图片描述
  将RGB与YCbCr以十六进制保存到.dat文件里面,供FPGA端代码测试。

import os
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image

"""
把图像像素转hex写入.dat文件
"""
def write_file(arr, dat_file):
    arr_list = arr.tolist()
    f = open(dat_file, "a")
    for i in range(len(arr_list)):
        row_hex = ' '.join([hex(j)[2:] for j in arr_list[i]]) + '\n'
        f.write(row_hex)
    f.close()

"""
r,g,b全部写入文件
"""
def gen_dat(image_file, dat_file):
    image_file = os.path.join(os.getcwd(), image_file)
    dat_file = os.path.join(os.getcwd(), dat_file)
    if os.path.exists(dat_file):#如果存在,就删除.dat文件
        os.remove(dat_file)
    img =  Image.open(image_file)
    resized_image = img.resize((10,10))#由于原图太大,不便于观察
    r, g, b = resized_image.split()
    r_array = np.array(r)
    g_array = np.array(g)
    b_array = np.array(b)
    write_file(r_array, dat_file)
    write_file(g_array, dat_file)
    write_file(b_array, dat_file)
    
if __name__ == "__main__":
    gen_dat("girl.jpg", "img_rgb.dat")
    gen_dat("ycbcr.jpg", "img_ycbcr.dat")

  原图过大,为了减少计数量,缩放至10x10,r是1到10行,g是11到20行,b是21到30行。

在这里插入图片描述

总结

  实现的代码还是有所区别,并不是和课本完成一致,但是目标是一致的,就如《基于MATLAB与FPGA的图像处理教程》中说到的,让你的软件起飞。下期将带来RGB转YCbCr——FPGA,敬请期待。

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值