图像尺寸:450*450
image.v,模拟左摄像头
image2.v,模拟右摄像头
仿真的方法:采用matlab和modelsim联合仿真的形式
1、用matba将图像转换成txt文档。
2、verilog读入txt文档,并得到图像数据,后将图像数据写入到txt文档中
3、采用matlab,将txt文档转换成图像进行校对。
这里可看到,我们采用的是灰度图的形式,8位灰度图噪声更小且阴影细节更多,还能减少数据量,运算更快。
%==========================================================================
% 彩色图片转为灰度图片,再转为txt文本数据,格式为8bit的hex数据
%==========================================================================
clear all;
clc;
%--------------------------------------------------------------------------
pre_img = imread('left.jpg'); %读取图片
[ROW,COL,N] = size(pre_img); %获得图片尺寸[高度,长度,维度]
gray = rgb2gray(pre_img); %图片转为gray灰度图
%--------------------------------------------------------------------------
fid=fopen('left.txt','w'); %打开文件
for i=1:ROW
for j=1:COL
fprintf(fid,'%x\n',gray(i,j));%将字符打印到txt文件
end
end
fclose(fid); %关闭文件
%--------------------------------------------------------------------------
imshow(gray),title('处理前'); %查看处理前的图片
imwrite(gray,'处理前灰度图.jpg');
至此,我们得到了待处理的左图像数据:left.txt,根据该数据,可模拟摄像头进行仿真
特别注意:生成txt文档后的存放位置。
//采集左图图像
module image(
input clk,
input camera_en,
output reg data_valid,
output reg [7:0] data_out
);
parameter N = 450, M = 450;
reg [7:0] mem[3*N*M:0];
integer ptr;
initial
begin
$readmemh("../txt/left.txt", mem);
ptr <= 0;
end
always @(posedge clk)begin
if (camera_en)begin
data_valid <= 1'b1;
data_out <= mem[ptr];
ptr <= ptr + 1;
end
else begin
data_valid <= 0;
ptr <= 0;
data_out <= 8'hzz;
end
if (ptr == ((N*M*3) - 1))begin
ptr <= 0;
end
end
endmodule
模拟摄像头上电配置后,数据有效的情况下进行采集的情况。由于450*450像素,因此仿真的时候至少运行2025000ns后才能停止,否则图像数据的写入不完全。
module image_tb();
reg clk;
reg camera_en;
wire data_valid;
wire [7:0] data_out;
image UUT(clk, camera_en, data_valid, data_out);
initial
begin
clk = 0;
$dumpfile("vcd/image.vcd");
$dumpvars(0, image_tb);
camera_en = 0;
#2;
camera_en = 1;
#2025000;
$finish;
end
always
begin
clk = ~clk;
#1;
end
//==========================================================================
//== 图像数据转变为txt文本
//==========================================================================
//打开post_img.txt文件
//---------------------------------------------------
integer post_img_txt;
initial begin
post_img_txt = $fopen("post_img.txt");
end
//像素写入到txt中
//---------------------------------------------------
reg [20:0] pixel_cnt; //450*450 = 202500 ,对这些像素逐个写入
always @(posedge clk) begin
if(!camera_en) begin
pixel_cnt <= 0;
end
else if(data_valid) begin
pixel_cnt = pixel_cnt + 1;
$fdisplay(post_img_txt,"%h",data_out);
if(pixel_cnt == 202500)
$stop;
end
end
endmodule
仿真后我们即可得到采集到的图像数据,并将其写入了txt文档中,——post_img_txt
将该txt文档放入matlab文件夹,即可将处理后得到的txt,变成图像的形式来显示,此时即可解决没有摄像头的问题。
由于我们只是进行图像数据采集,没有做其他处理,因此可将采集后的图像与采集前的图像进行比对。
fid0=fopen('post_img.txt','r'); %读入所需要的txt文件
[a,count]=fscanf(fid0,'%x'); %a为data.txt文件数据读入的矩阵,以16进制形式,count为该矩阵元素个数
b=reshape(a,450,450); % 构建成450*450的矩阵形式
c=b'; % 需要再转置一次方为图片行列方向的矩阵
imshow(c,[]); %显示图片
通过波形的停止的位置可看到,像素计数器为202500,因此共向txt文档中写入了202500个像素,也就是450*450图像大小。——像素个数的写入正确。
放大查看每个像素,与原图生成的txt文档中的像素对比,发现相同。——像素值的写入均正确。
至此,一幅图像的像素个数以及像素值均正确,说明我们完成了左图的采集,同样的方式可实现右图的采集。
修改的地方:
在image_tb的模块例化处进行修改,将右图的顶层文件例化进来。
image2 UUT(clk, camera_en, data_valid, data_out);
在顶层文件image2中,改变读入的图像数据即可,其余部分相同
initial
begin
$readmemh("../txt/right.txt", mem);
ptr <= 0;
end
最终我们将上述两个左右采集的verilog写成模块的形式,如下所示,就相当于两个摄像头来采集图像数据的RTL图:
注意:在生成RTL的时候,需要将代码中读入图像数据的initial语句注释掉,不然无法综合,当仿真的时候将注释取消。
得到双目采集的仿真图:
当左右图像有效信号为高电平时,分别进行采集,这里是同时采集,采集到的数据依次写入到左右的txt文档中。
我们仍然采用matlab对采集到的左右图txt数据进行图像展示,得到如下图像效果,与原图一样:
本文是图像拼接融合图像采集部分的学习记录。