前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >fpga实现YCbCr444转RGB

fpga实现YCbCr444转RGB

作者头像
FPGA开源工作室
发布2020-09-23 13:03:14
1.9K0
发布2020-09-23 13:03:14
举报
文章被收录于专栏:FPGA开源工作室

1 基本概念

颜色空间(color space)是颜色集合的数学表示。三个最常用的颜色模型是:RGB(用于计算机图像学中);YIQ、YUV或YCbCr(用于视频系统中);CMYK(用于彩色打印)。

1.1 YCbCr颜色空间

YCbCr颜色空间是YUV颜色空间的缩放和偏移版本。Y定义为8bit,标称颜色范围为16-235;Cb和Cr标称颜色表示范围为16-240。YCbCr的采样格式一般有4:4:4、4:2:2、4:1:1、和4:2:0。

4:4:4 YCbCr格式:

图1表示4:4:4格式YCbCr采样点的定位。每个采样点有Y、Cb和Cr值,每个颜色值的颜色分量为8bit(典型),因此每个采样点24bit。

图1 4:4:4采样

1.2 RGB颜色空间

红、绿和蓝(RGB)颜色空间广泛用于计算机图像学和显示器。红绿蓝是三种基本的加性颜色,可以用三维的笛卡尔坐标系统来表示RGB颜色空间。

1.3 YCbCr到RGB颜色空间的转换:数学公式

为了将标称取值范围为16~235(Studio R’G’B’)的8位YCbCr数据转换为R’G’B’颜色公式可以简化为:

R’=Y+1.371(Cr-128)

G’=Y-0.689(Cr-128)-0.336(Cb-128)

B’=Y+1.732(Cb-128)

2 matlab实现ycbcr444转RGB

代码语言:javascript
复制
close all
clear all
clc
 
I=imread('1.bmp');
 
[H ,W ,D]=size(I);
 
R=double(I(:,:,1));
G=double(I(:,:,2));
B=double(I(:,:,3));
 
 
Y0= double(zeros(H,W));
Cb0 =double(zeros(H,W));
Cr0 = double(zeros(H,W));
 
R0= double(zeros(H,W));
G0 =double(zeros(H,W));
B0 = double(zeros(H,W));
 
%RGB转YCbCr444
 for i = 1:H
     for j = 1:W
         Y0(i, j) = 0.299*R(i, j) + 0.587*G(i, j) + 0.114*B(i, j);
         Cb0(i, j) = -0.172*R(i, j) - 0.339*G(i, j) + 0.511*B(i, j) + 128;
         Cr0(i, j) = 0.511*R(i, j) - 0.428*G(i, j) - 0.083*B(i, j) + 128;
     end
 end 
 
 for i = 1:H
     for j = 1:W
         RGB(i, j,1) =Y0(i,j)+1.371*(Cr0(i,j)-128);
         RGB(i, j,2) =Y0(i,j)-0.689*(Cr0(i,j)-128)-0.336*(Cb0(i,j)-128);
         RGB(i, j,3) =Y0(i,j)+1.732*(Cb0(i,j)-128);
     end
 end
 
YCbCr(:,:,1)=Y0;
YCbCr(:,:,2)=Cb0;
YCbCr(:,:,3)=Cr0;
 
YCbCr=uint8(YCbCr);
 
RGB=uint8(RGB);
 
figure(1),
imshow(YCbCr),title('YCbCr');
 
figure(2),
imshow(RGB),title('RGB');

转之前(YCbCr444)

转之后(RGB)

3 fpga实现

代码语言:javascript
复制
/*
	计算公式:	
	R = 1.164(Y - 16) + 1.793(CR - 128)                   = 1.164Y           + 1.793CR - 248.128;
	G = 1.164(Y - 16) - 0.534(CR - 128) - 0.213(CB - 128) = 1.164Y - 0.213CB - 0.534CR + 76.992;
	B = 1.164(Y - 16) 		    + 2.115(CB - 128) = 1.164Y + 2.115CB           - 289.344;
	其中,时序在计算过程中完全没有用到
	输入到输出有三个clock的时延。
	第一级流水线计算所有乘法;
	第二级流水线计算所有加法,把正的和负的分开进行加法;
	第三级流水线计算最终的和,若为负数取0;
*/
`timescale 1ns/1ps
module	ycbcr_to_rgb(
	input	clk,
	input	wire[7 : 0]		i_y_8b,
	input	wire[7 : 0]		i_cb_8b,
	input	wire[7 : 0]		i_cr_8b,
 
	input	                i_h_sync,
	input	                i_v_sync,
	input	                i_data_en,
 
	output	wire[7 : 0]		o_r_8b,
	output	wire[7 : 0]		o_g_8b,
	output	wire[7 : 0]		o_b_8b,
 
	output	reg				o_h_sync,
	output	reg				o_v_sync,                                                                                                    
	output	reg				o_data_en                                                                                                   
);

/***************************************parameters*******************************************/
//multiply 256
parameter	para_1164_10b = 10'd297;	//1.160
parameter	para_1793_10b = 10'd459;	//1.793
parameter	para_0534_10b = 10'd137;	//0.535
parameter	para_0213_10b = 10'd54;		//0.211
parameter	para_2115_10b = 10'd541;	//2.113
parameter	para_248128_18b = 18'd63521;//248.128
parameter	para_76992_18b = 18'd19710; //76.992
parameter	para_289344_18b = 18'd74072;//289.344
/********************************************************************************************/

/***************************************signals**********************************************/
wire				sign_r;
wire				sign_g;
wire				sign_b;
reg[17 : 0]	mult_y_for_r_18b;
reg[17 : 0]	mult_y_for_g_18b;
reg[17 : 0]	mult_y_for_b_18b;

reg[17 : 0]	mult_cb_for_g_18b;
reg[17 : 0]	mult_cb_for_b_18b;

reg[17 : 0]	mult_cr_for_r_18b;
reg[17 : 0]	mult_cr_for_g_18b;

reg[17 : 0]	add_r_0_18b;
reg[17 : 0]	add_g_0_18b;
reg[17 : 0]	add_b_0_18b;

reg[17 : 0]	add_r_1_18b;
reg[17 : 0]	add_g_1_18b;
reg[17 : 0]	add_b_1_18b;

reg[17 : 0] result_r_18b;
reg[17 : 0]	result_g_18b;
reg[17 : 0]	result_b_18b;

reg			i_h_sync_delay_1;
reg			i_v_sync_delay_1;
reg			i_data_en_delay_1;

reg			i_h_sync_delay_2;
reg			i_v_sync_delay_2;
reg			i_data_en_delay_2;

/********************************************************************************************/

/***************************************initial**********************************************/
initial
begin
	mult_y_for_r_18b <= 18'd0;
	mult_y_for_g_18b <= 18'd0;
	mult_y_for_b_18b <= 18'd0;
 
	mult_cb_for_g_18b <= 18'd0;
	mult_cb_for_b_18b <= 18'd0;
 
	mult_cr_for_r_18b <= 18'd0;
	mult_cr_for_g_18b <= 18'd0;

 
	add_r_0_18b <= 18'd0;
	add_g_0_18b <= 18'd0;
	add_b_0_18b <= 18'd0;
 
	add_r_1_18b <= 18'd0;
	add_g_1_18b <= 18'd0;
	add_b_1_18b <= 18'd0;
 
	result_r_18b <= 18'd0;
	result_g_18b <= 18'd0;
	result_b_18b <= 18'd0;
 
	i_h_sync_delay_1 <= 1'd0;
	i_v_sync_delay_1 <= 1'd0;
	i_data_en_delay_1 <= 1'd0;
 
	i_h_sync_delay_2 <= 1'd0;
	i_v_sync_delay_2 <= 1'd0;
	i_data_en_delay_2 <= 1'd0;

 
	o_h_sync <= 1'd0;
	o_v_sync <= 1'd0;                                                                                                  
	o_data_en <= 1'd0;                                             	
end 
/********************************************************************************************/
 
/***************************************arithmetic*******************************************/
//LV1 pipeline : mult
always @ (posedge	clk)
begin
	mult_y_for_r_18b <= i_y_8b * para_1164_10b;
	mult_y_for_g_18b <= i_y_8b * para_1164_10b;
	mult_y_for_b_18b <= i_y_8b * para_1164_10b;
end

always @ (posedge	clk)
begin
	mult_cb_for_g_18b <= i_cb_8b * para_0213_10b;
	mult_cb_for_b_18b <= i_cb_8b * para_2115_10b;
end

always @ (posedge	clk)
begin
	mult_cr_for_r_18b <= i_cr_8b * para_1793_10b;
	mult_cr_for_g_18b <= i_cr_8b * para_0534_10b;
end
//LV2 pipeline : add
always @ (posedge	clk)
begin
	add_r_0_18b <= mult_y_for_r_18b + mult_cr_for_r_18b;
	add_r_1_18b <= para_248128_18b;
	add_g_0_18b <= mult_y_for_g_18b + para_76992_18b;
	add_g_1_18b <= mult_cb_for_g_18b + mult_cr_for_g_18b;
	add_b_0_18b <= mult_y_for_b_18b + mult_cb_for_b_18b;
	add_b_1_18b <= para_289344_18b;
end
//LV3 pipeline : y + cb + cr
assign	sign_r = (add_r_0_18b >= add_r_1_18b);
assign	sign_g = (add_g_0_18b >= add_g_1_18b);
assign	sign_b = (add_b_0_18b >= add_b_1_18b);
always @ (posedge	clk)
begin
	result_r_18b = sign_r ? (add_r_0_18b - add_r_1_18b) : 18'd0;
	result_g_18b = sign_g ? (add_g_0_18b - add_g_1_18b) : 18'd0;
	result_b_18b = sign_b ? (add_b_0_18b - add_b_1_18b) : 18'd0;
end

//output 溢出处理
assign	o_r_8b = (result_r_18b[17:16] == 2'b00) ? result_r_18b[15 : 8] : 8'hff;
assign	o_g_8b = (result_g_18b[17:16] == 2'b00) ? result_g_18b[15 : 8] : 8'hff;
assign	o_b_8b = (result_b_18b[17:16] == 2'b00) ? result_b_18b[15 : 8] : 8'hff;
/********************************************************************************************/

/***************************************timing***********************************************/
always @ (posedge	clk)
begin
	i_h_sync_delay_1 <= i_h_sync;
	i_v_sync_delay_1 <= i_v_sync;
	i_data_en_delay_1 <= i_data_en;

	i_h_sync_delay_2 <= i_h_sync_delay_1;
	i_v_sync_delay_2 <= i_v_sync_delay_1;
	i_data_en_delay_2 <= i_data_en_delay_1;

 
	o_h_sync <= i_h_sync_delay_2;
	o_v_sync <= i_v_sync_delay_2;
	o_data_en <= i_data_en_delay_2;
end
/********************************************************************************************/
Endmodule

fpga实现YCbCr444转RGB效果和matlab一致。


本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-09-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 FPGA开源工作室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档