RGB到HSV的转换公式为
由于s的范围是0到1,所以用verilog实现时,将s扩大256倍,容易表示,当然会丢失精度,其次,这里用到许多除法,笔者用的工具可以直接综合除法,所以这里没有例化除法器,当然,例化除法器ip核也是一样的效果。
实现代码如下:
module rgb2hsv(
input clk,
input reset_n,
input [7:0]rgb_r,
input [7:0]rgb_g,
input [7:0]rgb_b,
input vs,
input hs,
input de,
output [8:0]hsv_h,
output [8:0]hsv_s,
output [7:0]hsv_v,
output hsv_vs,
output hsv_hs,
output hsv_de);
reg [7:0]max;
reg [7:0]min;
reg [13:0]rgb_r_r;
reg [13:0]rgb_g_r;
reg [13:0]rgb_b_r;
reg [13:0]rgb_r_r2;
reg [13:0]rgb_g_r2;
reg [13:0]rgb_b_r2;
reg [7:0]max_r;
wire [7:0]max_min;
assign max_min=max-min;
reg [7:0]max_min_r;
wire [13:0]max60;
assign max60=max*60;
wire [13:0] g_b;
wire [13:0] b_r;
wire [13:0] r_g;
assign g_b=(rgb_g_r>=rgb_b_r)?(rgb_g_r-rgb_b_r):(rgb_b_r-rgb_g_r);
assign b_r=(rgb_b_r>=rgb_r_r)?(rgb_b_r-rgb_r_r):(rgb_r_r-rgb_b_r);
assign r_g=(rgb_r_r>=rgb_g_r)?(rgb_r_r-rgb_g_r):(rgb_g_r-rgb_r_r);
reg [13:0]temp;
reg [13:0]hsv_h_r;
reg [15:0]hsv_s_r;
reg [7:0]hsv_v_r;
always@(posedge clk or negedge reset_n)begin
if(!reset_n)begin
rgb_r_r<=0;
rgb_g_r<=0;
rgb_b_r<=0;
end
else begin
rgb_r_r<=60*rgb_r;
rgb_g_r<=60*rgb_g;
rgb_b_r<=60*rgb_b;
end
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)begin
rgb_r_r2<=0;
rgb_g_r2<=0;
rgb_b_r2<=0;
end
else begin
rgb_r_r2<=rgb_r_r;
rgb_g_r2<=rgb_g_r;
rgb_b_r2<=rgb_b_r;
end
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
max<=0;
else if((rgb_r>=rgb_b)&&(rgb_r>=rgb_g))
max<=rgb_r;
else if((rgb_g>=rgb_b)&&(rgb_g>=rgb_r))
max<=rgb_g;
else if((rgb_b>=rgb_r)&&(rgb_b>=rgb_g))
max<=rgb_b;
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
min<=0;
else if((rgb_r<=rgb_b)&&(rgb_r<=rgb_g))
min<=rgb_r;
else if((rgb_g<=rgb_b)&&(rgb_g<=rgb_r))
min<=rgb_g;
else if((rgb_b<=rgb_r)&&(rgb_b<=rgb_g))
min<=rgb_b;
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
max_min_r<=0;
else
max_min_r<=max_min;
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
temp<=0;
else if(max_min!=0)begin
if(rgb_r_r==max60)
temp<=g_b/{6'b0,max_min};
else if(rgb_g_r==max60)
temp<=b_r/{6'b0,max_min};
else if(rgb_b_r==max60)
temp<=r_g/{6'b0,max_min};
end
else if(max_min==0)
temp<=0;
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
max_r<=0;
else
max_r<=max;
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
hsv_h_r<=0;
else if(max_r==0)
hsv_h_r<=0;
else if(rgb_r_r2==60*max_r)
hsv_h_r<=(rgb_g_r2>=rgb_b_r2)?temp:(14'd360-temp);
else if(rgb_g_r2==60*max_r)
hsv_h_r<=(rgb_b_r2>=rgb_r_r2)?(temp+120):(14'd120-temp);
else if(rgb_b_r2==60*max_r)
hsv_h_r<=(rgb_r_r2>=rgb_g_r2)?(temp+240):(14'd240-temp);
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
hsv_s_r<=0;
else if(max_r==0)
hsv_s_r<=0;
else
hsv_s_r<={max_min_r,8'b0}/{8'b0,max_r};
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
hsv_v_r<=0;
else
hsv_v_r<=max_r;
end
reg [2:0]vs_delay;
reg [2:0]hs_delay;
reg [2:0]de_delay;
always@(posedge clk or negedge reset_n)begin
if(!reset_n)begin
vs_delay<=0;
hs_delay<=0;
de_delay<=0;
end
else begin
vs_delay <= { vs_delay[1:0],vs};
hs_delay <= { hs_delay[1:0],hs};
de_delay <= { de_delay[1:0],de};
end
end
assign hsv_vs=vs_delay[2];
assign hsv_hs=hs_delay[2];
assign hsv_de=de_delay[2];
assign hsv_h=hsv_h_r[8:0];
assign hsv_s=hsv_s_r[8:0];
assign hsv_v=hsv_v_r;
endmodule
HSV到RGB的转换公式:
实现代码:
module hsv2rgb(
input clk,
input reset_n,
input [8:0]i_hsv_h,
input [8:0]i_hsv_s,
input [7:0]i_hsv_v,
input vs,
input hs,
input de,
output [7:0]rgb_r,
output [7:0]rgb_g,
output [7:0]rgb_b,
output rgb_vs,
output rgb_hs,
output rgb_de
);
reg [7:0]i_hsv_v_r1;
reg [7:0]i_hsv_v_r2;
reg [7:0]i_hsv_v_r3;
reg [7:0]i_hsv_v_r4;
reg [8:0]i_hsv_h_r;
reg [8:0]i_hsv_s_r1;
reg [8:0]i_hsv_s_r2;
reg [8:0]i_hsv_s_r3;
reg [8:0]i_hsv_s_r4;
wire [8:0]temp;
assign temp=9'd256-i_hsv_s;
reg [16:0] p;//p=V-V*S,,扩大256
reg [7:0] p2;
reg [7:0]p3;
reg [2:0]I;//H/60的商
reg [2:0]I2;
reg [2:0]I3;
wire [5:0]f;//H/60的余数
assign f=i_hsv_h_r-I*60;
reg [15:0]f_60;
reg [15:0]adjust;
always@(posedge clk or negedge reset_n)begin
if(!reset_n)begin
i_hsv_v_r1 <= 0;
i_hsv_v_r2 <= 0;
i_hsv_v_r3<=0;
i_hsv_v_r4<=0;
end
else begin
i_hsv_v_r1<=i_hsv_v;
i_hsv_v_r2<=i_hsv_v_r1;
i_hsv_v_r3<=i_hsv_v_r2;
i_hsv_v_r4<=i_hsv_v_r3;
end
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
i_hsv_h_r<=0;
else
i_hsv_h_r<=i_hsv_h;
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)begin
i_hsv_s_r1<=0;
i_hsv_s_r2<=0;
i_hsv_s_r3<=0;
i_hsv_s_r4<=0;
end
else begin
i_hsv_s_r1<=i_hsv_s;
i_hsv_s_r2<=i_hsv_s_r1;
i_hsv_s_r3<=i_hsv_s_r2;
i_hsv_s_r4<=i_hsv_s_r3;
end
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)begin
p<=0;
p2<=0;
p3<=0;
end
else begin
p<=temp*i_hsv_v;
p2<=p[15:8];
p3<=p2;
end
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
I<=0;
else if(i_hsv_h<60)
I<=0;
else if((i_hsv_h<120)&&(i_hsv_h>=60))
I<=1;
else if((i_hsv_h<180)&&(i_hsv_h>=120))
I<=2;
else if((i_hsv_h<240)&&(i_hsv_h>=180))
I<=3;
else if((i_hsv_h<300)&&(i_hsv_h>=240))
I<=4;
else
I<=5;
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)begin
I2<=0;
I3<=0;
end
else begin
I2<=I;
I3<=I2;
end
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
f_60<=0;
else
f_60<={f,8'b0}/60;
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)
adjust<=0;
else
adjust<=(i_hsv_v_r2-p2)*f_60[7:0];
end
/**************************************/
reg [7:0]rgb_r_r;
reg [7:0]rgb_g_r;
reg [7:0]rgb_b_r;
reg [3:0]vs_delay;
reg [3:0]hs_delay;
reg [3:0]de_delay;
always@(posedge clk or negedge reset_n)begin
if(!reset_n)begin
rgb_r_r<=0;
rgb_g_r<=0;
rgb_b_r<=0;
end
else case(I3)
0: begin
rgb_r_r<=i_hsv_v_r3;
rgb_g_r<=p3+adjust[15:8];
rgb_b_r<=p3;
end
1: begin
rgb_r_r<=i_hsv_v_r3-adjust[15:8];
rgb_g_r<=i_hsv_v_r3;
rgb_b_r<=p3;
end
2: begin
rgb_r_r<=p3;
rgb_g_r<=i_hsv_v_r3;
rgb_b_r<=p3+adjust[15:8];
end
3: begin
rgb_r_r<=p3;
rgb_g_r<=i_hsv_v_r3-adjust[15:8];
rgb_b_r<=i_hsv_v_r3;
end
4: begin
rgb_r_r<=p3+adjust[15:8];
rgb_g_r<=p3;
rgb_b_r<=i_hsv_v_r3;
end
5: begin
rgb_r_r<=i_hsv_v_r3;
rgb_g_r<=p3;
rgb_b_r<=i_hsv_v_r3-adjust[15:8];
end
default: begin
rgb_r_r<=0;
rgb_g_r<=0;
rgb_b_r<=0;
end
endcase
end
always@(posedge clk or negedge reset_n)begin
if(!reset_n)begin
vs_delay<=0;
hs_delay<=0;
de_delay<=0;
end
else begin
vs_delay<={vs_delay[2:0],vs};
hs_delay<={hs_delay[2:0],hs};
de_delay<={de_delay[2:0],de};
end
end
assign rgb_r = (i_hsv_s_r4==0)?i_hsv_v_r4:rgb_r_r;
assign rgb_g = (i_hsv_s_r4==0)?i_hsv_v_r4:rgb_g_r;
assign rgb_b = (i_hsv_s_r4==0)?i_hsv_v_r4:rgb_b_r;
assign rgb_vs = vs_delay[3];
assign rgb_hs = hs_delay[3];
assign rgb_de = de_delay[3];
endmodule
参考文献:
[1]袁奋杰, 周晓, 丁军,等. 基于FPGA的RGB和HSV色空间转换算法实现[J]. 电子器件, 2010, 33(4):5.