FPGA学习笔记——图像处理之亮度调节(乘法型)

目录

一、任务

二、乘法型

1.表达式

三、代码

1.v文件

(1)brightness_adjust_mul.v

(2)brightness.v

2.仿真文件

(1)tb.v

(2)video_source

四、实现现象

(1)变亮

(2)变暗


一、任务

将下面这幅图片进行亮度调节。(RGB888)


二、乘法型

1.表达式

I_out = I_in × k
I_in :输入像素值(0-255)
k :亮度缩放系数(通常0.0-2.0)
I_out :输出像素值
思路:根据表达式,将输入的一个颜色(红、绿、蓝),进行缩放,然后再输出。但是Verilog中没有小数的表示,所以把k给变成(0~255),k为128则图像数据不变,小于128则变暗,大于128则变亮。这个的位宽要考虑清楚,两个数相乘位宽是两个位宽相加,最后输出的要进行截断,也就是成8位输出。


三、代码

1.v文件

(1)brightness_adjust_mul.v

rust 复制代码
`timescale 1ns / 1ps
module brightness_adjust_mul(
input                   clk                ,
input                   rst_n              ,
input           [7:0]   pixel_in           ,
input           [7:0]   scale              , //缩放系数(0-255,128=1.0)
output  reg     [7:0]   pixel_out 
);
reg [15:0]  product ;
//乘法运算调节亮度
always @(posedge clk) begin
    if(!rst_n)
        product <= 0;
    else
        product <= pixel_in * scale;
end

//截断
always @(posedge clk) begin
    if(!rst_n)
        pixel_out <= 0;
    else if (product[15] == 1) //product[15] == 1
        pixel_out <= 8'hff;
    else if(product[15] == 0) //product[15] == 0
        pixel_out <= product[14:7]; // product >> 7
end

endmodule

(2)brightness.v

rust 复制代码
`timescale 1ns / 1ps
module brightness(
input           clk         ,
input           rst_n       ,
input   [7:0]   scale       ,
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   
    );

reg [1:0]   i_vsync_r;
reg [1:0]   i_hsync_r;
reg [1:0]   i_vaild_r;
       
//红色   
brightness_adjust_mul brightness_adjust_mul_u1(
.   clk        (clk)       ,
.   rst_n      (rst_n)       ,
.   pixel_in   (i_rgb888[23:16])       ,
.   scale      (scale)       , //缩放系数(0-255,128=1.0)
.   pixel_out  (o_rgb888[23:16])
);

//绿色
brightness_adjust_mul brightness_adjust_mul_u2(
.   clk        (clk)       ,
.   rst_n      (rst_n)       ,
.   pixel_in   (i_rgb888[15:8])       ,
.   scale      (scale)       , //缩放系数(0-255,128=1.0)
.   pixel_out  (o_rgb888[15:8])
);

//蓝色
brightness_adjust_mul brightness_adjust_mul_u3(
.   clk        (clk)                ,
.   rst_n      (rst_n)              ,
.   pixel_in   (i_rgb888[7:0])      ,
.   scale      (scale)              , //缩放系数(0-255,128=1.0)
.   pixel_out  (o_rgb888[7:0])
);

//同步打拍,否则图像会平移
always @(posedge clk) begin
    i_vsync_r <= {i_vsync_r[0],i_vsync};
    i_hsync_r <= {i_hsync_r[0],i_hsync};
    i_vaild_r <= {i_vaild_r[0],i_vaild};
end

assign o_vsync = i_vsync_r[1];
assign o_hsync = i_hsync_r[1];
assign o_vaild = i_vaild_r[1];


endmodule

2.仿真文件

(1)tb.v

rust 复制代码
`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;
end

brightness brightness_u(
. clk      (clk)   ,
. rst_n    (rst_n)   ,
. scale    (90)   ,
. i_rgb888 (i_rgb888)   ,
. i_vsync  ()   ,
. 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

rust 复制代码
`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;   // 鍦哄悓姝ユ瀬鎬?
`endif

localparam 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 begin
    bmp_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]);//娉ㄦ剰鍙傛暟%c
	   else       
           $fwrite(bmp_dout_id, "%c", wr_data[i]);//娉ㄦ剰鍙傛暟%c
    end
    $fclose(bmp_dout_id);
    #100;
    $stop ;
    
end


//----璇诲嚭鍥惧儚鏁版嵁--------------------------------
always@(posedge pclk)begin
    if(source_de_o) begin
        if(addr_rd >= addr_size-3)
            addr_rd<=54;
        else
            addr_rd<=addr_rd+3;
    end
end


assign source_data_o={rd_data[addr_rd],rd_data[addr_rd+1],rd_data[addr_rd+2]};    //R + G + B

//----鍐欏叆鍥惧儚鏁版嵁--------------------------------
always@(posedge pclk)begin
    if(de_i) begin
        if(addr_wr >= addr_size-3)
            addr_wr<=54;
        else
            addr_wr<=addr_wr+3;
    end
end

always@(posedge pclk)begin
    wr_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];
end

localparam  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)begin
    if(!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;
   else
        source_de_o<=0;
end



always@(posedge pclk)begin
    if(!rstn)
        cnt_h<=0;
    else if(cnt_h == H_TOTAL_TIME-1)
        cnt_h<=0;
    else
        cnt_h<=cnt_h+1;
end

always@(posedge pclk)begin
    if(!rstn)
        cnt_v<=0;
    else if(cnt_h == H_TOTAL_TIME-1)begin
        if(cnt_v == V_TOTAL_TIME-1)
            cnt_v<=0;
        else
            cnt_v<=cnt_v+1;
    end
end



endmodule

注意:这里的图片地址,按照自己的图片路径来修改。


四、实现现象

(1)变亮

(2)变暗


以上就是图像增强之亮度调节(乘法型)。(如果有错误的地方,还请大家指出来,谢谢!)

相关推荐
能不能别报错2 小时前
K8s学习笔记(五) Velero结合minnio业务数据备份与恢复
笔记·学习·kubernetes
能不能别报错2 小时前
K8s学习笔记(六) K8s升级与节点管理
笔记·学习·kubernetes
今天也好累2 小时前
贪心算法之分数背包问题
c++·笔记·学习·算法·贪心算法
不枯石3 小时前
Matlab通过GUI实现点云的随机(Random)下采样(附最简版)
图像处理·计算机视觉·matlab
文火冰糖的硅基工坊3 小时前
[硬件电路-320]:模拟电路与数字电路,两者均使用晶体管(如BJT、MOSFET),但模拟电路利用其线性区,数字电路利用其开关特性。
单片机·嵌入式硬件·数学建模·fpga开发·系统架构·信号处理
誰能久伴不乏3 小时前
Linux Shell 脚本:从零到进阶的实战笔记
linux·chrome·笔记
九年义务漏网鲨鱼3 小时前
等效学习率翻倍?梯度累积三连坑:未除以 accum_steps、调度器步进错位、梯度裁剪/正则标度错误(含可复现实验与修复模板)
python·深度学习·学习
ooolmf4 小时前
3.1.1话题,发布小说笔记20250923
笔记
未来之窗软件服务4 小时前
自己写算法(五)CryptoJS 前端学习——东方仙盟练气期
学习·算法·仙盟创梦ide·东方仙盟·东方仙盟加密