直方圖均衡化實(shí)驗(yàn),主要包括三部分,直方圖統(tǒng)計(jì)、計(jì)算累加直方圖、均衡化。
1、直方圖統(tǒng)計(jì)
? ? ? ?直方圖統(tǒng)計(jì)就是記錄每個(gè)灰度值在圖片中出現(xiàn)的像素次數(shù),灰度圖片有0-255個(gè)灰度級(jí),如果我們定義256個(gè)寄存器來(lái)存儲(chǔ)數(shù)據(jù)比較麻煩,所以借用RAM來(lái)實(shí)現(xiàn)直方圖統(tǒng)計(jì)。當(dāng)輸入一個(gè)像素點(diǎn)的灰度值,將其作為地址,在RAM中讀出該地址對(duì)應(yīng)的數(shù)據(jù),進(jìn)行加1操作,然后再寫會(huì)該地址。
? ? ? ?我配置了一個(gè)雙端口RAM u1來(lái)進(jìn)行直方圖統(tǒng)計(jì),當(dāng)輸入圖片數(shù)據(jù)流有效時(shí),讀地址為輸入圖片數(shù)據(jù)流的灰度值,將讀出的數(shù)據(jù)加一后再寫回,從a端口進(jìn)行讀數(shù)據(jù),從b端口進(jìn)行寫 數(shù)據(jù),為了防止讀寫數(shù)據(jù)產(chǎn)生沖突,我將寫數(shù)據(jù)的地址延遲了一個(gè)時(shí)鐘周期;兩張圖片輸入之間,場(chǎng)同步信號(hào)會(huì)有一段時(shí)間保持在低電平,這段時(shí)間沒有輸入圖片像素?cái)?shù)據(jù),在這段時(shí)間將RAM中的數(shù)據(jù)讀出,并將RAM清零。地址從0遍歷到255,每讀出一個(gè)地址的數(shù)據(jù)后,相應(yīng)將該地址清零,這個(gè)過程和讀出數(shù)據(jù)加一再寫回的過程類似。
2、計(jì)算累加直方圖
? ? ? ?將上一步讀出的RAM數(shù)據(jù)進(jìn)行累加,存放在另一個(gè)RAM u2中,u2中存放累加直方圖的信息,這個(gè)過程也是在場(chǎng)同步信號(hào)會(huì)有一段時(shí)間保持在低電平時(shí)期完成。地址從0遍歷到255,將累加后的數(shù)據(jù)sum寫入RAM,地址遍歷完累加直方圖計(jì)算完成。
3、均衡化
? ? ? ?在第二張圖片輸入時(shí),根據(jù)像素點(diǎn)灰度值對(duì)應(yīng)的地址,在u2中讀出累計(jì)直方圖數(shù)據(jù),通過圖中的公式,計(jì)算出均衡化后的灰度值,最后將計(jì)算后的數(shù)據(jù)輸出。
4、代碼
module histogram_equ(
input clk,
input rst_n,
input per_frame_vsync,
input per_frame_href,
input per_frame_clken,
input [7:0] per_img_Y,
output post_frame_vsync,
output post_frame_href,
output post_frame_clken,
output [7:0] post_img_Y
);
localparam IMG_TOTAL_PIXEL=307200; //640*480
localparam IMG_MAX_GRAY=256; //0-255
//reg web;
wire [18:0] cnt,cntplus; //同一灰度級(jí)像素個(gè)數(shù)計(jì)數(shù)器
wire [18:0] ram_his_rd_data; //從累計(jì)直方圖中讀出的數(shù)據(jù)
reg vsync_delay;
wire vsync_negedge; //場(chǎng)同步信號(hào)下降沿
wire vsync_posedge; //場(chǎng)同步信號(hào)上升沿
reg web2; //雙端口RAM u2的寫使能信號(hào)
reg tag; //標(biāo)志位
reg [7:0] dizhi;
reg [7:0] dizhi1,dizhi2; //雙端口RAM u2的寫數(shù)據(jù)地址
wire [7:0] addra; //雙端口RAM u1的a端口地址
wire [18:0] dout; //雙端口RAM u1的輸出數(shù)據(jù)
wire [18:0] din; //雙端口RAM u1的輸入數(shù)據(jù)
reg [7:0] addrb; //雙端口RAM u1的b端口地址
wire web; //雙端口RAM的寫使能
reg [18:0] sum; //為了計(jì)算累加直方圖,用于存放直方圖數(shù)據(jù)的和
wire [18:0] ram_accu_rddata; //從累加直方圖中讀出的數(shù)據(jù)
//統(tǒng)計(jì)像素個(gè)數(shù)時(shí)的寫使能信號(hào)
//always @(posedge clk)
//begin
// web<=per_frame_clken;
// //addrb<=per_img_Y;
//end
assign cntplus=cnt+1;
//將場(chǎng)同步信號(hào)延時(shí)一拍
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
vsync_delay<=1'b0;
else
vsync_delay<=per_frame_vsync;
end
assign vsync_negedge=vsync_delay&(!per_frame_vsync);
assign vsync_posedge=(!vsync_delay)&per_frame_vsync;
always @(posedge clk)
begin
dizhi1<=dizhi;
dizhi2<=dizhi1;
end
//在一幀圖像輸入完成后需要對(duì)RAM進(jìn)行數(shù)據(jù)讀出和數(shù)據(jù)清0,此時(shí)的讀寫數(shù)據(jù)地址為變量dizhi
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
dizhi<=8'd0;
else
begin
if(tag==0)
begin
if(dizhi==255)
dizhi<=dizhi;
else
dizhi<=dizhi+1;
end
end
end
//在對(duì)累計(jì)直方圖進(jìn)行寫操作時(shí),只有在標(biāo)志位tag=0時(shí)才進(jìn)行,并且只遍歷一次0-255地址
always @(posedge clk)
begin
if(tag==0)
begin
if(dizhi2==255)
web2<=0;
else
web2<=1;
end
end
//當(dāng)場(chǎng)有效信號(hào)為上升沿時(shí),標(biāo)志位置1,下降沿時(shí),標(biāo)志位置0。tag=1代表正在輸入圖像數(shù)據(jù)流,tag=0代表兩幀圖像輸入數(shù)據(jù)流之間的間隙
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
tag<=1;
else
begin
if(vsync_posedge)
tag<=1;
if(vsync_negedge)
tag<=0;
end
end
always @(posedge clk)
begin
addrb<=addra;
end
assign addra=tag?per_img_Y:dizhi; //當(dāng)輸入圖像數(shù)據(jù)流時(shí),地址為每個(gè)像素點(diǎn)圖像灰度值對(duì)應(yīng)的地址,當(dāng)處于兩幀圖像輸入數(shù)據(jù)流之間的間隙時(shí),地址為0-255遍歷過程的地址
assign cnt=tag?dout:cnt; //當(dāng)輸入圖像數(shù)據(jù)流時(shí),cnt與u1 的輸出數(shù)據(jù)相連,否則保持
assign ram_his_rd_data=web2?dout:ram_his_rd_data; //當(dāng)web2有效時(shí),從累計(jì)直方圖中讀出的數(shù)據(jù)與雙端口RAM u2的輸出相連,否則保持
assign din=tag?cntplus:(19'd0); //當(dāng)tag=1時(shí),輸入為+1后的數(shù)據(jù),當(dāng)tag=0時(shí),需要對(duì)RAN進(jìn)行清0操作,所以輸入為0
assign web=tag?per_frame_clken:1; //tag=1時(shí),使能信號(hào)為幀時(shí)鐘使能信號(hào),tag=0時(shí),要對(duì)RAM進(jìn)行清零操作,所以使能信號(hào)一直為1
//計(jì)算累加直方圖要輸入的數(shù)據(jù)
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
sum<=19'd0;
end
else
begin
if(web2==1)
begin
sum<=sum+ram_his_rd_data;
end
end
end
//雙端口RAM u1,用于存放直方圖的數(shù)據(jù),當(dāng)輸入圖片數(shù)據(jù)流有效時(shí),將每個(gè)像素點(diǎn)灰度值對(duì)應(yīng)的地址存放的數(shù)據(jù)讀出,再加1,然后再寫回去
//在幀與幀之間的間隙,從地址0-255,將累計(jì)直方圖數(shù)據(jù)讀出,再將RAM清零
ram_ip u1(
.clka(clk),
.wea(1'b0),
.addra(addra), // input wire [7 : 0] addra
.dina(0), // input wire [18 : 0] dina
.douta(dout), // output wire [18 : 0] douta
.clkb(clk), // input wire clkb
.web(web), // input wire [0 : 0] web
.addrb(addrb), // input wire [7 : 0] addrb
.dinb(din), // input wire [18 : 0] dinb
.doutb() // output wire [18 : 0] doutb
);
//雙端口RAM u2,用于存放累加直方圖數(shù)據(jù),將累加直方圖的數(shù)據(jù)從a端口寫入,b端口讀出
ram_ip u2(
.clka(clk),
.wea(web2),
.addra(dizhi2), // input wire [7 : 0] addra
.dina(sum), // input wire [18 : 0] dina
.douta(), // output wire [18 : 0] douta
.clkb(per_frame_clken), // input wire clkb
.web(1'b0), // input wire [0 : 0] web
.addrb(per_img_Y), // input wire [7 : 0] addrb
.dinb(), // input wire [18 : 0] dinb
.doutb(ram_accu_rddata) // output wire [18 : 0] doutb
);
/直方圖均衡化
reg [26:0] data_mult; //乘法運(yùn)算結(jié)果
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
data_mult<=27'd0;
else
data_mult<=ram_accu_rddata*(IMG_MAX_GRAY-1);
end
reg [7:0] data_div; //除法運(yùn)算結(jié)果
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
data_div<=8'd0;
else
data_div<=data_mult/IMG_TOTAL_PIXEL;
end
//------------------------------------------
//lag 3 clocks signal sync
reg [2:0] per_frame_vsync_r;
reg [2:0] per_frame_href_r;
reg [2:0] per_frame_clken_r;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
per_frame_vsync_r <= 0;
per_frame_href_r <= 0;
per_frame_clken_r <= 0;
end
else
begin
per_frame_vsync_r <= {per_frame_vsync_r[1:0], per_frame_vsync};
per_frame_href_r <= {per_frame_href_r[1:0], per_frame_href};
per_frame_clken_r <= {per_frame_clken_r[1:0], per_frame_clken};
end
end
assign post_frame_vsync = per_frame_vsync_r[2];
assign post_frame_href = per_frame_href_r[2];
assign post_frame_clken = per_frame_clken_r[2];
assign post_img_Y = post_frame_href?data_div:8'd0;
endmodule
5、結(jié)果圖
6、參考資料
https://blog.csdn.net/qq_32010099/article/details/123060197文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-734257.html
https://www.bilibili.com/video/BV1JV411J7ef/?spm_id_from=333.1007.top_right_bar_window_history.content.click&vd_source=8b552433c6e99d96c09feffd0ad1ed7a文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-734257.html
到了這里,關(guān)于FPGA圖像處理仿真實(shí)驗(yàn)——直方圖均衡化的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!