(1)HSL:H色相、S饱和度、L亮度,其中H与HSV中的H一致,但是S饱和度与HSV中的S有区别,HSL呈现出一个双圆锥体形状,白色在上顶点,黑色在下顶点,最大横切面的圆心呈现半程灰色。
(2)matlab实现:
% 清空工作区
clear;
clc;
% 设定文件路径
input_path = 'D:\FPGA\Image processing\9_rgb_hsl\matlab\1_1920x1080.bmp';
output_folder = 'D:\FPGA\Image processing\9_rgb_hsl\matlab\';
txt_path = [output_folder 'output.txt'];
% 读取BMP图片
input_img = imread(input_path);
[height, width, ~] = size(input_img);
% 确保图片尺寸正确
if height ~= 1080 || width ~= 1920
error('图片尺寸必须是1920x1080');
end
% 将RGB转换为HSL
rgb_normalized = double(input_img) / 255;
hsl_img = zeros(size(rgb_normalized));
for i = 1:height
for j = 1:width
r = rgb_normalized(i,j,1);
g = rgb_normalized(i,j,2);
b = rgb_normalized(i,j,3);
cmax = max([r g b]);
cmin = min([r g b]);
delta = cmax - cmin;
% 计算L (Lightness)
L = (cmax + cmin) / 2;
% 计算S (Saturation)
if delta == 0
S = 0;
else
S = delta / (1 - abs(2*L - 1));
end
% 计算H (Hue)
if delta == 0
H = 0;
else
if cmax == r
H = 60 * mod(((g-b)/delta), 6);
elseif cmax == g
H = 60 * (((b-r)/delta) + 2);
else
H = 60 * (((r-g)/delta) + 4);
end
end
if H < 0
H = H + 360;
end
% 将HSL归一化到0-255范围
hsl_img(i,j,1) = round(H * 255/360);
hsl_img(i,j,2) = round(S * 255);
hsl_img(i,j,3) = round(L * 255);
end
end
% 保存HSL数据到txt文件
fid = fopen(txt_path, 'w');
for i = 1:height
for j = 1:width
fprintf(fid, '%d %d %d\n', ...
round(hsl_img(i,j,1)), ...
round(hsl_img(i,j,2)), ...
round(hsl_img(i,j,3)));
end
end
fclose(fid);
% 从txt文件读取HSL数据
fid = fopen(txt_path, 'r');
hsl_restored = zeros(height, width, 3);
for i = 1:height
for j = 1:width
line = fgetl(fid);
values = sscanf(line, '%d %d %d');
hsl_restored(i,j,:) = values;
end
end
fclose(fid);
% 将HSL转换回RGB
rgb_restored = zeros(size(hsl_restored));
for i = 1:height
for j = 1:width
H = hsl_restored(i,j,1) * 360/255;
S = hsl_restored(i,j,2) / 255;
L = hsl_restored(i,j,3) / 255;
% HSL到RGB的转换
function_C = (1 - abs(2*L - 1)) * S;
function_H = H/60;
function_X = function_C * (1 - abs(mod(function_H, 2) - 1));
if function_H >= 0 && function_H < 1
R1 = function_C; G1 = function_X; B1 = 0;
elseif function_H >= 1 && function_H < 2
R1 = function_X; G1 = function_C; B1 = 0;
elseif function_H >= 2 && function_H < 3
R1 = 0; G1 = function_C; B1 = function_X;
elseif function_H >= 3 && function_H < 4
R1 = 0; G1 = function_X; B1 = function_C;
elseif function_H >= 4 && function_H < 5
R1 = function_X; G1 = 0; B1 = function_C;
else
R1 = function_C; G1 = 0; B1 = function_X;
end
function_m = L - (function_C/2);
rgb_restored(i,j,1) = round((R1 + function_m) * 255);
rgb_restored(i,j,2) = round((G1 + function_m) * 255);
rgb_restored(i,j,3) = round((B1 + function_m) * 255);
end
end
% 确保值在0-255范围内
rgb_restored = uint8(max(0, min(255, rgb_restored)));
% 显示原图、HSL图像和还原图像
figure;
subplot(1,3,1); imshow(input_img); title('原图');
subplot(1,3,2); imshow(uint8(hsl_img)); title('HSL图像');
subplot(1,3,3); imshow(rgb_restored); title('还原图像');
% 保存图像
imwrite(input_img, [output_folder 'original.bmp']);
imwrite(uint8(hsl_img), [output_folder 'hsl.bmp']);
imwrite(rgb_restored, [output_folder 'restored.bmp']);
% 计算原图和还原图的PSNR
mse = mean((double(input_img(:)) - double(rgb_restored(:))).^2);
psnr = 10 * log10(255^2/mse);
fprintf('PSNR: %.2f dB\n', psnr);
% 显示处理完成信息
fprintf('所有文件已保存在: %s\n', output_folder);
(3)FPGA实现(RGB转HSL)
module RGB_HSL
(
input wire clk ,
input wire reset ,
input wire valid_i ,
input wire [23:0] rgb_data_i ,
output wire valid_o ,
output wire [7:0] H ,
output wire [7:0] S ,
output wire [7:0] L
);
// 第一级流水线 - 提取RGB分量并计算最大最小值
reg [7:0] r_reg, g_reg, b_reg;
reg [8:0] max_val, min_val; // 增加1位防止溢出
reg [1:0] max_index; // 记录最大值的颜色索引
reg valid_p1;
// 第二级流水线 - 计算L和色差
reg [8:0] luminance; // L = (max + min)/2
reg [8:0] delta; // max - min
reg [1:0] max_index_p2;
reg valid_p2;
reg [8:0] max_val_p2;
reg [8:0] min_val_p2;
// 第三级流水线 - H计算准备
reg [19:0] h_temp; // 放大255倍的H值
reg [19:0] s_temp; // 放大255倍的S值
reg valid_p3;
reg [8:0] luminance_p3;
// 第四级流水线 - 最终计算
reg [7:0] h_final;
reg [7:0] s_final;
reg [7:0] l_final;
reg valid_p4;
// 输入RGB提取
wire [7:0] red = rgb_data_i[23:16];
wire [7:0] green = rgb_data_i[15:8];
wire [7:0] blue = rgb_data_i[7:0];
// 第一级流水线逻辑
always @(posedge clk or posedge reset) begin
if (reset) begin
r_reg <= 8'd0;
g_reg <= 8'd0;
b_reg <= 8'd0;
max_val <= 9'd0;
min_val <= 9'd0;
max_index <= 2'd0;
valid_p1 <= 1'b0;
end
else if (valid_i) begin
r_reg <= red;
g_reg <= green;
b_reg <= blue;
valid_p1 <= valid_i;
// 计算最大值和最小值
if (red >= green && red >= blue) begin
max_val <= {1'b0, red};
max_index <= 2'd0;
end
else if (green >= red && green >= blue) begin
max_val <= {1'b0, green};
max_index <= 2'd1;
end
else begin
max_val <= {1'b0, blue};
max_index <= 2'd2;
end
if (red <= green && red <= blue)
min_val <= {1'b0, red};
else if (green <= red && green <= blue)
min_val <= {1'b0, green};
else
min_val <= {1'b0, blue};
end
else
valid_p1 <= 1'b0;
end
// 第二级流水线逻辑
always @(posedge clk or posedge reset) begin
if (reset) begin
luminance <= 9'd0;
delta <= 9'd0;
max_index_p2 <= 2'd0;
valid_p2 <= 1'b0;
max_val_p2 <= 9'd0;
min_val_p2 <= 9'd0;
end
else if (valid_p1) begin
// 计算亮度 L = (max + min)/2
luminance <= (max_val + min_val) >> 1;
delta <= max_val - min_val;
max_index_p2 <= max_index;
valid_p2 <= valid_p1;
max_val_p2 <= max_val;
min_val_p2 <= min_val;
end
else
valid_p2 <= 1'b0;
end
// 第三级流水线逻辑
always @(posedge clk or posedge reset) begin
if (reset) begin
h_temp <= 20'd0;
s_temp <= 20'd0;
valid_p3 <= 1'b0;
luminance_p3 <= 9'd0;
end
else if (valid_p2) begin
valid_p3 <= valid_p2;
luminance_p3 <= luminance;
// 先计算0-360度范围的H值,然后乘以255/360转换到0-255范围
if (delta == 9'd0)
h_temp <= 20'd0;
else begin
case (max_index_p2)
2'd0: begin // max = red
if (g_reg >= b_reg)
h_temp <= (((g_reg - b_reg) * 20'd60) / delta * 20'd255) / 20'd360;
else
h_temp <= ((((g_reg - b_reg) * 20'd60) / delta + 20'd360) * 20'd255) / 20'd360;
end
2'd1: begin // max = green
h_temp <= ((((b_reg - r_reg) * 20'd60) / delta + 20'd120) * 20'd255) / 20'd360;
end
2'd2: begin // max = blue
h_temp <= ((((r_reg - g_reg) * 20'd60) / delta + 20'd240) * 20'd255) / 20'd360;
end
default: h_temp <= 20'd0;
endcase
end
// 计算饱和度 S (保持不变)
if (luminance == 9'd0 || luminance == 9'd255 || delta == 9'd0)
s_temp <= 20'd0;
else if (luminance <= 9'd127)
s_temp <= (delta * 20'd255) / (max_val_p2 + min_val_p2);
else
s_temp <= (delta * 20'd255) / (9'd510 - max_val_p2 - min_val_p2);
end
else
valid_p3 <= 1'b0;
end
// 第四级流水线逻辑 - 最终输出
always @(posedge clk or posedge reset) begin
if (reset) begin
h_final <= 8'd0;
s_final <= 8'd0;
l_final <= 8'd0;
valid_p4 <= 1'b0;
end
else if (valid_p3) begin
// 规范化H值到0-255
h_final <= (h_temp[19] ? (h_temp + 20'd255) : h_temp);
// 规范化S值到0-255
s_final <= s_temp[7:0];
// 规范化L值到0-255
l_final <= luminance_p3[7:0];
valid_p4 <= valid_p3;
end
else
valid_p4 <= 1'b0;
end
// 输出赋值
assign H = h_final;
assign S = s_final;
assign L = l_final;
assign valid_o = valid_p4;
endmodule
FPGA实现(HSL转RGB)