FPGA处理图像,可以先用modelsim仿真一下,就是原始图片转换成txt文档,把文档数据作为输入,通过自己写的处理模块后得到输出的txt文档数据,再使用matlab把文档转换成图片,查看写的模块是否正确。
第一步就是写一个数据产生模块,为了和视频数据流格式统一,在行同步和场同步期间写数据。这里借鉴这位博主的数据产生模块:Jane Laki Zder,把数据读到寄存器image中
`timescale 1ns/1ps
`define VIDEO_1920_1080
module sim_image(
input wire pclk ,
output wire [02:00] vs_o ,
output wire [23:00] ds_o
);
//1920x1080 148.5Mhz
`ifdef VIDEO_1920_1080
parameter H_ACTIVE = 1920; // 行数据有效时间
parameter H_FRONT_PORCH = 88; // 行消隐前肩时间
parameter H_SYNC_TIME = 44; // 行同步信号时间
parameter H_BACK_PORCH = 148; // 行消隐后肩时间
parameter V_ACTIVE = 1080; // 列数据有效时间
parameter V_FRONT_PORCH = 4; // 列消隐前肩时间
parameter V_SYNC_TIME = 5; // 列同步信号时间
parameter V_BACK_PORCH = 36; // 列消隐后肩时间
`endif
//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 V_ACTIVE = 720; // 列数据有效时间
parameter V_FRONT_PORCH = 5; // 列消隐前肩时间
parameter V_SYNC_TIME = 5; // 列同步信号时间
parameter V_BACK_PORCH = 20; // 列消隐后肩时间
`endif
parameter H_TOTAL_TIME = H_ACTIVE + H_FRONT_PORCH + H_SYNC_TIME + H_BACK_PORCH;
parameter V_TOTAL_TIME = H_ACTIVE + V_FRONT_PORCH + V_SYNC_TIME + V_BACK_PORCH;
reg o_hs;
reg o_vs;
reg o_de,o_deo;
reg [07:00] o_rr;
reg [07:00] o_gg;
reg [07:00] o_bb;
reg [12:00] h_syn_cnt = 'd0;
reg [12:00] v_syn_cnt = 'd0;
reg [23:00] image [0:H_ACTIVE*H_ACTIVE - 1];
reg [31:00] image_cnt = 'd0;
initial begin
$readmemh("E:/D_desktop/mmworkspcae/matlab_src/image_1080_1920_3.txt",image);
end
always @(posedge pclk) begin
if (h_syn_cnt == H_TOTAL_TIME - 1)
h_syn_cnt <= 0;
else
h_syn_cnt <= h_syn_cnt + 1;
end
always @(posedge pclk) begin
if (h_syn_cnt == H_TOTAL_TIME - 1) begin
if (v_syn_cnt == V_TOTAL_TIME - 1)
v_syn_cnt <= 0;
else
v_syn_cnt <= v_syn_cnt + 1;
end
end
always @(posedge pclk) begin
if (h_syn_cnt < H_SYNC_TIME)
o_hs <= 0;
else
o_hs <= 1;
end
always @(posedge pclk) begin
if (v_syn_cnt < V_SYNC_TIME)
o_vs <= 0;
else
o_vs <= 1;
end
always@(posedge pclk)begin
if(v_syn_cnt >= V_SYNC_TIME + V_BACK_PORCH && v_syn_cnt < V_SYNC_TIME + V_BACK_PORCH + V_ACTIVE)
begin
if(h_syn_cnt >= H_SYNC_TIME + H_BACK_PORCH && h_syn_cnt < H_SYNC_TIME + H_BACK_PORCH + H_ACTIVE)
o_de <= 1;
else
o_de <= 0;
end
else
o_de <= 0;
end
always @(posedge pclk) begin
if (o_de) begin
o_rr <= image[image_cnt][23:16];
o_gg <= image[image_cnt][15:08];
o_rr <= image[image_cnt][07:00];
image_cnt <= image_cnt + 1;
end
else if (image_cnt == H_ACTIVE*V_ACTIVE) begin
o_rr <= 8'h00;
o_gg <= 8'h00;
o_bb <= 8'h00;
image_cnt <= 'd0;
end
else begin
o_rr <= 8'h00;
o_gg <= 8'h00;
o_bb <= 8'h00;
image_cnt <= image_cnt;
end
end
always @(posedge pclk) o_deo <= o_de;
assign vs_o = {o_hs,o_vs,o_de};
assign ds_o = {o_rr,o_gg,o_bb};
endmodule
数据产生模块好了之后就是处理模块,这里简单用rgb转灰度试一下,代码就是我之前写过的。
写一个顶层文件,例化模块。然后在modelsim中新建工程,编写tb文件,步骤和上面提到的博主一样,仿真步骤就好了。
随后就是用matlab读取和产生txt文件了,这里我也是用这位博主的matlab程序,但是仿真后却无法读出txt文档,查看波形发现过一段时间后,产生的data都是XXXXX,查看源头image也是这样,直接打开文档看看只有一百万个数据,远小于应该的1920*1080个。原来是在matlab运行中直接打开“image_1080_1920_3.txt”这个文件会导致数据不会再写入文档,只要等一会数据写完即可。
clear;clear all;clc;
image_in = imread('origin_image.jpg');
FileName=['image_',num2str(size(image_in,1)),'_',num2str(size(image_in,2)),'_',num2str(size(image_in,3)),'.txt'];
[row,col,n] = size(image_in);
fid = fopen(FileName,'w');
for x = 1:row
for y = 1:col
image_R = dec2hex(image_in(x,y,1));
image_G = dec2hex(image_in(x,y,2));
image_B = dec2hex(image_in(x,y,3));
[rm,rn]=size(image_R);
[gm,gn]=size(image_G);
[bm,bn]=size(image_B);
if rn == 1
image_R =['0',image_R];
elseif rn == 0
image_R ='00';
end
if gn == 1
image_G =['0',image_G];
elseif gn == 0
image_G ='00';
end
if bn == 1
image_B =['0',image_B];
elseif bn == 0
image_B ='00';
end
image_hex=[image_R,image_G,image_B];
fprintf(fid,'%s\n',image_hex);
end
end
fclose(fid);
rgb转灰度后有三个分量ycbcr,用rgb显示灰度图像把三个通道都设置为Y即可显示灰度图像。