FPGA学习笔记——图像处理之饱和度调节(RGB)
目录
一、任务
二、饱和度调节
表达式:
三、代码
1.v代码
(1)satur_adjust
2.仿真代码
(1)tb
(2)video_source
四、实验现象
一、任务
将下面这幅图片进行饱和度调节。
二、饱和度调节
饱和度(Saturation)指颜色的鲜艳程度,饱和度越高,颜色越鲜艳;饱和度越低,颜色越接近灰色。饱和度调节是图像处理中的常见操作,广泛应用于摄影后期、视频调色、图像增强等领域。
表达式:
·original:原始 RGB 像素值
·gray:原始像素的灰度值(Y)
·α:饱和度调节系数
·α=1:保持原图不变
·α>1:增强饱和度(颜色更鲜艳)
·0<α<1:降低饱和度(颜色更灰)
·α=0:完全去饱和度(灰度图)
思路:先将输入进来的RGB图像数据,转成Y(灰度值),然后根据公式进行流水线的操作。
三、代码
1.v代码
(1)satur_adjust
`timescale 1ns / 1ps
module satur_adjust(
input clk ,
input rst_n ,
input [7:0] satur_va ,
input [23:0] i_rgb888 ,
input i_vsync ,
input i_hsync ,
input i_vaild ,
output [23:0] o_rgb888 ,
output o_vsync ,
output o_hsync ,
output o_vaild );wire [7:0] Y;reg [15:0] temp0_r;reg [15:0] temp0_g;reg [15:0] temp0_b;reg [16:0] temp1_r;reg [16:0] temp1_g;reg [16:0] temp1_b;reg [9:0] temp2_r;reg [9:0] temp2_g;reg [9:0] temp2_b;wire [8:0] temp3_r;wire [8:0] temp3_g;wire [8:0] temp3_b;reg [2:0] i_vsync_r;reg [2:0] i_hsync_r;reg [2:0] i_vaild_r;reg [7:0] Y_r0,Y_r1;assign Y = (77*i_rgb888[23:16] + 150*i_rgb888[15:8] + 29*i_rgb888[7:0]) >> 8;always@(posedge clk) beginY_r0 <= Y;Y_r1 <= Y_r0;end//----第一级流水线--------------------always @(posedge clk) beginif(!rst_n)begintemp0_r <= 0;temp0_g <= 0;temp0_b <= 0;endelse begintemp0_r <= i_rgb888[23:16] - Y;temp0_g <= i_rgb888[15:8] - Y;temp0_b <= i_rgb888[7:0] - Y;endend//------第二级流水线------------------always @(posedge clk) beginif(!rst_n)begintemp1_r <= 0;temp1_g <= 0;temp1_b <= 0;endelse begintemp1_r <= temp0_r* satur_va;temp1_g <= temp0_g* satur_va;temp1_b <= temp0_b* satur_va;endend//----第三级流水线---------------------always@(posedge clk) beginif(!rst_n)begintemp2_r <= 0;temp2_g <= 0;temp2_b <= 0;endelse begintemp2_r <= temp1_r[16:7] + Y_r1;temp2_g <= temp1_g[16:7] + Y_r1;temp2_b <= temp1_b[16:7] + Y_r1;endend//-----判断正负----------------------assign temp3_r = (temp2_r[9]==1)? 9'h00:temp2_r[8:0];assign temp3_g = (temp2_g[9]==1)? 9'h00:temp2_g[8:0];assign temp3_b = (temp2_b[9]==1)? 9'h00:temp2_b[8:0];assign o_rgb888[23:16] = (temp3_r[8] == 1) ? 8'hff:temp3_r[7:0];assign o_rgb888[15:8] = (temp3_g[8] == 1) ? 8'hff:temp3_g[7:0];assign o_rgb888[7:0] = (temp3_b[8] == 1) ? 8'hff:temp3_b[7:0];//同步打拍,否则图像会平移
always @(posedge clk) begini_vsync_r <= {i_vsync_r[1:0],i_vsync};i_hsync_r <= {i_hsync_r[1:0],i_hsync};i_vaild_r <= {i_vaild_r[1:0],i_vaild};
endassign o_vsync = i_vsync_r[2];
assign o_hsync = i_hsync_r[2];
assign o_vaild = i_vaild_r[2];endmodule
2.仿真代码
(1)tb
`timescale 1ns / 1ps
module tb();reg clk = 0;
reg rst_n = 0;
wire [23:0] i_rgb888;
wire [23:0] o_rgb888;
wire i_vaild;
wire o_vaild;always #10 clk = ~clk;
initial begin#100;rst_n = 1;
endsatur_adjust satur_adjust_u(
. clk (clk) ,
. rst_n (rst_n) ,
. satur_va (220),
. i_rgb888 (i_rgb888) ,
. i_vsync (i_vaild) ,
. i_hsync () ,
. i_vaild (i_vaild) ,
. o_rgb888 (o_rgb888) ,
. o_vsync () ,
. o_hsync () ,
. o_vaild (o_vaild));video_source video_source_u(
. pclk (clk) ,
. rstn (rst_n) ,
//----图像输出----------------------
. source_de_o (i_vaild) ,
. source_data_o (i_rgb888),
//----图像输入----------------------
. de_i (o_vaild) ,
. data_i (o_rgb888));endmodule
(2)video_source
`timescale 1ns / 1ps
`define VIDEO_1280_720
module video_source#(
parameter VSYNC=720,HSYNC=1280,DELAY1=50_000_000 //鍥惧儚澶勭悊寤惰繜)(
input pclk ,
input rstn ,
//----鍥惧儚杈撳嚭----------------------
output reg source_de_o ,
output [23:0] source_data_o,
//----鍥惧儚杈撳叆----------------------
input de_i ,
input [23:0] data_i);
//1280X720 74.25MHZ
`ifdef VIDEO_1280_720
parameter H_ACTIVE = 1280;// 琛屾暟鎹湁鏁堟椂闂?
parameter H_FRONT_PORCH = 110; // 琛屾秷闅愬墠鑲╂椂闂?
parameter H_SYNC_TIME = 40; // 琛屽悓姝ヤ俊鍙锋椂闂?
parameter H_BACK_PORCH = 220; // 琛屾秷闅愬悗鑲╂椂闂?
parameter H_POLARITY = 1; // 琛屽悓姝ユ瀬鎬?
parameter V_ACTIVE = 720; // 鍒楁暟鎹湁鏁堟椂闂?
parameter V_FRONT_PORCH = 5; // 鍒楁秷闅愬墠鑲╂椂闂?
parameter V_SYNC_TIME = 5; // 鍒楀悓姝ヤ俊鍙锋椂闂?
parameter V_BACK_PORCH = 20; // 鍒楁秷闅愬悗鑲╂椂闂?
parameter V_POLARITY = 1; // 鍦哄悓姝ユ瀬鎬?
`endiflocalparam addr_size=HSYNC*VSYNC*3+54; //鎬诲瓧鑺傛暟
//鏂囦欢鍚?
integer bmp_file_id;
integer bmp_dout_id;
//鏂囦欢鍙ユ焺
integer h;
reg [7:0] rd_data [addr_size-1:0]; //鏍规嵁鑷繁鍥剧墖澶у皬 BMP鏍煎紡涓猴細浣嶅浘鏂囦欢澶达紙14瀛楄妭锛?+浣嶅浘淇℃伅澶达紙40瀛楄妭锛?+瀹為檯鍍忕礌鐐瑰崰鍐呭瓨
reg [7:0] wr_data [addr_size-1:0];
integer i=0;
integer addr_rd=54;
integer addr_wr=54;initial beginbmp_file_id = $fopen("D:/intelFPGA_lite/haiyunjiexun/text_Vivado/image_isp/image_1.bmp","rb"); //鎵撳紑鍘熷鍥惧儚bmp_dout_id = $fopen("D:/intelFPGA_lite/haiyunjiexun/text_Vivado/image_isp/image_1_out.bmp","wb"); //鎵撳紑杈撳嚭鍥惧儚h = $fread(rd_data,bmp_file_id); //璇诲彇bmp鏂囦欢 璇诲彇鍒扮殑鏁版嵁灏嗕細渚濇鏀惧叆rd_data涓?$fclose(bmp_file_id); //璇诲彇瀹屾瘯#DELAY1 ; //鍥惧儚澶勭悊寤惰繜for(i = 0; i < addr_size; i = i + 1)begin //鍥惧儚鏁版嵁鍐欏叆鏂囦欢if(i < 54)$fwrite(bmp_dout_id, "%c", rd_data[i]);//娉ㄦ剰鍙傛暟%celse $fwrite(bmp_dout_id, "%c", wr_data[i]);//娉ㄦ剰鍙傛暟%cend$fclose(bmp_dout_id);#100;$stop ;end//----璇诲嚭鍥惧儚鏁版嵁--------------------------------
always@(posedge pclk)beginif(source_de_o) beginif(addr_rd >= addr_size-3)addr_rd<=54;elseaddr_rd<=addr_rd+3;end
endassign source_data_o={rd_data[addr_rd],rd_data[addr_rd+1],rd_data[addr_rd+2]}; //R + G + B//----鍐欏叆鍥惧儚鏁版嵁--------------------------------
always@(posedge pclk)beginif(de_i) beginif(addr_wr >= addr_size-3)addr_wr<=54;elseaddr_wr<=addr_wr+3;end
endalways@(posedge pclk)beginwr_data[addr_wr]=data_i[23:16]; //鍐欏叆瀛樺偍鍣?wr_data[addr_wr+1]=data_i[15:8];wr_data[addr_wr+2]=data_i[7:0];
endlocalparam H_TOTAL_TIME=H_ACTIVE+H_FRONT_PORCH+H_SYNC_TIME+H_BACK_PORCH;
localparam V_TOTAL_TIME=V_ACTIVE+V_FRONT_PORCH+V_SYNC_TIME+V_BACK_PORCH;
reg [31:0] cnt_v; //鍦哄悓姝ヨ鏁板櫒
reg [31:0] cnt_h; //琛屽悓姝ヨ鏁板櫒always@(posedge pclk)beginif(!rstn)source_de_o<=0;else if(( cnt_h > (H_SYNC_TIME + H_BACK_PORCH -1)) && (cnt_h <= (H_SYNC_TIME + H_BACK_PORCH + H_ACTIVE -1)) && (cnt_v > (V_SYNC_TIME + V_BACK_PORCH-1)) && (cnt_v <= (V_SYNC_TIME + V_BACK_PORCH + V_ACTIVE-1)))source_de_o<=1;elsesource_de_o<=0;
endalways@(posedge pclk)beginif(!rstn)cnt_h<=0;else if(cnt_h == H_TOTAL_TIME-1)cnt_h<=0;elsecnt_h<=cnt_h+1;
endalways@(posedge pclk)beginif(!rstn)cnt_v<=0;else if(cnt_h == H_TOTAL_TIME-1)beginif(cnt_v == V_TOTAL_TIME-1)cnt_v<=0;elsecnt_v<=cnt_v+1;end
endendmodule
四、实验现象
以上就是图像处理之饱和度调节。(如果有错误的地方,还请大家指出来,谢谢!)