使用FPGA对图像直方图做出均衡化,公式如下:
$$D _ { B } = f ( D _ { A } ) = \frac { D _ { m a x } } { A _ { 0 } } \sum _ { i = 0 } ^ { D _ { A } } H ( i )$$
上式中,H(i)为第i级灰度的像素个数,A为图像的面积,也即像素总数。因此,
计算均衡后的图像步骤如下:
(1)首先计算出当前图像的直方图H(i)
(2)其次计算像素直方图累计和
(3)将上式乘以灰度值的最大值
(4)将上式除以图像像素总数
后两步运算统称为归一化运算。
要把上述算法映射到FPGA中,第一步需要做的工作是什么呢?自然是帧缓存。
这是由于直方图统计需要至少一帧的数据才能完成。第一帧完成后,根据上述步骤计算出来的累加和∑,H()中的D,已经是一顿之前的像素值了。要得到这个值进行累加和查找,就必须要至少缓存一帧图像。
加速操作-近似直方图均衡化
在实际应用中,处理帧缓存是费时费力费资源的一件事情,在许多情况下,图像的变换比较慢,在这种情况下的一个近似是当建立当前帧的直方图统计结果时使用从前一帧得到的映射。结果是直方图均衡化可能不是非常准确,但是消耗的资源和处理的延时都有显著地减少。
/***********************************************************
********* Company: WHUT
********* Engineer: ZhengXiaoliang
********* Design Name:
********* Module Name: hist_equalized.v
********* Project Name: Image Process
********* Description: histogram equalized operation
********* Dependencies:
***********************************************************/
// Engineer: radiumlrb
// Date: 2023.10.03
// Version: 1.0
`timescale 1ns/1ns
module hist_equalized(
rst_n,
clk,
din_valid,
din,
dout,
vsync,
dout_valid,
vsync_out
);
parameter DW = 8;
parameter IH = 512;
parameter IW = 640;
parameter TW = 32;
localparam TOTAL_CNT = IW * IH;
localparam HALF_WIDTH = (TW>>1);
localparam latency = 6;
input rst_n;
input clk;
input din_valid;
input [DW-1:0]din;
output [DW-1:0]dout;
input vsync;
output vsync_out;
output dout_valid;
reg [DW-1:0]hist_cnt_addr;
wire [TW-1:0]hist_cnt_out;
histogram_2d hist(
.rst_n(rst_n),
.clk(clk),
.din_valid(din_valid),
.din(din),
.vsync(vsync),
.hist_cnt_addr(hist_cnt_addr),
.hist_cnt_out(hist_cnt_out)
);
defparam hist.DW = DW;
defparam hist.IH = IH;
defparam hist.IW = IW;
wire vsync_fall;
wire valid;
reg [1:0]frame_cnt;
reg hist_valid_temp;
reg vsync_r;
reg [latency:0]valid_r;
always @(posedge clk or negedge rst_n)
if (((~(rst_n))) == 1'b1) begin
valid_r[latency:0] <= {latency+1{1'b0}};
end
else begin
valid_r <= #1 {valid_r[latency-1:0],valid};
end
reg [DW-1:0]din_r;
always @(posedge clk or negedge rst_n)
if (((~(rst_n))) == 1'b1) begin
hist_cnt_addr <= {DW{1'b0}};
end
else begin
if(valid_r[0])
hist_cnt_addr <= #1 din_r;
end
reg [2*TW-1:0]mul_temp[0:2];
reg [DW-1:0]dout_temp;
// for 512*512
generate
if((IW ==512) & (IH ==512) )begin :IW_512
always @(posedge clk or negedge rst_n)
if (((~(rst_n))) == 1'b1) begin
mul_temp[0] <= {2*TW{1'b0}};
end
else begin
if(valid_r[1])
//hist_cnt_out*255,DW must be 8
mul_temp[0] <= #1 {{TW-DW{1'b0}},hist_cnt_out[TW-1:0],{DW{1'b0}}} - {{TW{1'b0}},hist_cnt_out};
if(valid_r[1])
//hist_cnt_out/(512*512) IW = IH = 512
mul_temp[1] <= #1 {{18{1'b0}},mul_temp[0][2*TW-1:18]};
if(valid_r[2])
dout_temp <= #1 mul_temp[1][DW-1:0];
end
end
endgenerate
// for 640*512
generate
if(IW ==640 & IH ==512 ) begin :IW_640
wire [2*TW-1:0]dout_tmp ;
assign dout_tmp = {{16{1'b0}},mul_temp[2][2*TW-1:16]};
always @(posedge clk or negedge rst_n)
if (((~(rst_n))) == 1'b1) begin
mul_temp[0] <= {2*TW{1'b0}};
end
else begin
if(valid_r[1])
//hist_cnt_out*51,DW must be 8
//hist_cnt_out*32 + hist_cnt_out*16
mul_temp[0] <= #1 {{TW-5{1'b0}},hist_cnt_out[TW-1:0],{5{1'b0}}} + {{TW-4{1'b0}},hist_cnt_out[TW-1:0],{4{1'b0}}};
//hist_cnt_out*2 + hist_cnt_out*1
mul_temp[1] <= #1 {{TW{1'b0}},hist_cnt_out[TW-1:0]} + {{TW-1{1'b0}},hist_cnt_out[TW-1:0],{1{1'b0}}};
if(valid_r[1])
//hist_cnt_out/(64*2*512)
mul_temp[2] <= #1 mul_temp[0] + mul_temp[1];
//
if(valid_r[2])
dout_temp <= #1 dout_tmp[DW-1:0];
end
end
endgenerate
assign dout = dout_temp;
assign dout_valid = valid_r[latency];
assign vsync_out = vsync;
endmodule
标签:din,均衡化,cnt,Research,hist,直方图,valid,vsync From: https://www.cnblogs.com/radiumlrb/p/17741037.html