当前位置: 首页 > wzjs >正文

杭州网站建设招标网站模板论坛

杭州网站建设招标,网站模板论坛,中山金舜家庭用品有限公司怎样网站地图,用织梦的网站怎么做推广我最近在从事一项很有意思的项目,我想在PFGA上部署CNN并实现手写图片的识别。而本篇文章,是我迈出的第一步。具体代码已发布在github上 模块介绍 卷积神经网络(CNN)可以分为卷积层、池化层、激活层、全链接层结构,本篇要实现的&…

我最近在从事一项很有意思的项目,我想在PFGA上部署CNN并实现手写图片的识别。而本篇文章,是我迈出的第一步。具体代码已发布在github上

模块介绍

卷积神经网络(CNN)可以分为卷积层、池化层、激活层、全链接层结构,本篇要实现的,就是CNN的卷积层中的window窗。

在卷积过程中,最复杂的就是卷积运算,也就是Filter和图片(输入)相乘然后在相加的这一步骤。

img

我此处的构想就是将其卷积这个步骤进行拆分:加窗、载入权重、卷积运算。因而对应3个模块,而此处实现的就是加窗这个模块。而他主要负责的功能就是:提取输入图片中的数据,生成对应的窗口。 如上图所示,对x[:,:,0]图片进行窗口提起,提取的第一个窗口(左上角第一个)就是

[ 0 0 0 0 0 1 0 0 1 ] \begin{bmatrix}0&0&0\\0&0&1\\0&0&1\end{bmatrix} 000000011

代码

  1. 可配置参数、输入和输出定义

STRIDE为窗口滑动的步长,KERNEL_SIZE对应输入卷积核的大小,PADDING 为补充的长度

pixel_in 为输出的图片数据,frame_start 为图片开始输入的标志,pixel_valid为输入有效标志

window_out是图片展成一维的窗口数据

module window #(parameter DATA_WIDTH = 16,             // Width of each pixel dataparameter IMG_WIDTH = 32,             // Width of input imageparameter IMG_HEIGHT = 32,            // Height of input imageparameter KERNEL_SIZE = 3,            // Size of convolution window (square)parameter STRIDE = 1,                 // Stride of convolutionparameter PADDING = (KERNEL_SIZE - 1) / 2  // Padding size calculated for SAME mode
)
(input wire clk,                       // Clock signalinput wire rst_n,                     // Active low resetinput wire [DATA_WIDTH-1:0] pixel_in, // Input pixel datainput wire pixel_valid,               // Input pixel valid signalinput wire frame_start,               // Start of new frame signaloutput reg [KERNEL_SIZE*KERNEL_SIZE*DATA_WIDTH-1:0] window_out, // Flattened window outputoutput reg window_valid              // Window data valid
);
  1. 内部信号定义
  • 输入的图片数据是一个一个输入的,用x_pos和y_pos 来记录当前pixel位于图片中的位置

  • 窗口在图片上滑动,用x_window,y_window用来判断窗口目前的位置

  • line_Buffer缓存输入的数据,同时进行padding操作, 形成数据窗口,而window_buffer 在line_buffer上进行滑动,形成窗口

  • 状态机,分为三个状态 IDLE, LOAD,PROCESS, 分别对应空闲,载入(开始载入数据),处理(形成window)

// Internal signals
reg [5:0] x_pos, y_pos;                  // Current input pixel position
reg [5:0] x_window, y_window;            // Window center position
reg [DATA_WIDTH-1:0] line_buffer [0:KERNEL_SIZE][0:IMG_WIDTH+2*PADDING-1]; // Line buffer
reg [DATA_WIDTH-1:0] window_buffer [0:KERNEL_SIZE-1][0:KERNEL_SIZE-1]; // Window buffer
reg signed [6:0] src_y, src_x;           // Temporary variables for coordinate calculation// State machine
reg [1:0] current_state, next_state;
localparam IDLE = 2'b00, LOAD = 2'b01, PROCESS = 2'b10;// Loop variables
integer i, j, k;
  1. 状态的赋值以及跳转
  • 当接收到frame_start信号(图片开始输入),状态从空闲进入到LOAD状态;

  • 当目前的图片数据可以已经足够,可以用来生成稳定的输出窗口时,进入到PROCESS状态

  • 当目前滑窗口提取完对应数据窗口后,回到IDLE状态

注:y_pos从0到KERNEL_SIZE-1时,已经有了KERNEL_SIZE行数据了,可以进入窗口数据提取阶段;实际上可以更早进入,因为存在Padding。当y_pos=KERNEL_SIZE-Padding-1的时候,就可以进入了

// FSM state transitions
always @(posedge clk or negedge rst_n) beginif (!rst_n) current_state <= IDLE;else current_state <= next_state;
endalways @(*) begincase (current_state)IDLE:    next_state = frame_start ? LOAD : IDLE;LOAD:    next_state = (y_pos >= KERNEL_SIZE-1) ? PROCESS : LOAD;PROCESS: next_state = (y_window >= IMG_HEIGHT && x_window == 0) ? IDLE : PROCESS;default: next_state = IDLE;endcase
end
  1. 状态执行

推荐使用拆分的方法,把一个状态执行的大always块,分成很多子always块。

a. 输入图片数据位置捕获

  • 当前状态为IDLE,图片即将开始输入时,将定位信号复原

  • 当前状态不为IDLE, 同时输入有效,那么坐标根据情况自增

// Input pixel position tracking
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginx_pos <= 0;y_pos <= 0;end else if (current_state == IDLE && frame_start) beginx_pos <= 0;y_pos <= 0;end else if (pixel_valid && current_state != IDLE) beginif (x_pos == IMG_WIDTH-1) beginx_pos <= 0;y_pos <= y_pos + 1;end else beginx_pos <= x_pos + 1;endend
end

b. Line_Buffer 的缓冲

  • 每次开启新的一行的数据,对Line_Buffer 全部复位
  • 然后对对应的位置进行实际数据的填充
// Line buffer management
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginfor (i = 0; i <= KERNEL_SIZE; i = i + 1)for (j = 0; j < IMG_WIDTH + 2*PADDING; j = j + 1)line_buffer[i][j] <= 0;end else if (pixel_valid && current_state != IDLE) beginif (x_pos == 0) begin// Clear the line buffer row at the start of each new linefor (k = 0; k < IMG_WIDTH + 2*PADDING; k = k + 1)line_buffer[y_pos % (KERNEL_SIZE + 1)][k] <= 0;endline_buffer[y_pos % (KERNEL_SIZE + 1)][x_pos + PADDING] <= pixel_in;end
end

c .Window position tracking

  • 复位、一帧图片的开始或即将进入PROCESS状态,对window记位进行复位
  • 当前状态位PROCESS状态,同时没有超过当前图片的高度时,对window的位置进行对应的变化
// Window position tracking
always @(posedge clk or negedge rst_n) beginif (!rst_n || frame_start || (current_state == LOAD && next_state == PROCESS)) beginx_window <= 0;y_window <= 0;end else if (current_state == PROCESS && y_window < IMG_HEIGHT) beginif (x_window + STRIDE >= IMG_WIDTH) beginx_window <= 0;y_window <= y_window + STRIDE;end else beginx_window <= x_window + STRIDE;endend
end

d. window_buffer的处理

// Window generation and output
always @(posedge clk or negedge rst_n) beginif (!rst_n) beginwindow_valid <= 0;for (i = 0; i < KERNEL_SIZE; i = i + 1)for (j = 0; j < KERNEL_SIZE; j = j + 1)window_buffer[i][j] <= 0;end else beginwindow_valid <= 0; // Defaultif (current_state == PROCESS && x_window < IMG_WIDTH && y_window < IMG_HEIGHT && y_window + (KERNEL_SIZE>>1) <= y_pos) begin// Generate windowfor (i = 0; i < KERNEL_SIZE; i = i + 1) beginfor (j = 0; j < KERNEL_SIZE; j = j + 1) beginsrc_y = y_window + i - (KERNEL_SIZE>>1);src_x = x_window + j - (KERNEL_SIZE>>1);if (src_y >= 0 && src_y < IMG_HEIGHT && src_x >= 0 && src_x < IMG_WIDTH) beginwindow_buffer[i][j] <= line_buffer[src_y % (KERNEL_SIZE + 1)][src_x + PADDING];end else beginwindow_buffer[i][j] <= 0; // Paddingendendendwindow_valid <= 1;end end
end

当window坐标没有超过图片大小,确保可以生成窗口时,获取生成。对KERNEL_SIZE>>1,等价于KERNEL_SIZE/2,表示中心位置的偏移量

e.g.

[0,0] [0,1] [0,2]    [-1,-1] [-1, 0] [-1,+1]
[1,0] [1,1] [1,2] -> [ 0,-1] [ 0, 0] [ 0,+1]  <- (1,1)是中心
[2,0] [2,1] [2,2]    [+1,-1] [+1, 0] [+1,+1]

这样就可以将卷积索引转换为相对于中心的坐标,这样可以用于判断是否越界,从而进行padding补充

以KERNEL_SIZE=3为例

卷积核位置src坐标计算结果取值
0,0scr_y=0+0-1=-1越界padding
0,1src_y=0+0-1=-1越界padding
0,2src_y=0+0-1=-1越界padding
1,0src_x=0+0-1=-1越界padding
1,1src_y=0,src_x=0有效原图[0,0]
1,2src_y=0,src_x=1有效原图[0,1]
2,0src_x=0+0-1=-1越界padding
2,1src_y=1,src_x=0有效原图[1,0]
2,2scr_y=1,src_x=1有效原图[1,1]

e. 数据窗口的展平

将原本二维的的数据(宽为KERNEL_SIZE, 高为KERNEL_SIZE, 位宽为DATA_WIDTH)的数据,按照从罪小位排在最高位的顺序,压缩成一维的数据

// Flatten window buffer for output
always @(*) beginfor (i = 0; i < KERNEL_SIZE; i = i + 1) beginfor (j = 0; j < KERNEL_SIZE; j = j + 1) beginwindow_out[(KERNEL_SIZE*KERNEL_SIZE-(i*KERNEL_SIZE+j))*DATA_WIDTH-1 -: DATA_WIDTH] = window_buffer[i][j];endend
endendmodule

测试

`timescale 1ns / 1psmodule window_tb();// 测试用参数 - 使用小尺寸便于观察parameter DATA_WIDTH = 8;parameter IMG_WIDTH = 32;parameter IMG_HEIGHT = 32;parameter KERNEL_SIZE = 3;parameter STRIDE = 1;parameter PADDING = (KERNEL_SIZE - 1) / 2;// 测试信号reg clk;reg rst_n;reg [DATA_WIDTH-1:0] pixel_in;reg pixel_valid;reg frame_start;wire [KERNEL_SIZE*KERNEL_SIZE*DATA_WIDTH-1:0] window_out;wire window_valid;// 实例化被测模块window #(.DATA_WIDTH(DATA_WIDTH),.IMG_WIDTH(IMG_WIDTH),.IMG_HEIGHT(IMG_HEIGHT),.KERNEL_SIZE(KERNEL_SIZE),.STRIDE(STRIDE),.PADDING(PADDING)) dut (.clk(clk),.rst_n(rst_n),.pixel_in(pixel_in),.pixel_valid(pixel_valid),.frame_start(frame_start),.window_out(window_out),.window_valid(window_valid));// 时钟生成initial beginclk = 0;forever #5 clk = ~clk;end// 测试数据 - 5x5图像reg [DATA_WIDTH-1:0] test_image [0:IMG_HEIGHT-1][0:IMG_WIDTH-1];// 窗口计数器integer window_count = 0;// 初始化测试图像task reset_test_image;integer i, j;beginfor(i = 0; i < IMG_HEIGHT; i = i + 1) beginfor(j = 0; j < IMG_WIDTH; j = j + 1) begintest_image[i][j] =0;endendendendtasktask init_test_image;integer i, j;beginfor(i = 0; i < IMG_HEIGHT; i = i + 1) beginfor(j = 0; j < IMG_WIDTH; j = j + 1) begintest_image[i][j] = i * IMG_WIDTH + j + 1;endendendendtask// 显示测试图像task display_test_image;integer i, j;begin$display("\n=== 4x4 Test Image ===");for(i = 0; i < IMG_HEIGHT; i = i + 1) begin$write("Row %0d: ", i);for(j = 0; j < IMG_WIDTH; j = j + 1) begin$write("%3d ", test_image[i][j]);end$display("");end$display("======================\n");endendtask// 发送一帧图像数据task send_frame;integer i, j;begin$display("Sending 4x4 frame...");init_test_image();display_test_image();// 发送frame_start信号@(posedge clk);frame_start = 1;@(posedge clk);frame_start = 0;// 逐像素发送数据for(i = 0; i < IMG_HEIGHT; i = i + 1) beginfor(j = 0; j < IMG_WIDTH; j = j + 1) begin@(posedge clk);pixel_in = test_image[i][j];pixel_valid = 1;$display("Sending pixel[%0d][%0d] = %0d at time %0t", i, j, pixel_in, $time);endend@(posedge clk);pixel_valid = 0;$display("All pixels sent at time %0t", $time);endendtask// 主测试序列initial begin$display("========================================");$display("Window Test - Focus on Last Window");$display("IMG_SIZE: %0dx%0d, KERNEL: %0dx%0d", IMG_WIDTH, IMG_HEIGHT, KERNEL_SIZE, KERNEL_SIZE);$display("Expected windows: %0d", IMG_WIDTH * IMG_HEIGHT);$display("========================================");// 初始化信号rst_n = 0;pixel_in = 0;pixel_valid = 0;frame_start = 0;reset_test_image();// 复位序列repeat(5) @(posedge clk);rst_n = 1;repeat(3) @(posedge clk);// 发送测试帧send_frame();// 等待所有窗口输出repeat(50) @(posedge clk);$display("\n========================================");$display("Test Summary:");$display("Total Windows Generated: %0d", window_count);$display("Expected Windows: %0d", IMG_WIDTH * IMG_HEIGHT);if(window_count == IMG_WIDTH * IMG_HEIGHT) begin$display("SUCCESS: All windows generated!");end else begin$display("FAILURE: Missing windows!");end$display("========================================");$finish;end// 窗口监控always @(posedge clk) beginif(window_valid) beginwindow_count = window_count + 1;$display("Window %0d: pos(%0d,%0d) at time %0t", window_count, dut.x_window, dut.y_window, $time);// 显示窗口内容$write("Window content: ");$write("[%0d %0d %0d] ", window_out[71:64], window_out[63:56], window_out[55:48]);$write("[%0d %0d %0d] ", window_out[47:40], window_out[39:32], window_out[31:24]);$write("[%0d %0d %0d]", window_out[23:16], window_out[15:8], window_out[7:0]);$display("");endend// 状态机监控reg [1:0] prev_state = 2'b00;always @(posedge clk) beginif(dut.current_state != prev_state) begincase(dut.current_state)2'b00: $display("Time %0t: State -> IDLE", $time);2'b01: $display("Time %0t: State -> LOAD", $time);2'b10: $display("Time %0t: State -> PROCESS", $time);default: $display("Time %0t: State -> UNKNOWN(%0d)", $time, dut.current_state);endcaseprev_state = dut.current_state;endend// 波形转储initial begin$dumpfile("window_tb.vcd");$dumpvars(0, window_tb);// 限制仿真时间#2000;$display("ERROR: Simulation timeout!");$finish;endendmodule 

结果

输入数据

在这里插入图片描述

Row 0: 1 2 3 4 5
Row 1: 6 7 8 9 10
Row 2: 11 12 13 14 15
Row 3: 16 17 18 19 20

Line_Buffer 缓冲数据
在这里插入图片描述

Window_Buffer输出数据

在这里插入图片描述

valid为高,window_buffer开始提取line_buffer数据,同时输出展平的window_out;

在这里插入图片描述

window_buffer提取完毕,valid拉低


文章转载自:

http://hbM7E6Sz.ckfqt.cn
http://IJXikpku.ckfqt.cn
http://0xsguwnx.ckfqt.cn
http://dKpHnoF1.ckfqt.cn
http://CrgdQUfV.ckfqt.cn
http://YiLGmopM.ckfqt.cn
http://lNLdrkGJ.ckfqt.cn
http://2JMccc5Y.ckfqt.cn
http://xrzqKGky.ckfqt.cn
http://3KaKzUnI.ckfqt.cn
http://TIQJzRUv.ckfqt.cn
http://8qgewznc.ckfqt.cn
http://i894VLPl.ckfqt.cn
http://cBYIL9qd.ckfqt.cn
http://ZP2CoaEw.ckfqt.cn
http://ju4my0ji.ckfqt.cn
http://hQCEVFAB.ckfqt.cn
http://pQjIDehi.ckfqt.cn
http://Kwj7JEee.ckfqt.cn
http://QI2yhkxC.ckfqt.cn
http://4WGi9SIk.ckfqt.cn
http://GA22n3xj.ckfqt.cn
http://1MRxLou7.ckfqt.cn
http://D94V9JyB.ckfqt.cn
http://6gUmCmMc.ckfqt.cn
http://Tzmqjx2r.ckfqt.cn
http://XtgpSkWb.ckfqt.cn
http://JNIPzNtI.ckfqt.cn
http://AU7HysEt.ckfqt.cn
http://GAf0JosK.ckfqt.cn
http://www.dtcms.com/wzjs/629820.html

相关文章:

  • 网站建设结构设计方案网站备案修改域名ip
  • 商城系统网站模板做一元云购网站
  • 在线阅读网站建设方案邯郸百度网络服务中心
  • 企业官网建站如何设计网站风格
  • 石家庄市交建高速公路建设管理有限公司网站wordpress前台发视频图片
  • 网站访客分析江苏建设网站
  • 大气的企业网站模板WordPress设置两个域名
  • 长沙产品网站建设网上国网下载
  • 网站建设首选亿企联盟discuz 做网站可以吗
  • 西安cms模板建站dnf怎么做发卡网站
  • 手机网站设计与实现是什么wordpress 用户遍历
  • 中国建设银行官网站积分抽奖南昌seo网站
  • iis架设jsp网站四川建筑人才招聘网
  • wordpress怎么给网站设置几种语言网站站内搜索代码
  • 百度网盘0基础网站开发教程国内最新军事新闻
  • 建设网站和网页有啥区别建设电子商务网站的步骤
  • 怎么区分模板网站wordpress栏目页设置
  • 网络营销产品的首选产品快排seo软件
  • 嘉兴网站推广平台建设网站报价
  • 怎么想百度提交网站wordpress 修改语言包
  • wordpress move怎么用兰州seo新站优化招商
  • 招聘网站建设费用多少湖南省邵阳市建设局网站
  • 嘉兴网站建议福州做网站哪家好
  • 可以做网站的语言年轻人免费观看视频
  • 手机网站自助百度网盟 网站定向投放
  • wordpress 自定义分类宁波网站推广优化公司怎么样
  • 手机网站搜索优化如何搭建网络论坛平台
  • 网站宽带值多少合适房屋网签查询系统官方网站
  • 西安优秀的集团门户网站建设服务商购物网页模板
  • 集团网站设计专业团队网站开发及服务合同模板