【FPGA图像处理】——DDR仲裁、多输入源拼接、旋转任意角度、突发长度修改、任意地址读取。

news2024/9/22 17:19:24

前言:做FPGA大赛期间遇到的问题,自己coding过程。
包含:hdmi、摄像头等多输入源的拼接;了解DDR以及多种DMA传输方式,修改底层突发长度以及存储位宽;单输入源任意角度旋转(无需降低帧率)。

文章目录

  • 前言
    • 免责声明
  • 一、hdmi、摄像头等多输入源的拼接
  • 二、WDMA传输
  • 三、单输入源的任意旋转
    • 任意突发长度修改
    • 旋转部分
  • 其他事项记录
  • 总结


前言

写这篇文章的原因呢,是因为之前参加FPGA大赛的时候遇到很多问题找不到系统的解决办法,本文主要提供一个大概的关于图像的大概处理流程;当然根本原因是没晋级决赛了哇,但是不得不承认我在这个比赛的过程中学习到了非常多的东西,记录下来帮助更多希望入门FPGA和图像处理的朋友们。接下来的内容会以提出问题->分析问题->解决问题的形式展示。

免责声明

本人做FPGA很多年,但是系统的做FPGA图像处理这是第一次,本文仅记录一月以来的调试内容,如果内容有问题请通过邮箱联系我,评论偶尔会看。代码(紫光同创版)免费提供(仅仅提供我写的部分)


一、hdmi、摄像头等多输入源的拼接

问题:DDR在某个时刻只能进行读或者写操作的条件下如何进行数据处理?怎么才能最大程度的减缓帧丢失?

在使用xilinx系列FPGA的时候里面有一个很常用的IP:AXI-interconnect;AXI-interconnect是一个一主多从的模块,对多通道从机进行数据缓存通过自动仲裁,输出。他的优点简单,emm,只有简单。

最初,解决这个问题的时候进行了降帧的处理,即DDR的某片区域存够了摄像头或者hdmi输入的一帧数据进行暂停处理,当DDR的另一片区域也存够了hdmi或者摄像头输入的一帧再进行输出。
在这里插入图片描述
如图所示,每个区域会在存满一帧以后等待另一个输入也存满的时候进行输出,然后在此进行下一次存储。这样造成的结果会使得两个输入源的帧率成倍的降低。

那么我们在没有AXI-interconnect IP的条件下,如何进行仲裁呢?怎么才能减缓帧率的丢失呢?

为了解决这个问题,我使用的数据仲裁方法是——固定优先级算法进行仲裁。

   if(wfifo_rcount_1 >= wr_bust_len  )begin  
       state_cnt <= WRITE_ADDR_1;                    
   end         
   else if(wfifo_rcount_2 >= wr_bust_len  )begin 
       state_cnt <= WRITE_ADDR_2;                    
   end                
   else if(raddr_rst_h)begin                       
           state_cnt <= DDR3_DONE;                                                    
   end                                
   else if(rfifo_wcount_1 < rd_bust_len  )begin 
       state_cnt <= READ_ADDR_1;                                                 
   end                             
   else if(rfifo_wcount_2 < rd_bust_len  )begin  
       state_cnt <= READ_ADDR_2;                                                                                        
   end 

这个算法的缺点很明显,就是可能会造成总线主设备的“饥饿”或“撑”的现象,但是由于DDR速率远远超过fifo的存储速率在从机不多的条件下远远满足我所需要的要求。

有了仲裁算法,剩下的就是对AXI总线的coding了,有兴趣的人可以参考博客AXI-lite以及debug过程,这里要注意的是紫光同创今年这个版本的DDR的特点:使用的是Simplified AXI4 接口,配置较为简单。即:读写地址需要进行握手,数据则不需要。

在进行完数据仲裁之后,就可以各输入源进行写入和读出的操作了,经测试,帧率完美吻合,使用两帧缓存乒乓操作不会出现画面撕裂现象。

最后,记录一下DDR里面的数据计算方法,因为这个也曾困扰我一个晚上。
首先PGL50H中,DDR支持32bit,含有4Gbit(一片512MB,两片1024MB)内存。生成ip后的地址位宽为28bit;
当所有地址写满的时候我们计算一下内存是否吻合:

2^28*32/8=1,073,741,824Byte = 1024MB

最初版代码使用的是:
burst_len=16; input_data_width=16; AXI_data_width=256;DDR_data_width=32;
那么每次地址变化应该是:addr=addr+burst_len*AXI_data_width/DDR_data_width;
地址变化这里一定要仔细理解,不然后续旋转无法清楚

DDR中每个地址存放的数据位宽为32bit,每一次burst传输256个bit,也就意味着每一次burst的时候DDR对应的地址变化是8
在这里插入图片描述
如果进行16次burst,那自然就是burst_len*8;

二、WDMA传输

摘要:WDMA(Waste Direct Memory Access),即一种极其占用DDR内存和时间的传输方式,由于它极其消耗资源,因此我给它命名为WDMA。

在正式介绍WDMA之前,介绍一下目前我目前接触到的几种DMA传输方式:VDMA,CDMA,XDMA,FDMA;前三种DMA传输方式是xilinx厂家提供的ip,最后一个FDMA是米联客提供的ip。简单介绍一下前三种。

VDMA:简单来说就是为了缓存帧图像专门开发出来的一个DMA方式,可以满足改变帧速率,缓存帧的需求。
CDMA:用过MicroBlaze的应该都很了解,就是PL和PS之间的沟通渠道,ZYNQ则是用到DDR的时候会用到这个DMA传输方式。
XDMA:我使用XDMA都是用来进行PCIe数据沟通的,可见xilinx series 7 PCIE xdma测试记录

这里重点说一下FDMA(米联客开发,有详细的文档说明,目前已经更新到第六版,如有需求请通过邮箱联系我),是我在比赛最开始准备使用的一款ip,我这有详细的文档介绍,这里只说一下我前期准备过程中学到的一些东西。
在这里插入图片描述

首先是名字FDMA,为什么叫FDMA? 解答:FDMA(Fast Direct Memory Access)是一种快速DMA缓存方式。
FDMA的优点:如果使用过xilinx的DMA ip那么大家应该了解,配置起来稍显麻烦,不够灵活。而FDMA突出特点是简单直接。FDMA主要是定义了一个AXI4 FULL的ip,其余需要的DDR等外设只需要挂载在AXI4总线上就可以进行外设读取存储的操作了,跟着米联客的教程,一步一步做,不要光看一定要有自己debug的过程。
FDMA使用的三帧缓存架构数据框图如下:
在这里插入图片描述
使用xilinx的话我们就是为了简单,那么如果此时有多通道的输入,我们只需要调用axi-interconnect ip就行,如果通道数过多的话我建议使用自己写的仲裁方式,因为这个ip只能满足低时序,数据量不是那么大的情况下使用。
三帧缓存架构,这里定义的FBUF_SIZE就是来控制帧缓存的一个parameter。

//write
 if(W0_bcnt == BURST_TIMES) begin
     if(W0_Fbuf == FBUF_SIZE) 
        W0_Fbuf <= 7'd0;
     else 
        W0_Fbuf <= W0_Fbuf + 1'b1; 
     W_MS <= S_IDLE;
 end
//read
 if(R0_bcnt == BURST_TIMES ) begin
 	R_MS <= S_IDLE;
 	if(W0_Fbuf == 7'd0) 
 		R0_Fbuf <= FBUF_SIZE;
 	else 
 		R0_Fbuf <= W0_Fbuf - 1'b1; 
 end

//frame 地址切换
assign O_bufn = I_bufn < BUF_DELAY?  (BUF_LENTH - BUF_DELAY + I_bufn) : (I_bufn - BUF_DELAY) ;

三帧缓存,里面的操作就是对帧的缓存和读出有一个乒乓操作,当然我们的代码中没有修改使用的是两帧缓存方案的乒乓操作,这里介绍一下三帧缓存方案:
在这里插入图片描述
如图所示,我读出的帧和写入的帧两个地址永远不会重叠,我们做的地址切换就有这样的操作。

assign O_bufn = I_bufn < BUF_DELAY?  (BUF_LENTH - BUF_DELAY + I_bufn) : (I_bufn - BUF_DELAY) ;
// 3帧缓存 延迟2帧推导 BUF_DELAY     = 2 ,BUF_LENTH     = 3
//0<BUF_DELAY(2)     BUF_LENTH(3) - BUF_DELAY(2) + I_bufn(0)  = 1
//1<BUF_DELAY(2)     BUF_LENTH(3) - BUF_DELAY(2) + I_bufn(1)  = 2
//2=BUF_DELAY(2)     I_bufn(2)    - BUF_DELAY(2)   = 0

FDMA配置问题等等可以看文档说明,说的绝对比我明白的多。

那开始进入正题,WDMA的介绍。
为什么叫WDMA呢,上面已经有过介绍,这里用图片来简单介绍一下,由于输入的图像位宽是16,而一个DDR地址的位宽为32bit,如果我们想让每个地址对应一个点,显示还要做一个像素点的“挑选”。按照简单输入地址和输出地址做对应来说,输出地址从0-1的时候对应的DDR里面都是0,那这么定义的话addr_o>>1=addr_DDR。那我们的挑选规则就是

	addr_o[0] -> data[15:0];
	addr_o[1] -> data[31:16];

由于我们想做的是任意旋转,每次我只要一个点,而点的对应最好就是一个DDR地址存储的数据就是一个像素点,这样会大大简化算法复杂度,于时就有了WDMA的产生,这是它的第一层含义。
在这里插入图片描述那么它的第二层含义在哪呢?

使用的紫光同创的DDR最低一次burst最少传输256bit数据,如果对应旋转的话,我一次只要一个点,那就对应不上了,第二层含义就是修改读出地址,重复读出已经读过的数据,这是第二个含义。
在这里插入图片描述
为了到达想要的状态,不得不进行这样的资源消耗,这样带来的效果是非常好的,可以在任意旋转的状态下保持和平常一样的帧率。

三、单输入源的任意旋转

有了上述一、二的解释,最后一节就很好说了,我们只需要在满足所需要的缓存内存和地址映射就可以完成任意旋转了。

难点: 突发长度的修改,任意地址的读取,满足时序的要求等。
这里先看一下最开始的效果,一行显示1024个像素点的时候,16个像素点表示1个点的结果如下。
图1
这是最开始,不浪费任何资源时候的效果。
接下来演示使用WDMA的效果
在这里插入图片描述

任意突发长度修改

在代码中修改rd_butst_len=5‘d1,这时候我们进行一次burst会传递256个数据,此时出现的结果是上述模糊图像。那么还要修改的地方就是我的输入数据

  wr_fifo wr_fifo_init (
  .wr_clk        (wr_clk),                    // input
  .wr_rst        (!rst_n|wfifo_rst_h),                    // input
  .wr_en         (datain_valid),                      // input
  .wr_data       ({datain,16'd0}),                  // input [31:0]
  .wr_full       (),                  // output
  .wr_water_level(),    // output [12:0]
  .almost_full   (),          // output
  .rd_clk        (ddr_clk),                    // input
  .rd_rst        (!rst_n|wfifo_rst_h),                    // input
  .rd_en         (wfifo_rden),                      // input
  .rd_data       (wfifo_dout),                  // output [255:0]
  .rd_empty      (),                // output
  .rd_water_level(wfifo_rcount),    // output [9:0]
  .almost_empty  ()         // output
);

这里修改之后相当于我每个地址存放的是一个像素点,此时又要进行一个计算,就是一帧图像需要占据的DDR的大小是多少;

1280 * 720 * 32 / 32 = 921600,这是对应的我们DDR的最大地址,很明显资源浪费多了一倍
输入是16bit时 : 1280 * 720 * 16 / 32 = 460800

接下来是对读地址进行重复读操作的代码

      if(axi_arready && axi_arvalid) begin
          axi_arvalid <= 1'b0;
          axi_araddr_n_1 <= axi_araddr_n_1 + 5'd4;
      end

如果正常完成一次burst应该是地址加8(见一所述),因为每次读出的数据不希望是256bit所以对地址进行这样的操作。
如果仅仅修改完这次加载代码会发现,什么东西都没了,为什么呢?
在代码里面仲裁是通过固定优先级来实现的,读操作的许可证,是通过rd_fifo的数据位来进行控制的,当一次burst吐出256个数据而我只要128个数据的时候会造成DDR->fifo时序和数据位的错乱,因此,要做一个强制拉回的操作,在代码里是这样控制的。

		always@(posedge clk or negedge rst_n)
    		if(!rst_n)
        		rd_data_cnt <= 6'd0;
    		else if(rd_data_cnt== 6'd31 && (state_cnt == READ_DATA_1 ||state_cnt == READ_ADDR_1))
        		rd_data_cnt <= 0;
   	 		else if(axi_rvalid && (state_cnt == READ_DATA_1 ||state_cnt == READ_ADDR_1))
      	  		rd_data_cnt <= rd_data_cnt + 1;
    		else if(state_cnt == READ_DATA_1 ||state_cnt == READ_ADDR_1 )
        		rd_data_cnt <= rd_data_cnt ;
    		else 
        		rd_data_cnt <= 0 ;
//------------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------------
            READ_ADDR_1:begin
                if(rd_data_cnt==6'd31 )
                    state_cnt <= DDR3_DONE;
                else if(axi_arvalid && axi_arready)
                    state_cnt <= READ_DATA_1;
                else
                    state_cnt <= state_cnt;
            end
            READ_DATA_1:begin                   //
                if( rd_data_cnt < 6'd31)
                    state_cnt <= READ_ADDR_1;   //
                else if(rd_data_cnt==6'd31 )
                    state_cnt <= DDR3_DONE;
                else                          //
                    state_cnt   <= state_cnt; //
            end

这就是全部内容了,当完成强制拉回操作之后,就可以对任意地址,任意突发长度,任意数据的读取操作了。

写完文章一下午最多提问的是关于拉回操作为什么这么做,体现在哪里
不管是使用官方例程还是黑金的axi,最初的burst_len=16。
使用代码的时候一开始突发长度为16的时候所有东西都正常这是肯定的,那么当现在burst=1的时候会有问题,那该怎么改呢,才能正确呢?好,强制进行16次burst为1的操作 ,此时的地址跳变为8,结果你会发现,哎,正常了。
那么我们进行下一步,开始浪费资源,重复去读,此时地址跳变为4,那么该怎么做呢?很明显,强制进行16x2次burst为1的操作即可。这是对强制拉回操作的一个解释。

旋转部分

旋转模块采用的是逆向思维,用目标图像的坐标去与原图的坐标进行坐标匹配,若在原图像中能找到匹配的图像,就显示该点旋转后的点坐标,若在原图中找不到该点,则不显示该点。具体算法参考19年FPGA大赛大佬,下面是他的链接https://blog.csdn.net/weixin_42905573/article/details/105941991
在任意旋转模块中,首先要保证的是得到一帧完整存在的图像,对于显示器输出坐标做一个回环,经过旋转算法模块对应到DDR中的数据,取出显示,本模块数据流程框图如图。
在这里插入图片描述
本方案配置的摄像头分辨率为1280 * 720p,HDMI显示也是1280 * 720p,因此如果对应到坐标位置,每一行用x表示,x从0开始计数到1280,用y来表示此时已经计数到哪一行,对应到DDR一帧图像中选取的坐标点的addr信息为ddr_addr=x_r+1280*y_r。
使用之前介绍的WDMA方式,可以对DDR中的任意数据进行读出,且满足时序要求,使用二级缓存乒乓操作的方式可以保证画面不撕裂。

if(axi_arready && axi_arvalid)begin                                                                                  
    axi_arvalid <= 1'b0;                                                                                             
    axi_araddr_n_1 <= axi_araddr_n_1 + rd_bust_len*5'd4;                                                             
    axi_araddr_n_11 <= ( x_rotate >= 1280 || y_rotate > 720 ) ? 28'd0 :  x_rotate[12:0]	+ y_rotate[12:0] *12'd1280;  
    if(x_cnt> 12'd1280-12'd8)begin                                                                                   
        x_cnt <= 32'd0;                                                                                              
        y_cnt <= y_cnt + 1;                                                                                          
    end                                                                                                              
    else begin                                                                                                       
        x_cnt <= x_cnt + 5'd4;                                                                                       
        y_cnt <= y_cnt;                                                                                              
    end                                                                                                              
end           
//-------------------------------------------------------------------------------------------
coor_trans coor_trans_inst
(
    .clk		(	clk			),
    .rst_n		(	rst_n			),
    
    
    .angle		(	10'd180			),
    .x_in		(	x_cnt			),
    .y_in		(	y_cnt			),
   

	.x_out		(	x_rotate		),
    .y_out		(	y_rotate		)
);                                                                                                       

效果展示

A4EA9C00A50A042A13BD13535A3E5A90

以上是对这次FPGA大赛的一次总结,如果按照工程走可完成的任务是图像拼接,旋转,以太网收发(本文主要讲摄像头,不涉及以太网的东西),上述所用的所有算法代码等如有需求可以通过邮箱联系我:784927721@qq.com

其他事项记录

在这次比赛中,学到了很多东西,最后记录一点小东西,希望能在不经意之间帮到大家,做完之后我们的视频中在旋转的过程中一些该是黑色的地方有很多毛刺,分析原因,是在外层r_data的时候用了组合逻辑进行了输出,不影响输出,但是某些时序可能没有对上。
在这过比赛中收获最大的可能是在资源消耗过大的时候,使用大量组合逻辑会影响布局布线规则,而我使用组合还是时序的条件都是看是否当前输入要和时钟产生关系,没想到最后使用一点组合逻辑就会导致了很多时序问题。
篇幅有限,上述还有很多仿真工作以及debug过程没有展示。

本文全部原创,如果转载请联系作者,侵权必究。


总结

这次比赛,感谢全国大学生FPGA创新设计竞赛组委会所提供的宝贵的参赛机会,感谢FPGA紫光同创为我们提供的一切支持,感谢米联客ip作者在晚上十一点被我打扰还一点一点与我讲解ip的问题所提供的帮助。
因为淋过雨,所以想给别人撑伞。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1272950.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

tex2D使用学习

1. 背景&#xff1a; 项目中使用到了纹理进行插值的加速&#xff0c;因此记录一些自己在学习tex2D的一些过程 2. 代码&#xff1a; #include "cuda_runtime.h" #include "device_launch_parameters.h" #include <assert.h> #include <stdio.h>…

XTU OJ 1339 Interprime 学习笔记

链接 传送门 代码 #include<bits/stdc.h> using namespace std;const int N1e610; //78498 我计算了一下&#xff0c;6个0的范围内有这么多个素数&#xff0c;所以开这么大的数组存素数 //计算的代码是一个循环 int prime[80000]; int a[N],s[N];//s数组是前缀和数组b…

自定义链 SNAT / DNAT 实验举例

参考原理图 实验前的环境搭建 1. 准备三台虚拟机&#xff0c;定义为内网&#xff0c;外网以及网卡服务器 2. 给网卡服务器添加网卡 3. 将三台虚拟机的防火墙和安全终端全部关掉 systemctl stop firewalld && setenforce 0 4. 给内网虚拟机和外网虚拟机 yum安装 httpd…

Echarts的引入使用

ECharts文档 1.下载并引入Echarts 2.准备一个具备大小的DOM容器 3.初始化echarts实例对象 4.指定配置项和数据(option) 5.将配置项设置给echarts实例对象 最后是一个js文件 echarts的引入 1.引入echarts - js 文件 <script src"js/echarts.min.js"></scri…

「Linux」使用C语言制作简易Shell

&#x1f4bb;文章目录 &#x1f4c4;前言简易shell实现shell的概念系统环境变量shell的结构定义内建命令完整代码 &#x1f4d3;总结 &#x1f4c4;前言 对于很多学习后端的同学来讲&#xff0c;学习了C语言&#xff0c;发现除了能写出那个经典的“hello world”以外&#xff…

XUbuntu22.04之OBS30.0设置录制音频降噪(一百九十六)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

LabVIEWL实现鸟巢等大型结构健康监测

LabVIEWL实现鸟巢等大型结构健康监测 管理国家地震防备和减灾的政府机构中国地震局(CEA)选择了七座新建的巨型结构作为结构健康监测(SHM)技术的测试台。这些标志性建筑包括北京2008年夏季奥运会场馆&#xff08;包括北京国家体育场和北京国家游泳中心&#xff09;、上海104层的…

QML学习一、GridView的使用和增加添加动画、删除动画

一、效果预览 二、源码分享 import QtQuick import QtQuick.ControlsApplicationWindow {visible: truewidth: 640height: 480title: "Test"property int cnt:cnt model.countListModel{id:modelListElement{index:0}ListElement{index:1}ListElement{index:2}List…

csapp-linklab之第3阶段“输出学号”实验报告(强弱符号)

题目 新建一个phase3_patch.o&#xff0c;使其与main.o和phase3.o链接后&#xff0c;运行输出自己的学号&#xff1a; $ gcc -o linkbomb main.o phase3.o phase3_patch.o $ ./linkbomb $学号 提示 利用符号解析中的强弱符号规则。&#xff08;COOKIE字符串未初始化&#xff…

单片机AVR单片机病房控制系统设计+源程序

一、系统方案 设计一个可容8张床位的病房呼叫系统。要求每个床位都有一个按钮&#xff0c;当患者需要呼叫护士时&#xff0c;按下按钮&#xff0c;此时护士值班室内的呼叫系统板上显示该患者的床位号&#xff0c;并蜂鸣器报警。当护士按下“响应”键时&#xff0c;结束当前呼叫…

【无标题】读transformer

这里写目录标题 transformerabstractconclusionintroductionbackground注意力机制mlptransformer和RNN传递序列信息embedding之后维度越大的向量归一化后其单个值就越小&#xff0c;乘个根号512position encoding加入时序信息 transformer abstract 编码器和解码器的架构 处理…

强化学习中的Q学习

Q学习&#xff08;Q-Learning&#xff09;是强化学习中的一种基于值的学习方法&#xff0c;用于在有限马尔可夫决策过程&#xff08;MDP&#xff09;中学习最优的动作策略。Q学习主要用于离散状态和离散动作的问题。 以下是Q学习的基本概念和步骤&#xff1a; Q-Value&#xf…

程序员也需要养生——程序员睡不好,重视一下你的情绪吧

程序员也需要养生——程序员睡不好&#xff0c;重视一下你的情绪吧 睡眠是一个复杂的系统工程&#xff0c;可以促进生长发育&#xff0c;修复受损的组织。促进大脑细胞的修复等等。在情绪的失调会影响到我们的睡眠状况。 一、心情差&#xff0c;压力大&#xff0c;睡不好跟这…

XXL-Job详解(一):组件架构

目录 XXL-Job特性系统组成架构图调度模块剖析任务 “运行模式” 剖析执行器 XXL-Job XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。 特性 1、简单&#…

【驱动】串口驱动分析(二)-tty core

前言 tty这个名称源于电传打字节的简称&#xff0c;在linux表示各种终端&#xff0c;终端通常都跟硬件相对应。比如对应于输入设备键盘鼠标&#xff0c;输出设备显示器的控制终端和串口终端。也有对应于不存在设备的pty驱动。在如此众多的终端模型之中&#xff0c;linux是怎么…

信贷专员简历模板

这份简历内容&#xff0c;以信贷专员招聘需求为背景&#xff0c;我们制作了1份全面、专业且具有参考价值的简历案例&#xff0c;大家可以灵活借鉴。 信贷专员简历在线编辑下载&#xff1a;百度幻主简历 求职意向 求职类型&#xff1a;全职 意向岗位&#xff1a;信贷专员 …

Linux:docker的数据管理(6)

数据管理操作*方便查看容器内产生的数据 *多容器间实现数据共享 两种管理方式数据卷 数据卷容器 1.数据卷 数据卷是一个供容器使用的特殊目录&#xff0c;位于容器中&#xff0c;可将宿主机的目录挂载到数据卷上&#xff0c;对数据卷的修改操作立刻可见&#xff0c;并且更新数…

基于SpringBoot的在线视频教育平台的设计与实现

摘 要 随着科学技术的飞速发展&#xff0c;各行各业都在努力与现代先进技术接轨&#xff0c;通过科技手段提高自身的优势&#xff1b;对于在线视频教育平台当然也不能排除在外&#xff0c;随着网络技术的不断成熟&#xff0c;带动了在线视频教育平台&#xff0c;它彻底改变了过…

Django二转Day03 04

0 cbv执行流程&#xff0c;self问题 path(index/, Myview.as_view()),Myview.as_view() 实例化后返回 变成return Myview.dispatch(request, *args, **kwargs)但是视图函数Myview中没有 dispatch 方法 所以去 父类View中寻找return View.dispatch(request, *args, **kwargs)调用…

动手学深度学习(六)---权重衰退

文章目录 一、理论知识二、代码实现【相关总结】 主要解决过拟合 一、理论知识 1、使用均方范数作为硬性限制&#xff08;不常用&#xff09; 通过限制参数值的选择范围来控制模型容量 通常不限制偏移b 小的意味着更强的正则项 使用均方范数作为柔性限制 对于每个都可以找到使…