????????對于圖像的灰度處理,原理與基于FPGA的圖像反轉(zhuǎn)相同,但算法不同。相交于基于FPGA的圖像反轉(zhuǎn),基于FPGA的圖像灰度處理操作時間由于FPGA的并行性,其處理時間與前者相同。雖然工作量大了4倍左右,但處理時間基本相同,在仿真中,仍在5.2ms完成了處理。凸顯出FPGA圖像處理的優(yōu)勢特點(diǎn)。下文將對FPGA圖像灰度處理各部分進(jìn)行講解。
- 處理效果
先上處理效果,以下為對我妹妹的臉部進(jìn)行灰度處理效果。
512*512 處理前 ???????????
????????????????????????????????????????????????????????????????512*512 處理后
- 處理過程
????????通過python使用PILLOW,獲得輸入bmp圖片的RGB值,并將R/G/B三個分量分別以16進(jìn)制寫入三個txt文件中。再通過vivado仿真FPGA處理,讀取三個txt文件數(shù)據(jù)分別到三個寄存器中。再從寄存器中讀取數(shù)據(jù),以verilog語言進(jìn)行RGB轉(zhuǎn)YCbCr格式處理。在格式轉(zhuǎn)換過程中,同時以兩個always模塊處理乘、加和一個assig取高8位進(jìn)行運(yùn)算。得到Y(jié)CbCr的Y分量之后,將Y分量輸出到一個txt文件中,即為灰度轉(zhuǎn)換的512*512圖片的結(jié)果。通過python使用OpenCV將txt文件讀取,分配到512*512個像素中,即可得到灰度處理后的bmp圖像。
????????2.1讀取lzy.bmp圖像,通過配置miniconda環(huán)境中的PILLOW庫,讀取圖片RGB數(shù)據(jù),分離輸出RGB的值到red、green、blue.txt文件。
from PIL import Image
# 打開圖像文件
image = Image.open('lzy.bmp') # 圖像文件路徑
# 獲得圖像的 RGB 數(shù)據(jù)
rgb_values = list(image.getdata())
# 分離 R、G、B 值
r_values = [rgb[0] for rgb in rgb_values]
g_values = [rgb[1] for rgb in rgb_values]
b_values = [rgb[2] for rgb in rgb_values]
# 將 R、G、B 值寫入文本文件
with open('red.txt', 'w') as file:
for value in r_values:
file.write(format(value, '02X') + '\n')
with open('green.txt', 'w') as file:
for value in g_values:
file.write(format(value, '02X') + '\n')
with open('blue.txt', 'w') as file:
for value in b_values:
file.write(format(value, '02X') + '\n')
# 關(guān)閉圖像文件
image.close()
????????2.2在vivado中用Verilog語言編寫RGB轉(zhuǎn)YCbCr源文件、并編寫testbench文件讀取數(shù)據(jù)進(jìn)行仿真。在源文件中,對于YCbCr格式由于在Verilog語言中,對浮點(diǎn)運(yùn)算處理較為復(fù)雜,所以乘100轉(zhuǎn)為整數(shù)數(shù)據(jù)處理,簡化運(yùn)算。通過Y =(77 *R + 150*G + 29 *B)>>8,進(jìn)行計算,先進(jìn)行乘法運(yùn)算,再進(jìn)行加法運(yùn)算,最后取高8位,得到應(yīng)輸出的Y值。
Source:
module rgb_to_ycbcr
(
input clock, ?
input rst,
input [7:0] input_red_data,
input [7:0] input_green_data,
input [7:0] input_blue_data,
output [7:0] output_gray_data
);
reg [15:0] img_red_r0;
reg [15:0] img_green_r0;
reg [15:0] img_blue_r0;
always@(posedge clock or negedge rst)
begin
if(rst)
begin
img_red_r0 <= 0;
img_green_r0 <= 0;
img_blue_r0 <= 0;
end
else
begin
img_red_r0 <= input_red_data * 8'd77;
img_green_r0 <= input_green_data * 8'd150;
img_blue_r0 <= input_blue_data * 8'd29;
end
end
reg [15:0] img_Y_r0;
always@(posedge clock or negedge rst)
begin
if(rst)
begin
img_Y_r0 <= 0;
end
else
begin
img_Y_r0 <= img_red_r0 + img_green_r0 + img_blue_r0;
end
end
assign ?output_gray_data = img_Y_r0[15:8];
endmodule
???在testbench仿真文件中,通過分別讀取先前輸出的red/green/blue.txt文件到,red/green/blue_data寄存器中,設(shè)置基本仿真條件,從寄存器輸入數(shù)據(jù)到input_red/green/blue_data中。創(chuàng)建gray.txt文件,將輸出結(jié)果output_gray_data輸入到gray.txt文件中,即可得到灰度處理后的灰度值。
Simulation:
`timescale 1ns/1ps
module rgb_to_ycbcr_tb;
????reg clock;
????reg rst;
????reg [7:0] red_data [(512*512-1):0];
????reg [7:0] green_data [(512*512-1):0];
????reg [7:0] blue_data [(512*512-1):0];
????reg[18:0] cnt;
????integer file_id;
????wire[7:0] input_red_data;
????wire[7:0] input_green_data; ???
????wire[7:0] input_blue_data;
????
????wire[7:0] output_gray_data;
????initial begin
???? clock = 1'b0;
??? ?forever #10 clock = ~clock;
????end
????initial begin
?????cnt = 19'b0;
?????$readmemh("./red.txt", red_data);
?????$readmemh("./green.txt",green_data); ???
?????$readmemh("./blue.txt",blue_data); ??????
?????file_id = $fopen("./gray.txt", "w");
? ??end
????initial begin
?????rst = 1'b1;
?????#195 rst = 1'b0;
?????#20000000 $stop;
?????$fclose(file_id);
????end
????assign input_red_data = red_data[cnt[17:0]];
????assign input_green_data = green_data[cnt[17:0]];
????assign input_blue_data = blue_data[cnt[17:0]];
always @(posedge clock or posedge rst) ?????????????????????
????????if (rst) begin ?????????????????????????????????????????/
????????????cnt <= 19'b0; ??????????????????????????????????????/
????????end ????????????????????????????????????????????????????/
????????else if(cnt[18] == 1'b0) ???????????????????????????????/
????????begin ??????????????????????????????????????????????????/
????????????$fwrite(file_id, "0x%x\n", output_gray_data); ???????????/
????????????cnt <= cnt + 1'b1; ?????????????????????????????????/
????????end ????????????????????????????????????????????????????/
????rgb_to_ycbcr u_rgb_to_ycbcr(
????????????.clock(clock),
????????????.rst(rst),
????
????????????.input_red_data(input_red_data),
??????? ????.input_green_data(input_green_data),
????????????.input_blue_data(input_green_data),
??????
????????????.output_gray_data(output_gray_data)
????????);
?????
????endmodule
vivado仿真結(jié)果如下圖:
仿真總圖
仿真開始階段圖
仿真中間部分截取圖
????????將在python轉(zhuǎn)換得到的三個txt文件,放在工程文件的xsim文件夾里,仿真的結(jié)果都輸出在了xsim文件夾里的gray.txt。
blue.txt
red.txt
green.txt
gray.txt
????????可以看到red/green/blue.txt數(shù)據(jù)數(shù)量均為262136個,輸出到gray.txt文件中,數(shù)據(jù)量也為262136個十六進(jìn)制數(shù),所有數(shù)據(jù)都完成了運(yùn)算,表明仿真成功。
2.3在OpenCV中將輸出的txt文件轉(zhuǎn)為bmp圖像進(jìn)行輸出。
import cv2
import numpy as np
'''
main entry
'''
def main():
????picture = cv2.imread('./lzy.bmp')
????for i in range(512):
????????for j in range(512):
????????????picture[i, j] = 255
????f = open("./gray.txt", 'r')
????for i in range(512 * 512):
????????line = f.readline()
????????picture[int(i / 512), int(i % 512)] = int(line, 16)
????f.close()
????cv2.imwrite('./new_lzy.bmp', picture)
????cv2.waitKey(0)
????cv2.destroyAllWindows()
if __name__ == '__main__':
????main()
????????至此,可以看到在vivado仿真中,與FPGA圖像反轉(zhuǎn)處理進(jìn)行對比,在處理的數(shù)據(jù)量增加的情況下,處理時間并沒有改變,在圖像處理中,我們可以廣泛應(yīng)用FPGA的并行特性,實(shí)現(xiàn)硬件加速。在仿真中,以20ns一個周期的虛擬時鐘進(jìn)行仿真,處理速度就可以達(dá)到5.26ms,如果在FPGA實(shí)機(jī)中,以更快的時鐘速度運(yùn)行,并且不需要運(yùn)行仿真文件,直接讀取通過存儲器傳來的數(shù)據(jù),速度將可以獲得大更大的提高。
? ? ? ? 需要工程源碼的友友可以在下方評論。文章來源:http://www.zghlxwxcb.cn/news/detail-763538.html
????????文章來源地址http://www.zghlxwxcb.cn/news/detail-763538.html
到了這里,關(guān)于基于FPGA的圖像灰度處理的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!