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)变暗


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

相关推荐
摇滚侠12 分钟前
Spring Boot3零基础教程,响应式编程,前景提要,笔记108
java·spring boot·笔记
禁默16 分钟前
第四届图像处理、计算机视觉与机器学习国际学术会议(ICICML 2025)
图像处理·机器学习·计算机视觉
Antonio91541 分钟前
【图像处理】tiff格式介绍
图像处理·人工智能
Antonio91543 分钟前
【图像处理】png 格式详解
图像处理
AndrewHZ44 分钟前
【图像处理基石】什么是alpha matting?
图像处理·人工智能·计算机视觉·matting·发丝分割·trimap·人像模式
Han.miracle1 小时前
Java的多线程——多线程(3)线程安全
java·开发语言·jvm·学习·安全·线程·多线程
x_lrong1 小时前
本地访问远端环境tensorboard
linux·笔记·ai·虚拟机·云服务器·tensorboard
d111111111d1 小时前
STM32外设学习--TIM定时器--输入捕获---测频方法。
stm32·单片机·学习
hit56实验室2 小时前
如何在DCU上面编译llama.cpp
笔记
WPG大大通3 小时前
AIoT | 软件:Astra MCP边缘算力构建详解
经验分享·笔记·python·硬件架构·代码