6.RGB转YCbcr

6.RGB转YCbcrRGB 转灰度有很多种方式 1 将 RGB 中任意分量拿出来当做灰度值

大家好,欢迎来到IT知识分享网。

1.方法

1.1 YUV(YCbCr)格式

1.1.1 YUV4:4:4

  YUV三个通道采样率相同,因此每个分量相互独立。通常一个分量占8bit,一个像素占3byte。

1.1.2 YUV4:2:2

  YUV三个通道采样率不同,UV分量只有Y的一半,两个UV共占用一个Y。

1.2 RGB转YCbCr公式

在这里插入图片描述
  但是由于Verilog HDL无法进行浮点运算,因此使用扩大256倍,再向右移8Bit的方式来转换公式,(0.083 = 00010101)
在这里插入图片描述

2.算法验证平台搭建

2.1 图片转txt文本

  首先将图片转化为txt文本格式方便其他模块读取。

clear ; clc ; close; RGB = imread('../img/1920x1080.bmp'); imshow(RGB); [row,col,chn] = size(RGB); fid = fopen('../data//pre.txt','w+'); for i = 1:row for j = 1:col for k = 1:chn fprintf(fid,'%02x',RGB(i,j,k)); end fprintf(fid,'\n'); end end fclose(fid); 

2.2 txt文本数据仿真回传

2.2.1 文本读取

  这里首先读取MATLAB生成的pre.txt文本,读取txt文本的模块为img_gen3,表示读取的RGB888的数据。

`timescale 1ns / 1ps module img_gen3 #( parameter ACTIVE_IW = 1920 , parameter ACTIVE_IH = 1080 , parameter TOTAL_IW = 2200 , parameter TOTAL_IH = 1100 , parameter H_START = 100 , parameter V_START = 4 )( input wire clk , input wire rst_n , output reg vs , output reg de , output reg [23:0] data ); reg [23:0] raw_array [ACTIVE_IW*ACTIVE_IH-1:0]; integer i; initial begin for(i=0;i<ACTIVE_IW*ACTIVE_IH;i=i+1) raw_array[i] = 0; end initial begin $readmemh("H:/picture/Z7/lesson6/data/pre.txt",raw_array); end reg [15:0] hcnt ; reg [15:0] vcnt ; reg h_de ; reg v_de ; reg index_de ; reg [31:0] index ; always @(posedge clk or negedge rst_n) if(!rst_n) hcnt <= 'd0; else if(hcnt == TOTAL_IW - 1) hcnt <= 'd0; else hcnt <= hcnt + 1'b1; always @(posedge clk or negedge rst_n) if(!rst_n) vcnt <= 'd0; else if(hcnt == TOTAL_IW - 1 && vcnt == TOTAL_IH - 1) vcnt <= 'd0; else if(hcnt == TOTAL_IW - 1) vcnt <= vcnt + 1'b1; else vcnt <= vcnt; always @(posedge clk or negedge rst_n) if(!rst_n) vs <= 'd0; else if(vcnt>=2) vs <= 1'b1; else vs <= 1'b0; always @(posedge clk or negedge rst_n) if(!rst_n) h_de <= 'd0; else if(hcnt >= H_START && hcnt < H_START + ACTIVE_IW) h_de <= 1'b1; else h_de <= 1'b0; always @(posedge clk or negedge rst_n) if(!rst_n) v_de <= 'd0; else if(vcnt >= V_START && vcnt < V_START + ACTIVE_IH) v_de <= 1'b1; else v_de <= 1'b0; always @(posedge clk or negedge rst_n) if(!rst_n) index_de <= 'd0; else if(index == ACTIVE_IW * ACTIVE_IH-1) index_de <= 1'b0; else if(h_de == 1'b1 && v_de == 1'b1) index_de <= 1'b1; else index_de <= 1'b0; always @(posedge clk or negedge rst_n) if(!rst_n) index_de <= 'd0; else if(h_de == 1'b1 && v_de == 1'b1) index_de <= 1'b1; else index_de <= 1'b0; always @(posedge clk or negedge rst_n) if(!rst_n) index <= 'd0; else if(index == ACTIVE_IW * ACTIVE_IH-1) index <= 1'b0; else if(index_de == 1'b1) index <= index + 1; else index <= index; always @(posedge clk or negedge rst_n) if(!rst_n) de <= 'd0; else de <= index_de; always @(posedge clk or negedge rst_n) if(index_de == 1'b1) data <= raw_array[index]; else data <= 0; endmodule 

2.2.1 读取写入

  读取的数据在顶层写入为post.txt。

`timescale 1ns / 1ps module tb_top( ); reg clk ; reg rst_n ; integer outfile; initial begin clk = 0; rst_n = 0; #20 rst_n = 1; outfile = $fopen("H:/picture/Z7/lesson6/data/post.txt","w"); end always #5 clk = ~clk; wire vs ; wire de ; wire [23:0] data; img_gen3 #( .ACTIVE_IW (1920 ), .ACTIVE_IH (1080 ), .TOTAL_IW (2200 ), .TOTAL_IH (1100 ), .H_START (100 ), .V_START (4 ) )u_img_gen3( .clk (clk ), .rst_n (rst_n ), .vs (vs ), .de (de ), .data (data ) ); reg vs_r ; always @(posedge clk) if(rst_n == 0) vs_r <= 1'b0; else vs_r <= vs; always @(posedge clk) if(~vs&&vs_r) $stop; else if(de == 1) $fdisplay(outfile,"%h\t%h\t%h",data[23:16],data[15:8],data[7:0]); endmodule 

2.2.3 MATLAB数据读取

  这里对比pre.txt和post.txt是否相等的方式有很多中,可以直接用文本对比工具,也可以用MATLAB做对比。这里只做一个txt转bmp。

clear ; clc ; close; RGB = imread('../img/1920x1080.bmp'); imshow(RGB); [row,col,chn] = size(RGB); fid = fopen('../data//pre.txt','w+'); for i = 1:row for j = 1:col for k = 1:chn fprintf(fid,'%02x',RGB(i,j,k)); end fprintf(fid,'\n'); end end fclose(fid); 

搭建后对比pre.txt与post.txt的数据一致。可以开始验证算法了。

3 rgb2ycbcr算法实现与仿真

3.1 rgb2ycbcr算法实现

  本算法实现包括三个时钟周期,第一个时钟周期算乘法,第二个时钟周期算加减,第三个时钟周期算触发(截位)。

module rgb2ycbcr( input wire clk , //系统时钟 input wire rst_n , //复位信号 input wire pre_hsync , //输入的场同步 input wire pre_vsync , //输入行同步 input wire pre_de , //数据有效信号 input wire [ 7:0] pre_r , //输入像素数据 input wire [ 7:0] pre_g , input wire [ 7:0] pre_b , output reg post_hsync , //输出行同步 output reg post_vsync , //输出场同步 output reg post_de , //输出数据有效信号 output reg [7:0] post_y , //输出y(亮度)分量 output reg [7:0] post_cb , //输出蓝色色度分量 output reg [7:0] post_cr //输出红色色度分量 ); localparam SYNC = 2; reg [15:0] pre_r0 ; reg [15:0] pre_r1 ; reg [15:0] pre_r2 ; reg [15:0] pre_g0 ; reg [15:0] pre_g1 ; reg [15:0] pre_g2 ; reg [15:0] pre_b0 ; reg [15:0] pre_b1 ; reg [15:0] pre_b2 ; reg [15:0] post_y0 ; reg [15:0] post_cb0; reg [15:0] post_cr0; reg [SYNC-1:0] pre_hsync_r; reg [SYNC-1:0] pre_vsync_r; reg [SYNC-1:0] pre_de_r ; /* RGB888 to YCbCr Y = 0.299R +0.587G + 0.114B Cb = 0.568(B-Y) + 128 = -0.172R-0.339G + 0.511B + 128 CR = 0.713(R-Y) + 128 = 0.511R-0.428G -0.083B + 128 Y = (77 *R + 150*G + 29 *B)>>8 Cb = (-43*R - 85 *G + 128*B)>>8 + 128 Cr = (128*R - 107*G - 21 *B)>>8 + 128 Y = (77 *R + 150*G + 29 *B )>>8 Cb = (-43*R - 85 *G + 128*B + 32768)>>8 Cr = (128*R - 107*G - 21 *B + 32768)>>8 */ //计算乘法项 always @(posedge clk)begin if(rst_n == 0)begin pre_r0 <= 'd0; pre_r1 <= 'd0; pre_r2 <= 'd0; end else if(pre_de) begin pre_r0 <= pre_r *77; pre_r1 <= pre_r *43; pre_r2 <= pre_r *128; end end always @(posedge clk)begin if(rst_n == 0)begin pre_g0 <= 'd0; pre_g1 <= 'd0; pre_g2 <= 'd0; end else if(pre_de) begin pre_g0 <= pre_g *150; pre_g1 <= pre_g *85 ; pre_g2 <= pre_g *107; end end always @(posedge clk)begin if(rst_n == 0)begin pre_b0 <= 'd0; pre_b1 <= 'd0; pre_b2 <= 'd0; end else if(pre_de) begin pre_b0 <= pre_b *29; pre_b1 <= pre_b *128 ; pre_b2 <= pre_b *21; end end //计算加减法 always @(posedge clk)begin if(rst_n == 0)begin post_y0 <= 0; post_cb0 <= 0; post_cr0 <= 0; end else if(pre_de_r[0]) begin post_y0 <= pre_r0 + pre_g0 + pre_b0; post_cb0 <= 32768 - pre_r1 - pre_g1 + pre_b1; post_cr0 <= 32768 + pre_r2 - pre_g2 - pre_b2; end end //移位赋值 always @(posedge clk)begin if(rst_n == 0)begin post_y <= 0; post_cb <= 0; post_cr <= 0; end else if(pre_de_r[1]) begin post_y <= post_y0 /256; post_cb <= post_cb0/256; post_cr <= post_cr0/256; end end //本次计算一共用了三个时钟周期 所以其余的信号需要打三拍出来 always @(posedge clk)begin if(rst_n == 0)begin { 
   post_hsync,pre_hsync_r} <= 0; { 
   post_vsync,pre_vsync_r} <= 0; { 
   post_de ,pre_de_r } <= 0; end else begin { 
   post_hsync,pre_hsync_r} <= { 
   pre_hsync_r,pre_hsync}; { 
   post_vsync,pre_vsync_r} <= { 
   pre_vsync_r,pre_vsync}; { 
   post_de ,pre_de_r } <= { 
   pre_de_r ,pre_de }; end end endmodule 

3.2 算法仿真与验证

3.2.1 算法仿真模块

`timescale 1ns / 1ps module tb_rgb2ycbcr(); reg clk ; reg rst_n ; reg pre_hsync ; wire pre_vsync ; wire pre_de ; wire [7:0] pre_r ; wire [7:0] pre_g ; wire [7:0] pre_b ; wire post_hsync ; wire post_vsync ; wire post_de ; wire [7:0] post_y ; wire [7:0] post_cb ; wire [7:0] post_cr ; integer outfile; always #10 clk = ~clk; initial begin clk = 0; rst_n = 0; pre_hsync = 1; #200 rst_n = 1; outfile = $fopen("H:/picture/Z7/lesson6/data/post.txt","w"); end img_gen3#( .ACTIVE_IW (1920 ), .ACTIVE_IH (1080 ), .TOTAL_IW (2200 ), .TOTAL_IH (1100 ), .H_START (100 ), .V_START (4 ) )u_img_gen3( .clk (clk ), .rst_n (rst_n ), .vs (pre_vsync ), .de (pre_de ), .data ({ 
   pre_r,pre_g,pre_b}) ); rgb2ycbcr u1_rgb2ycbcr( .clk (clk ), //系统时钟 .rst_n (rst_n ), //复位信号 .pre_hsync (pre_hsync ), //输入的场同步 .pre_vsync (pre_vsync ), //输入行同步 .pre_de (pre_de ), //数据有效信号 .pre_r (pre_r ), //输入像素数据 .pre_g (pre_g ), .pre_b (pre_b ), .post_hsync (post_hsync ), //输出行同步 .post_vsync (post_vsync ), //输出场同步 .post_de (post_de ), //输出数据有效信号 .post_y (post_y ), //输出y(亮度)分量 .post_cb (post_cb ), //输出蓝色色度分量 .post_cr (post_cr ) //输出红色色度分量 ); reg vs_r ; always @(posedge clk) if(rst_n == 0) vs_r <= 1'b0; else vs_r <= post_vsync; always @(posedge clk) if(~post_vsync&&vs_r) $stop; else if(post_de == 1) $fdisplay(outfile,"%h",post_y); endmodule 

3.2.2 算法的MATLAB验证

clc; clear all; RGB = imread('../img/1920x1080.bmp'); [row,col,chn] = size(RGB); RGB = double(RGB); for i = 1:row for j = 1:col for k = 1:chn Y(i,j) = (77*RGB(i,j,1) + 150*RGB(i,j,2) + 29*RGB(i,j,3) )/256; Cb(i,j) = (-43*RGB(i,j,1) - 85*RGB(i,j,2) + 128*RGB(i,j,3) +32768 )/256; Cr(i,j) = (128*RGB(i,j,1) - 107*RGB(i,j,2) - 21*RGB(i,j,3) +32768 )/256; end end end matlab_Y = uint8(floor(Y)); a = textread('../data/post.txt','%s'); IMdec = hex2dec(a); col = 1920; row = 1080; IM = reshape(IMdec,col,row); fpga_Y = uint8(IM)'; subplot(1,2,1) imshow(matlab_Y),title('MATLAB算法图像'); subplot(1,2,2) imshow(fpga_Y),title('FPGA算法图像'); sub = matlab_Y - fpga_Y; min_sub = min(min(sub)); max_sub = max(max(sub)); 

3.2.3 TXT转bmp

clear; clc; close all; a = textread('../data/post.txt','%s'); IMdec = hex2dec(a); col = 1920; row = 1080; IM = reshape(IMdec,col,row); b = uint8(IM)'; imwrite(b,'../img/post.bmp'); imshow('../img/post.bmp'); 

在这里插入图片描述

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/129666.html

(0)
上一篇 2025-08-22 18:26
下一篇 2025-08-22 18:45

相关推荐

发表回复

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

关注微信