当前位置:网站首页>图像处理7:测试文件
图像处理7:测试文件
2022-07-23 07:20:00 【刘颜儿】
`timescale 1ns / 1ps
module Image_Processing_tb;
integer iBmpFileId; //输入BMP图片
integer oBmpFileId; //输出BMP图片
integer oTxtFileId; //输入TXT文本
integer iIndex = 0; //输出BMP数据索引
integer pixel_index = 0; //输出像素数据索引
integer iCode;
integer iBmpWidth; //输入BMP 宽度
integer iBmpHight; //输入BMP 高度
integer iBmpSize; //输入BMP 字节数
integer iDataStartIndex; //输入BMP 像素数据偏移量
reg [ 7:0] rBmpData [0:2000000]; //用于寄存输入BMP图片中的字节数据(包括54字节的文件头)
reg [ 7:0] Vip_BmpData [0:2000000]; //用于寄存视频图像处理之后 的BMP图片 数据
reg [7:0] rBmpWord; //输出BMP图片时用于寄存数据(以word为单位,即4byte)
reg [ 7:0] pixel_data; //输出视频流时的像素数据
reg clk;
reg rst_n;
reg [ 7:0] vip_pixel_data [0:230400]; //320x240x3
//产生50MHz时钟
initial clk = 0;
always #10 clk = ~clk;
//复位信号
initial begin
rst_n = 0;
#100;
rst_n = 1;
end
//--------------------------------------------------//
//------------读取外部的图片文件夹位置--------------//
//--------------------------------------------------//
initial begin
//分别打开 输入/输出BMP图片,以及输出的Txt文本
// 导入图片部分,需要更改
iBmpFileId = $fopen("E:\\vivado_fpga\\Image_sobel\\Image_sobel\\picture\\ly\\luosi.bmp","rb");
// 输出的图片
oBmpFileId = $fopen("E:\\vivado_fpga\\Image_sobel\\Image_sobel\\picture\\ly\\luosi_test.bmp","wb+");
oTxtFileId = $fopen("E:\\vivado_fpga\\Image_sobel\\Image_sobel\\picture\\ly\\luosi_3.txt","w+");
// =======2种方法=======
// 使用绝对路径:oBmpFileId = $fopen("E:\\vivado_fpga\\Image_sobel\\Image_sobel\\picture\\ly\\pic.bmp","wb+");
// 将图片加入工程:iBmpFileId = $fopen("che_BMP.bmp","rb");
//将输入BMP图片加载到数组中
iCode = $fread(rBmpData,iBmpFileId);
//根据BMP图片文件头的格式,分别计算出图片的 宽度 /高度 /像素数据偏移量 /图片字节数
iBmpWidth = {
rBmpData[21],rBmpData[20],rBmpData[19],rBmpData[18]};
iBmpHight = {
rBmpData[25],rBmpData[24],rBmpData[23],rBmpData[22]};
iBmpSize = {
rBmpData[ 5],rBmpData[ 4],rBmpData[ 3],rBmpData[ 2]};
iDataStartIndex = {
rBmpData[13],rBmpData[12],rBmpData[11],rBmpData[10]};
//关闭输入BMP图片
$fclose(iBmpFileId);
//将数组中的数据写到输出Txt文本中
$fwrite(oTxtFileId,"%p",rBmpData);
//关闭Txt文本
$fclose(oTxtFileId);
//延迟2ms,等待第一帧VIP处理结束
#2000000
//加载图像处理后,BMP图片的文件头和像素数据
for (iIndex = 0; iIndex < iBmpSize; iIndex = iIndex + 1) begin
if(iIndex < 54)
Vip_BmpData[iIndex] = rBmpData[iIndex];
else
Vip_BmpData[iIndex] = vip_pixel_data[iIndex-54];
end
//将数组中的数据写到输出BMP图片中
for (iIndex = 0; iIndex < iBmpSize; iIndex = iIndex + 1) begin
rBmpWord = Vip_BmpData[iIndex];
$fwrite(oBmpFileId,"%c",rBmpWord);
end
//关闭输出BMP图片
$fclose(oBmpFileId);
end
//=====================================================================================================
//--------------------------------------------------//
//-------------------图像处理外部IP-----------------//
//--------------------------------------------------//
//模拟的摄像头输出数据和时钟
wire cmos_vsync;
reg cmos_href;
wire cmos_clken;
reg [23:0] cmos_data;
// 2 图像处理部分,需要更改
wire per_frame_vsync = cmos_vsync;
wire per_frame_href = cmos_href;
wire per_frame_clken = cmos_clken;
wire [7:0] per_img_red = cmos_data[23:16];
wire [7:0] per_img_green = cmos_data[15: 8];
wire [7:0] per_img_blue = cmos_data[ 7: 0];
wire post_frame_vsync;
wire post_frame_href;
wire post_frame_clken;
wire [7:0] post_img_Y;
wire [7:0] post_img_Cb;
wire [7:0] post_img_Cr;
// 图像处理算法顶层模块
Image_Processing Image_Processing_inst(
.clk (clk),
.rst_n (rst_n),
.per_frame_vsync (per_frame_vsync),
.per_frame_href (per_frame_href),
.per_frame_clken (per_frame_clken),
.per_img_red (per_img_red),
.per_img_green (per_img_green),
.per_img_blue (per_img_blue),
.post_frame_vsync (post_frame_vsync),
.post_frame_href (post_frame_href),
.post_frame_clken (post_frame_clken),
.post_img_Y (post_img_Y),
.post_img_Cb (post_img_Cb),
.post_img_Cr (post_img_Cr)
/* .post_img_Bit (post_img_Bit) */
);
//--------------------------------------------------//
//--------------------图像输出部分------------------//
//--------------------------------------------------//
wire vip_out_frame_vsync;
wire vip_out_frame_href ;
wire vip_out_frame_clken;
wire [7:0] vip_out_img_R;
wire [7:0] vip_out_img_G;
wire [7:0] vip_out_img_B;
// 3 输出图像数据,需要更改的地方
assign vip_out_frame_vsync = post_frame_vsync;
assign vip_out_frame_href = post_frame_href ;
assign vip_out_frame_clken = post_frame_clken;
/* assign vip_out_img_R = {8{post_img_Bit}}; assign vip_out_img_G = {8{post_img_Bit}}; assign vip_out_img_B = {8{post_img_Bit}}; */
/* assign vip_out_img_R = post_img_Y; assign vip_out_img_G = post_img_Y; assign vip_out_img_B = post_img_Y; */
assign vip_out_img_R = post_img_Y;
assign vip_out_img_G = post_img_Cb;
assign vip_out_img_B = post_img_Cr;
//=====================================================================================================
//--------------------------------------------------//
//----------------产生摄像头的输出时序--------------//
//--------------------------------------------------//
reg [31:0] cmos_index;
parameter [10:0] IMG_HDISP = 11'd320;
parameter [10:0] IMG_VDISP = 11'd240;
localparam H_SYNC = 11'd5;
localparam H_BACK = 11'd5;
localparam H_DISP = IMG_HDISP;
localparam H_FRONT = 11'd5;
localparam H_TOTAL = H_SYNC + H_BACK + H_DISP + H_FRONT;
localparam V_SYNC = 11'd1;
localparam V_BACK = 11'd0;
localparam V_DISP = IMG_VDISP;
localparam V_FRONT = 11'd1;
localparam V_TOTAL = V_SYNC + V_BACK + V_DISP + V_FRONT;
//水平计数器
reg [10:0] hcnt;
[email protected](posedge clk or negedge rst_n) begin
if(!rst_n)
hcnt <= 11'd0;
else
hcnt <= (hcnt < H_TOTAL - 1'b1) ? hcnt + 1'b1 : 11'd0;
end
//竖直计数器
reg [10:0] vcnt;
[email protected](posedge clk or negedge rst_n) begin
if(!rst_n)
vcnt <= 11'd0;
else begin
if(hcnt == H_TOTAL - 1'b1)
vcnt <= (vcnt < V_TOTAL - 1'b1) ? vcnt + 1'b1 : 11'd0;
else
vcnt <= vcnt;
end
end
//场同步
reg cmos_vsync_r;
[email protected](posedge clk or negedge rst_n) begin
if(!rst_n)
cmos_vsync_r <= 1'b0; //H: Vaild, L: inVaild
else begin
if(vcnt <= V_SYNC - 1'b1)
cmos_vsync_r <= 1'b0; //H: Vaild, L: inVaild
else
cmos_vsync_r <= 1'b1; //H: Vaild, L: inVaild
end
end
assign cmos_vsync = cmos_vsync_r;
//Image data href vaild signal
wire frame_valid_ahead = ( vcnt >= V_SYNC + V_BACK && vcnt < V_SYNC + V_BACK + V_DISP
&& hcnt >= H_SYNC + H_BACK && hcnt < H_SYNC + H_BACK + H_DISP )
? 1'b1 : 1'b0;
reg cmos_href_r;
[email protected](posedge clk or negedge rst_n) begin
if(!rst_n)
cmos_href_r <= 0;
else begin
if(frame_valid_ahead)
cmos_href_r <= 1;
else
cmos_href_r <= 0;
end
end
[email protected](posedge clk or negedge rst_n) begin
if(!rst_n)
cmos_href <= 0;
else
cmos_href <= cmos_href_r;
end
assign cmos_clken = cmos_href;
//从数组中以视频格式输出像素数据
wire [10:0] x_pos;
wire [10:0] y_pos;
assign x_pos = frame_valid_ahead ? (hcnt - (H_SYNC + H_BACK )) : 0;
assign y_pos = frame_valid_ahead ? (vcnt - (V_SYNC + V_BACK )) : 0;
[email protected](posedge clk or negedge rst_n)begin
if(!rst_n) begin
cmos_index <= 0;
cmos_data <= 24'd0;
end
else begin
cmos_index <= y_pos * 960 + x_pos*3 + 54; // 3*(y*320 + x) + 54
cmos_data <= {
rBmpData[cmos_index], rBmpData[cmos_index+1] , rBmpData[cmos_index+2]};
end
end
//在时钟驱动下,从数组中读出像素数据
[email protected](posedge clk or negedge rst_n)begin
if(!rst_n) begin
pixel_data <= 8'd0;
pixel_index <= 0;
end
else begin
pixel_data <= rBmpData[pixel_index];
pixel_index <= pixel_index+1;
end
end
//-------------------------------------------//
//----------图像处理之后的像素数据-----------//
//-------------------------------------------//
reg [31:0] vip_cnt;
reg vip_vsync_r; //寄存VIP输出的场同步
reg vip_out_en; //寄存VIP处理图像的使能信号,仅维持一帧的时间
[email protected](posedge clk or negedge rst_n)begin
if(!rst_n)
vip_vsync_r <= 1'b0;
else
vip_vsync_r <= per_frame_vsync;
end
[email protected](posedge clk or negedge rst_n)begin
if(!rst_n)
vip_out_en <= 1'b1;
else if(vip_vsync_r & (!per_frame_vsync)) //第一帧结束之后,使能拉低
vip_out_en <= 1'b0;
end
[email protected](posedge clk or negedge rst_n)begin
if(!rst_n) begin
vip_cnt <= 32'd0;
end
else if(vip_out_en) begin
if(vip_out_frame_href & vip_out_frame_clken) begin
vip_cnt <= vip_cnt + 3;
vip_pixel_data[vip_cnt+0] <= vip_out_img_R;
vip_pixel_data[vip_cnt+1] <= vip_out_img_G;
vip_pixel_data[vip_cnt+2] <= vip_out_img_B;
end
end
end
endmodule
边栏推荐
- KingbaseESV8R6不同隔离级下xmin的区别
- GLIB-CRITICAL g_file_test:assertion ‘filename != null‘ failed
- ROS2自学笔记:URDF机器人建模
- 数据库系统原理与应用教程(041)—— MySQL 查询(三):设置查询条件
- -20: +usecgroupmemorylimitforheap failed to create virtual machine problem
- 了解canvas
- LeetCode_ 491_ Longest increasing subsequence
- Hardware system architecture of 4D millimeter wave radar
- Remove title block
- Kotlin - 挂起函数 suspend
猜你喜欢

专题讲座5 组合数学 学习心得(长期更新)

GLIB-CRITICAL g_file_test:assertion ‘filename != null‘ failed

2022暑假软件创新实验室集训 项目实战1

CenterNet目标检测模型及CenterFusion融合目标检测模型

Qt Creator .pro文件根据kit添加对应库

养老机构智能视频监控解决方案,用新技术助力养老院智慧监管

SeekTiger的Okaleido有大动作,生态通证STI会借此爆发?

内存取证之NSSCTF-OtterCTF 2018(复现赛)

Chapter II relational database after class exercises

Color recognition of regions of interest in pictures and videos based on OpenCV
随机推荐
数据库系统原理与应用教程(048)—— MySQL 查询(十):自连接查询
ModuleNotFoundError: No module named ‘setuptools_rust‘
数据库系统原理与应用教程(038)—— MySQL 的索引(四):使用 EXPLAIN 命令分析索引
SeekTiger的Okaleido有大动作,生态通证STI会借此爆发?
KingbaseESV8R6不同隔离级下xmin的区别
ES6 - weekly examination questions
七月到底有多热?通过爬虫爬取当月温度信息,并使用matplotlib绘制温度折线图
关于#redis#的问题:Redis设置数据持久化之后还是会有丢失数据的风险
图像处理:生成3×3的窗口
2022-07-22 review linked list operation and some problems
[Muduo] epollplayer event distributor
【Ardunio】2种方法控制舵机
Chapter II relational database after class exercises
Backtracking method to solve the eight queens problem
ROS中引用和输出消息类型
Événements courants de la souris et du clavier
Unity about local loading pictures involves webrequest or byte
Qt Creator .pro文件根据kit添加对应库
Probability meditation: 2. The quantitative rules
China leads the United States in another emerging technology field and stands at the commanding height of scientific and technological innovation