基于FPGA的图像RGB转CIE-Lab实现,包含testbench和MATLAB辅助验证程序

1.算法运行效果图预览

 

将FPGA的结果导入到matlab,并和matlab的仿真结果进行对比:

 

 

 

2.算法运行软件版本

vivado2019.2

 

matlab2022a

 

3.算法理论概述

      RGB和CIE-Lab是两种常用的颜色空间,它们在不同的应用领域中各有优势。RGB颜色空间主要用于显示设备,而CIE-Lab颜色空间则更适用于颜色测量和计算。因此,将RGB颜色空间转换为CIE-Lab颜色空间具有重要的应用价值。

 

       RGB颜色模式是一种常见的颜色表示方法,它是通过红、绿、蓝三种颜色的不同比例来表示不同的颜色。其中,红、绿、蓝三种颜色的值分别范围在0到255之间。

 

       CIELAB颜色模式是一种更加科学的颜色表示方法,它是基于人眼对颜色的感知来定义的。CIELAB颜色模式包括三个分量:L表示亮度,a表示绿色到红色的色差,b表示蓝色到黄色的色差。RGB到CIELAB转换可以通过以下步骤进行:

 

将RGB颜色模式转换为X, Y, Z三个分量的CIE XYZ颜色模式。

将CIE XYZ颜色模式转换为CIE Lab*颜色模式。

计算CIELAB颜色模式的L, a, b三个分量。

3.1RGB颜色空间

       RGB颜色空间是一种基于红、绿、蓝三种基本颜色的颜色空间。在该空间中,任意一种颜色都可以由这三种基本颜色的不同强度组合而成。RGB颜色空间通常用于显示设备,如电视、计算机显示器等。

 

3.2CIE-Lab颜色空间

       CIE-Lab颜色空间是一种基于人类视觉系统的颜色空间,由国际照明委员会(CIE)制定。在该空间中,颜色的表示与人眼的感知更加一致。CIE-Lab颜色空间由三个分量组成:L表示亮度,a表示红绿色差,b*表示黄蓝色差。

 

3.3RGB转CIE-Lab算法原理

       RGB转CIE-Lab的转换过程可以分为两个步骤:首先将RGB颜色空间转换为XYZ颜色空间,然后将XYZ颜色空间转换为CIE-Lab颜色空间。

 

RGB转XYZ

 

RGB转XYZ的转换公式如下:

 

X = 0.4124R + 0.3576G + 0.1805B

Y = 0.2126R + 0.7152G + 0.0722B

Z = 0.0193R + 0.1192G + 0.9505B

 

       其中,R、G、B分别表示红、绿、蓝三个通道的颜色值,取值范围为[0,255]。X、Y、Z表示转换后的XYZ颜色空间的三个分量。

 

XYZ转CIE-Lab

 

XYZ转CIE-Lab的转换公式如下:

 

L* = 116f(Y/Yn) - 16

a* = 500[f(X/Xn) - f(Y/Yn)]

b* = 200[f(Y/Yn) - f(Z/Zn)]

 

       其中,Xn、Yn、Zn表示XYZ颜色空间的参考白点的坐标值。f(t)是一个非线性函数,定义如下:

 

f(t) = t^(1/3) (当t>0.008856时)

= 7.787t + 16/116 (当t≤0.008856时)

 

在FPGA设计过程中,一般将上述公式转换为如下表达式进行处理:

 

 

fX = XT .* X.^(1/3) + (~XT) .* (7.787 .* X + 4/29);

fY = YT .* Y.^(1/3) + (~YT) .* (7.787 .* Y + 4/29);

fZ = ZT .* Z.^(1/3) + (~ZT) .* (7.787 .* Z + 4/29);

 

 

 

4.部分核心程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/08/01 
// Design Name:
// Module Name: RGB2gray
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
  
  
module test_image;
  
reg i_clk;
reg i_rst;
reg [7:0] Rbuff [0:100000];
reg [7:0] Gbuff [0:100000];
reg [7:0] Bbuff [0:100000];
reg [7:0] i_Ir,i_Ig,i_Ib;
wire [7:0] o_X,o_Y,o_Z;
wire [15:0] o_L;
wire signed[15:0] o_A,o_B;
integer fids1,dat1,fids2,dat2,fids3,dat3,jj=0;
  
//D:\D:\FPGA_Proj\FPGAtest\code_proj
initial
begin
    fids1 = $fopen("D:\\FPGA_Proj\\FPGAtest\\code_proj\\R.bmp","rb");
    dat1  = $fread(Rbuff,fids1);
    $fclose(fids1);
end
  
initial
begin
    fids2 = $fopen("D:\\FPGA_Proj\\FPGAtest\\code_proj\\G.bmp","rb");
    dat2  = $fread(Gbuff,fids2);
    $fclose(fids2);
end
  
initial
begin
    fids3 = $fopen("D:\\FPGA_Proj\\FPGAtest\\code_proj\\b.bmp","rb");
    dat3 = $fread(Bbuff,fids3);
    $fclose(fids3);
end
  
  
  
initial
begin
i_clk=1;
i_rst=1;
#1200;
i_rst=0;
end
  
always #5  i_clk=~i_clk;
  
always@(posedge i_clk)
begin
    i_Ir<=Rbuff[jj];
    i_Ig<=Gbuff[jj];
    i_Ib<=Bbuff[jj];
    jj<=jj+1;
end
  
  
  
main_lab main_lab_u(
.i_clk    (i_clk),
.i_rst    (i_rst),
.i_image_R      (i_Ir),
.i_image_G      (i_Ig),
.i_image_B      (i_Ib),
.o_X            (o_X),
.o_Y            (o_Y),
.o_Z            (o_Z),
.o_L            (o_L),
.o_A            (o_A),
.o_B            (o_B)
);
  
  
integer fout1;
initial begin
 fout1 = $fopen("X.txt","w");
end
  
always @ (posedge i_clk)
 begin
    if(jj<=66615)
    $fwrite(fout1,"%d\n",o_X);
    else
    $fwrite(fout1,"%d\n",0);
end
  
integer fout2;
initial begin
 fout2 = $fopen("Y.txt","w");
end
  
always @ (posedge i_clk)
 begin
    if(jj<=66615)
    $fwrite(fout2,"%d\n",o_Y);
    else
    $fwrite(fout2,"%d\n",0);
end
  
  
integer fout3;
initial begin
 fout3 = $fopen("Z.txt","w");
end
  
always @ (posedge i_clk)
 begin
    if(jj<=66615)
    $fwrite(fout3,"%d\n",o_Z);
    else
    $fwrite(fout3,"%d\n",0);
end
  
  
integer fout4;
initial begin
 fout4 = $fopen("L.txt","w");
end
  
always @ (posedge i_clk)
 begin
    if(jj<=66615)
    $fwrite(fout4,"%d\n",o_L);
    else
    $fwrite(fout4,"%d\n",0);
end
  
integer fout5;
initial begin
 fout5 = $fopen("A.txt","w");
end
  
always @ (posedge i_clk)
 begin
    if(jj<=66615)
    $fwrite(fout5,"%d\n",o_A);
    else
    $fwrite(fout5,"%d\n",0);
end
  
  
integer fout6;
initial begin
 fout6 = $fopen("B.txt","w");
end
  
always @ (posedge i_clk)
 begin
    if(jj<=66615)
    $fwrite(fout6,"%d\n",o_B);
    else
    $fwrite(fout6,"%d\n",0);
end
  
endmodule

  

posted @   简简单单做算法  阅读(75)  评论(0编辑  收藏  举报
(评论功能已被禁用)
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示