基于 FPGA 的彩色图像灰度化的设计实现(image_stitche_x)

news2024/9/22 3:34:38

文章目录

  • 前言
  • 一、图像合并模块的设计
  • 二、仿真文件


前言

image_stitche_x 模块:将串口接收的尺寸为 400480 大小的彩色图像与灰度化处理后的 400480 大小的图像数据以左右形式合并成一张 800*480 的图像。


提示:以下是本篇文章正文内容,下面案例可供参考

一、图像合并模块的设计

要实现图像以左右形式合并,首先要分析下“基于 DDR3 的串口传图帧缓存系统”是如何实现在 TFT 上显示一张图片的过程。这个过程是外部输入(串口传过来)图像数据经过数据位宽的处理后写入 DDR3 固定地址区间中,TFT 显示驱动模块根据 TFT 屏驱动时序从这个固定的地址区间取出数据实现一个个图像像素点数据在 TFT 屏上的显示,目前这个DDR3 中固定的地址区间的范围是存储 TFT 显示一帧数据的内存空间。可以看作是一个深度为 384000(5 寸 TFT 的长宽为 800480),数据位宽为 16bit 的“RAM”(假想的一个RAM)。写入和读出端口的地址范围均为 0~383999。每次写入(或读取)一个数据,写入端口地址(或读端口地址)加 1,地址达到最大值 383999 后又重新回到 0 开始往上加 1,循环往复。也就说 TFT 显示控制模块总是从读端的地址 0 开始读取数据,每次地址加 1,在读地址达到最大值 383999 后就完成了一帧图像的显示,然后读地址又重新回到 0 开始下一帧图像的显示。地址总是顺序的,这样在TFT屏显示的图像就取决于这个“RAM”地址从0~383999内存存储的数据。那么这样 TFT 显示的图像数据取决于写入端写入的图像数据,如果写入的图像数据是一张完整的 800480 图像数据,那么显示的就是一张 800480 的图像,如果写入的图像数据是两张 400480 的图像数据,那么显示的就是一张混合后拼接成的 800480 的图像。

那么如何实现左右形式的图像拼接显示呢?先写入第一张 400480 的图像数据,然后再写入第二张 400480 的图像数据?并不是,要知道如何去写入这两张图片数据,需要知道TFT 显示图片的扫描方式,这个在前面 TFT 显示驱动章节已经讲过,扫描方式是一行一行的,也就是这个缓存图片数据的“RAM”存储图片数据的内容结构如下图所示,地址 0799存储的是第1行图像数据,地址8001599存储的是第2行图像数据……,地址383200~383999存储的是第 480 行图像数据。
在这里插入图片描述
如果要实现左右形式的图片拼接显示,就需要往“RAM”中交错写的写入存储两张400480 的图片数据,左右形式拼接的“RAM”中存储的数据与 TFT 屏显示的对应关系如下图所示。从图中可以看出,存储两张 400480 图片的方式是,先存储左边图像(图片 2)的一行数据,然后再存储右边图像(图片 2)的一行数据,直到两张图像的 480 行数据均存储完成。
在这里插入图片描述
想要实现上面存储方式,考虑到两张图片可能是同时从其他模块进入,但由于图片 1 和图片 2 的存储到“RAM”有先后顺序,避免在存储其中一张图片时,另一张图片数据的丢失,需要在存储到“RAM”前为图片 1 和图片 2 的数据各加一个 fifo 就行少量数据的缓存。图像合并模块的整体设计框架如下图所示。图像合并模块两个图片输入端口,分别作为为图片 1 和图片 2 数据流的输入。通过逻辑控制交替输出两张图片的行数据给到下一级存储模块,到达实现图片合并的显示效果。
在这里插入图片描述
所谓的交替,就是先读取图片 1 的 FIFO 的 400 个数据进行输出,读取完之后,切换到读取图片 2 的 FIFO 的 400 个数据数据进行输出,同样读取完之后,切换到读取图片 1 的FIFO 的 400 个数据数据进行输出,如此反复进行这样的切换操作。(这里需要注意的是每次读取的数据个数是图片 1/图片 2 的一行数据的像素点个数,这里图片 1/图片 2 均为 400*480大小图片,所以每次读取 400 个数据)根据上面的设计思路,采用状态机进行设计,画出状态转移图如下图所示。
在这里插入图片描述
 IDLE:初始状态,上电或复位后处于该状态;
 ARB:仲裁状态,根据当前的情况决定下一状态跳转到哪个状态。如果跳转到 ARB 的上一状态是读取图片 1 的 FIFO 数据状态 RD_IMG1,则下一状态跳转到读取图片 2 的FIFO 数据状态RD_IMG2;否则如果跳转到 ARB 的上一状态是读取图片 2 的 FIFO 数据状态 RD_IMG2,则下一状态跳转到读取图片 1 的 FIFO 数据状态 RD_IMG1,读取FIFO 的交替切换就是在本状态实现。
 RD_IMG1:读取图片 1 的 FIFO 数据状态,在一行图像数据(400 个数据)读取完成后,状态跳转到 ARB 状态。
 RD_IMG2:读取图片 2 的 FIFO 数据状态,在一行图像数据(400 个数据)读取完成后,状态跳转到 ARB 状态。
状态机具体实现代码如下。

always@(posedge clk_image_out or posedge reset_p)
 begin
 if(reset_p)
 curr_state <= S_IDLE;
 else
 curr_state <= next_state;
 end
 always@(*)
 begin
 case(curr_state)
 S_IDLE:
 begin
 if(rst_busy_o == 1'b0)
 next_state = S_ARB;
 else
 next_state = S_IDLE;
 end
 S_ARB:
 begin
 if((rd_image_sel == 1'b0) && (image1_buf_empty == 1'b0))
 next_state = S_RD_IMG1;
 else if((rd_image_sel == 1'b1) && (image2_buf_empty == 1'b0))
 next_state = S_RD_IMG2;
 else
 next_state = S_ARB;
 end
 S_RD_IMG1:
 begin
 if(image1_buf_rden && (rd_data_cnt == IMAGE1_WIDTH_IN - 1'b1))
 next_state = S_ARB;
 else
 next_state = S_RD_IMG1;
 end
 S_RD_IMG2:
 begin
 if(image2_buf_rden && (rd_data_cnt == IMAGE2_WIDTH_IN - 1'b1))
 next_state = S_ARB;
 else
 next_state = S_RD_IMG2;
 end
 default: next_state = S_IDLE;
 endcase
 end

IDLE 状态中判断条件信号 rst_busy_o 为复位情况下,FIFO 的复位忙信号,FIFO 的复位需要一段时间,需要在 FIFO 复位完全结束,也就是 FIFO 的复位忙信号均变为 0 后才跳转到 ARB 状态。
RD_IMG1 和 RD_IMG2 状态中的 rd_image_sel 为读 FIFO 的切换选择标识信号,每读完图片 1(或图片 2)FIFO 的一行图片数据(400 个),信号 rd_image_sel 电平就变化一次。具体代码如下。

always@(posedge clk_image_out or posedge reset_p)
 begin
 if(reset_p)
 rd_image_sel <= 1'b0;
 else if((curr_state == S_RD_IMG1) && (rd_data_cnt == IMAGE1_WIDTH_IN - 1'b1))
 rd_image_sel <= 1'b1;
 else if((curr_state == S_RD_IMG2) && (rd_data_cnt == IMAGE2_WIDTH_IN - 1'b1))
 rd_image_sel <= 1'b0;
 else
 rd_image_sel <= rd_image_sel;
 end

不同的 rd_image_sel 信号电平表示的是需要读取哪个 FIFO 的图片数据,rd_image_sel为 0 表示需要读取图片 1 的 FIFO 的数据,rd_image_sel 为 1 表示需要读取图片 2 的 FIFO 的数据。代码中 rd_data_cnt 表示读取 FIFO 的数据个数计数,在读取 FIFO 状态(RD_IMG1 或RD_IMG2 状态),每读取一个 FIFO 数据,计数器加 1,具体代码如下。

always@(posedge clk_image_out or posedge reset_p)
 begin
 if(reset_p)
 rd_data_cnt <= 'd0;
 else if(curr_state == S_RD_IMG1)
 begin
 if(image1_buf_rden == 1'b1)
 rd_data_cnt <= rd_data_cnt + 1'b1;
 else
 rd_data_cnt <= rd_data_cnt;
 end
 else if(curr_state == S_RD_IMG2)
 begin
 if(image2_buf_rden == 1'b1)
 rd_data_cnt <= rd_data_cnt + 1'b1;
 else
 rd_data_cnt <= rd_data_cnt;
 end
 else
 rd_data_cnt <= 'd0;
 end

读 FIFO 信号 image1_buf_rden 和 image2_buf_rden 分别根据当前所处状态和 FIFO 的空满标识控制产生,直接使用组合逻辑产生。具体代码如下。

assign image1_buf_rden = (curr_state == S_RD_IMG1) & (image1_buf_empty == 1'b0) & (data_out_ready_i == 1'b0);
 assign image2_buf_rden = (curr_state == S_RD_IMG2) & (image2_buf_empty == 1'b0) & (data_out_ready_i == 1'b0);

data_out_ready_i 信号表示的是下游其他模块的入口 FIFO 的将满信号,主要是考虑到下游模块的入口 FIFO 如果要满的情况下,是不去读本模块的 FIFO 数据的,因为读取的本模块的 FIFO 数据是要输出给下游的,如果下游 FIFO 满了,还往下游传数据会导致数据的丢失的。合并后的输出信号就相对简单,将读出的 FIFO 的数据直接输出即可,考虑到读 FIFO 的读使能与读出的数据有效之间有一个周期的延时,所以读出的数据需要在读使能延迟一拍后获取数据,具体代码如下。

always@(posedge clk_image_out or posedge reset_p)
 begin
 if(reset_p)
 begin
 image1_buf_rden_dly1 <= 1'b0;
 image2_buf_rden_dly1 <= 1'b0;
 end
 else
 begin
 image1_buf_rden_dly1 <= image1_buf_rden;
 image2_buf_rden_dly1 <= image2_buf_rden;
 end
 end
 always@(posedge clk_image_out or posedge reset_p)
 begin
 if(reset_p)
 data_valid_o <= 1'b0;
 else if(image1_buf_rden_dly1 | image2_buf_rden_dly1)
 data_valid_o <= 1'b1;
 else
 data_valid_o <= 1'b0;
 end
 always@(posedge clk_image_out or posedge reset_p)
 begin
 if(reset_p)
 data_pixel_o <= 'd0;
 else if(image1_buf_rden_dly1)
 data_pixel_o <= image1_buf_dout;
 else if(image2_buf_rden_dly1)
 data_pixel_o <= image2_buf_dout;
 else
 data_pixel_o <= 'd0;
 end

考虑到模块的可移植性和可扩展性将图片的尺寸或数据位宽使用参数化表示,输入的两张图片的大小和合并输出的图片的大小尺寸均用参数化表示,具体代码如下。

module image_stitche_x
#(
 parameter DATA_WIDTH = 16, //16 or 24
 //image1_in: 400*480
 parameter IMAGE1_WIDTH_IN = 400,
 parameter IMAGE1_HEIGHT_IN = 480,
 //image2_in: 400*480
 parameter IMAGE2_WIDTH_IN = 400,
 parameter IMAGE2_HEIGHT_IN = 480,
 //image_out: 800*480
 parameter IMAGE_WIDTH_OUT = 800,
 parameter IMAGE_HEIGHT_OUT = 480
)
(
 input clk_image1_in ,
 input clk_image2_in ,
 input clk_image_out ,
 input reset_p ,
 output rst_busy_o ,
 output image_in_ready_o ,
 input [DATA_WIDTH-1:0] image1_data_pixel_i,
 input image1_data_valid_i,
 input [DATA_WIDTH-1:0] image2_data_pixel_i,
 input image2_data_valid_i,
 input data_out_ready_i ,
 output reg[DATA_WIDTH-1:0] data_pixel_o ,
 output reg data_valid_o 
);

考虑到用户在例化使用模块时对参数进行重定义时可能对出现由于笔误或其他不小心的错误使得图片的尺寸设置出现,输入的两张图片大小的尺寸参数的宽度之和不等于输出图片大小尺寸,或者输入图片的高度与输出图片的高度不一致问题,导致最终无法达到模块的功能而不便于定位错误。本模块与“彩色图像灰度化处理模块”设计采用类似的方式,使用generate-if 的形式对错误参数的设置输出固定的数据,或者采取他某种固定的输出,这样便于根据实际仿真和上板的现象快速定位是否为参数配置错误导致。具体代码如下。

generate
 if ((IMAGE1_WIDTH_IN + IMAGE2_WIDTH_IN != IMAGE_WIDTH_OUT) ||
(IMAGE1_HEIGHT_IN != IMAGE_HEIGHT_OUT) || (IMAGE2_HEIGHT_IN !=
IMAGE_HEIGHT_OUT))
 begin: error_set_pro //错误设置输入/输出图片参数情况的处理
//---------------------------------------------------------
 always@(posedge clk_image_out or posedge reset_p)
 begin
 if(reset_p)
 data_pixel_o <= 'd0;
 else
 data_pixel_o <= {DATA_WIDTH{1'b1}};
 end
 always@(posedge clk_image_out or posedge reset_p)
 begin
 if(reset_p)
 data_valid_o <= 'd0;
 else
 data_valid_o <= 1'b1;
 end
//---------------------------------------------------------
 end
 else
 begin: correct_set_pro //正确设置输入/输出图片参数情况的处理
//---------------------------------------------------------
........//正确参数配置情况下的代码,也就文档前面分析设计的代码
//---------------------------------------------------------
 end
endgenerate

完整设计图例如下:

在这里插入图片描述
完整代码设计如下:

/

// Module Name   : image_stitche_x
// Description   : 输入的两张图片左右拼接后输出,
// 设置输入的两张图片尺寸需与设置拼接后输出图片尺寸满足如下要求:
// 输入图片1的宽度 + 输入图片2的宽度 == 输出图片的宽度;
// 输入图片1的高度 == 输入图片2的高度 == 输出图片的高度;
// 不满足要求的做错误参数设置处理,以输出设置尺寸输出一张纯白色图片

/

module image_stitche_x
#(
  parameter DATA_WIDTH        = 16,  //16 or 24
  //image1_in: 400*480
  parameter IMAGE1_WIDTH_IN   = 400,
  parameter IMAGE1_HEIGHT_IN  = 480,
  //image2_in: 400*480
  parameter IMAGE2_WIDTH_IN   = 400,
  parameter IMAGE2_HEIGHT_IN  = 480,
  //image_out: 800*480
  parameter IMAGE_WIDTH_OUT   = 800,
  parameter IMAGE_HEIGHT_OUT  = 480
)
(
  input                      clk_image1_in      ,
  input                      clk_image2_in      ,
  input                      clk_image_out      ,
  input                      reset_p            ,

  output                     rst_busy_o         ,
  output                     image_in_ready_o   ,

  input     [DATA_WIDTH-1:0] image1_data_pixel_i,
  input                      image1_data_valid_i,

  input     [DATA_WIDTH-1:0] image2_data_pixel_i,
  input                      image2_data_valid_i,

  input                      data_out_ready_i   ,
  output reg[DATA_WIDTH-1:0] data_pixel_o       ,
  output reg                 data_valid_o       
);

localparam S_IDLE    = 4'b0001,
           S_ARB     = 4'b0010,
           S_RD_IMG1 = 4'b0100,
           S_RD_IMG2 = 4'b1000;

  wire                image1_buf_rden;
  reg                 image1_buf_rden_dly1;
  wire[DATA_WIDTH-1:0]image1_buf_dout;
  wire                image1_buf_alfull;
  wire                image1_buf_empty;
  wire                image1_buf_wr_rst_busy;
  wire                image1_buf_rd_rst_busy;

  wire                image2_buf_rden;
  reg                 image2_buf_rden_dly1;
  wire[DATA_WIDTH-1:0]image2_buf_dout;
  wire                image2_buf_alfull;
  wire                image2_buf_empty;
  wire                image2_buf_wr_rst_busy;
  wire                image2_buf_rd_rst_busy;

  reg                 rd_image_sel;//0:image1,1:image2
  reg [11:0]          rd_data_cnt;

  reg [3:0]           curr_state;
  reg [3:0]           next_state;

  assign rst_busy_o = image1_buf_wr_rst_busy | image1_buf_rd_rst_busy | image2_buf_wr_rst_busy | image2_buf_rd_rst_busy;
  assign image_in_ready_o = (~image1_buf_alfull) && (~image2_buf_alfull) && (~rst_busy_o);

generate
  if ((IMAGE1_WIDTH_IN + IMAGE2_WIDTH_IN != IMAGE_WIDTH_OUT) || (IMAGE1_HEIGHT_IN != IMAGE_HEIGHT_OUT) || (IMAGE2_HEIGHT_IN != IMAGE_HEIGHT_OUT)) 
  begin: error_set_pro   //错误设置输入/输出图片参数情况的处理
//---------------------------------------------------------
    always@(posedge clk_image_out or posedge reset_p)
    begin
      if(reset_p)
        data_pixel_o <= 'd0;
      else
        data_pixel_o <= {DATA_WIDTH{1'b1}};
    end

    always@(posedge clk_image_out or posedge reset_p)
    begin
      if(reset_p)
        data_valid_o <= 'd0;
      else
        data_valid_o <= 1'b1;
    end
//---------------------------------------------------------
  end
  else
  begin: correct_set_pro   //正确设置输入/输出图片参数情况的处理
//---------------------------------------------------------
    image_buffer image1_buffer (
      .rst           (reset_p                ), // input wire rst
      .wr_clk        (clk_image1_in          ), // input wire wr_clk
      .rd_clk        (clk_image_out          ), // input wire rd_clk
      .din           (image1_data_pixel_i    ), // input wire [15 : 0] din
      .wr_en         (image1_data_valid_i    ), // input wire wr_en
      .rd_en         (image1_buf_rden        ), // input wire rd_en
      .dout          (image1_buf_dout        ), // output wire [15 : 0] dout
      .almost_full   (image1_buf_alfull      ),  // output wire almost_full
      .full          (                       ), // output wire full
      .empty         (image1_buf_empty       ), // output wire empty
      .wr_rst_busy   (image1_buf_wr_rst_busy ), // output wire wr_rst_busy
      .rd_rst_busy   (image1_buf_rd_rst_busy )  // output wire rd_rst_busy
    );

    image_buffer image2_buffer (
      .rst           (reset_p                ), // input wire rst
      .wr_clk        (clk_image2_in          ), // input wire wr_clk
      .rd_clk        (clk_image_out          ), // input wire rd_clk
      .din           (image2_data_pixel_i    ), // input wire [15 : 0] din
      .wr_en         (image2_data_valid_i    ), // input wire wr_en
      .rd_en         (image2_buf_rden        ), // input wire rd_en
      .dout          (image2_buf_dout        ), // output wire [15 : 0] dout
      .almost_full   (image2_buf_alfull      ),  // output wire almost_full
      .full          (                       ), // output wire full
      .empty         (image2_buf_empty       ), // output wire empty
      .wr_rst_busy   (image2_buf_wr_rst_busy ), // output wire wr_rst_busy
      .rd_rst_busy   (image2_buf_rd_rst_busy )  // output wire rd_rst_busy
    );
	
	
	
	//-----------------------------------------------------------------------------------------
		//data_out_ready_i 信号表示的是下游其他模块的入口 FIFO 的将满信号,主要是考虑到下
		//游模块的入口 FIFO 如果要满的情况下,是不去读本模块的 FIFO 数据的,因为读取的本模
	   //块的 FIFO 数据是要输出给下游的,如果下游 FIFO 满了,还往下游传数据会导致数据的丢失的
   //-----------------------------------------------------------------------------------------
	
	assign image1_buf_rden = (curr_state == S_RD_IMG1) & (image1_buf_empty == 1'b0) & (data_out_ready_i == 1'b0);
    assign image2_buf_rden = (curr_state == S_RD_IMG2) & (image2_buf_empty == 1'b0) & (data_out_ready_i == 1'b0);
	
	//考虑到读 FIFO 的读使能与读出的数据有效之间有一个周期的延时,所以读出的数据需要在读使能延迟一拍后获取数据
	always@(posedge clk_image_out or posedge reset_p)
    begin
      if(reset_p)
      begin
        image1_buf_rden_dly1 <= 1'b0;
        image2_buf_rden_dly1 <= 1'b0;
      end
      else
      begin
        image1_buf_rden_dly1 <= image1_buf_rden;
        image2_buf_rden_dly1 <= image2_buf_rden;
      end
    end
	

    always@(posedge clk_image_out or posedge reset_p)
    begin
      if(reset_p)
        data_valid_o <= 1'b0;
      else if(image1_buf_rden_dly1 | image2_buf_rden_dly1)
        data_valid_o <= 1'b1;
      else
        data_valid_o <= 1'b0;
    end

    always@(posedge clk_image_out or posedge reset_p)
    begin
      if(reset_p)
        data_pixel_o <= 'd0;
      else if(image1_buf_rden_dly1)
        data_pixel_o <= image1_buf_dout;
      else if(image2_buf_rden_dly1)
        data_pixel_o <= image2_buf_dout;
      else
        data_pixel_o <= 'd0;
    end

    

    

    //rd_data_cnt
    always@(posedge clk_image_out or posedge reset_p)
    begin
      if(reset_p)
        rd_data_cnt <= 'd0;
      else if(curr_state == S_RD_IMG1)
      begin
        if(image1_buf_rden == 1'b1)
          rd_data_cnt <= rd_data_cnt + 1'b1;
        else
          rd_data_cnt <= rd_data_cnt;
      end
      else if(curr_state == S_RD_IMG2)
      begin
        if(image2_buf_rden == 1'b1)
          rd_data_cnt <= rd_data_cnt + 1'b1;
        else
          rd_data_cnt <= rd_data_cnt;
      end
      else
        rd_data_cnt <= 'd0;
    end

    //rd_image_sel
    always@(posedge clk_image_out or posedge reset_p)
    begin
      if(reset_p)
        rd_image_sel <= 1'b0;
      else if((curr_state == S_RD_IMG1) && (rd_data_cnt == IMAGE1_WIDTH_IN - 1'b1))
        rd_image_sel <= 1'b1;
      else if((curr_state == S_RD_IMG2) && (rd_data_cnt == IMAGE2_WIDTH_IN - 1'b1))
        rd_image_sel <= 1'b0;
      else
        rd_image_sel <= rd_image_sel;
    end

    //*********************************
    //State Machine
    //*********************************
    always@(posedge clk_image_out or posedge reset_p)
    begin
      if(reset_p)
        curr_state <= S_IDLE;
      else
        curr_state <= next_state;
    end

    always@(*)
    begin
      case(curr_state)
        S_IDLE:
        begin
          if(rst_busy_o == 1'b0)  // FIFO 的复位忙信号均变为 0 后才跳转到 ARB 状态
            next_state = S_ARB;
          else
            next_state = S_IDLE;
        end

        S_ARB:
        begin
          if((rd_image_sel == 1'b0) && (image1_buf_empty == 1'b0))
            next_state = S_RD_IMG1;
          else if((rd_image_sel == 1'b1) && (image2_buf_empty == 1'b0))
            next_state = S_RD_IMG2;
          else
            next_state = S_ARB;
        end

        S_RD_IMG1:
        begin
          if(image1_buf_rden && (rd_data_cnt == IMAGE1_WIDTH_IN - 1'b1))
            next_state = S_ARB;
          else
            next_state = S_RD_IMG1;
        end

        S_RD_IMG2:
        begin
          if(image2_buf_rden && (rd_data_cnt == IMAGE2_WIDTH_IN - 1'b1))
            next_state = S_ARB;
          else
            next_state = S_RD_IMG2;
        end

        default: next_state = S_IDLE;
      endcase
    end
//---------------------------------------------------------
  end
endgenerate

endmodule 

至此,图像左右合并模块的设计基本完成。

二、仿真文件

完整代码和仿真的 tb 文件见基于 FPGA 的彩色图像灰度化的设计实现。
仿真波形如下,图片1通道写入了两行(每行50个)数据,数据分别为049和100149。
在这里插入图片描述
之后,图片 2 通道写入了两行(每行 50 个)数据,数据分别为 50~99 和 150~199;
在这里插入图片描述
理论上,合并之后的输出数据应该为 0~199 的 200 个数据,可以观察仿真波形,仿真结果与期望一致。
在这里插入图片描述

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

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

相关文章

AI再度升级,IT业一片哀鸿遍野:程序员真的要失业了吗?

IT人员真的要失业了吗&#xff1f; 随着各个大厂已经相继传来裁员&#xff0c;降薪&#xff0c;减招的消息和ChatGPT等大型AI模型可以定制化写参考代码&#xff0c;甚至通过外接API直接帮助操作&#xff0c;IT人员似乎越来越不吃香了。 其实&#xff0c;ChatGPT有用的不是取代…

Diango学习-用户管理系统(简单部门管理、用户管理)

目录 1、创建项目和app 1.创建项目 2.创建app 2种创建方式 注册app 2、表结构的创建 Django中的模型字段有很多种&#xff0c;包括但不限于&#xff1a; 设计表结构&#xff08;Django&#xff09; 在models.py文件中创建表&#xff1a;部门表和员工表 加入性别列&…

FL Studio21.0.3.3517完整试用版

系统要求 FL STUDIO 可以运行在任何计算机上: 支持 WINDOWS: 7, 8, 10 或者更高版本 支持 MacOS: 10.11 或更高版本 不低于 4GB 的可用硬盘空间 建议最低 4GB 内存或 更高 当然CPU 越强大&#xff0c;也就意味着你运行的音源和效果器越多! FL Studio是一个非常受欢迎的数…

轻松实现远程访问本地wamp服务器,无公网IP也不怕,「内网穿透」

目录 前言 1.Wamp服务器搭建 1.1 Wamp下载和安装 1.2 Wamp网页测试 2. Cpolar内网穿透的安装和注册 2.1 本地网页发布 2.2 Cpolar云端设置 2.3 Cpolar本地设置 3. 公网访问测试 4. 结语 转载自cpolar极点云的文章&#xff1a;无公网IP&#xff1f;教你在外远程访问本地…

新零售发展现状剖析

“新零售”的商业生态将涵盖网络页面、实体店面、支付终端、数据系统、物流平台和营销路径等诸多方面。 企业通过使用大数据和人工智能等先进技术升级产品的生产、流通和销售流程&#xff0c;重塑商业结构与生态圈&#xff0c;深度融合线上服务、线下体验和现代物流。将物流、…

Devexpress GridControl 内部调用外面实现的FocusedRowChanged

个人需求是网格自带的条件发生改变时&#xff08;网格显示的内容会发生改变&#xff09;&#xff0c;同时需要刷新另一个网格的数据源&#xff0c;而另一个网格的数据源是走的这个网格的行焦点改变事件去刷新&#xff0c;自带的条件发生改变时并不会触发行焦点的改变 当前情况…

【HTTP协议】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 1. HTTP协议概述 2. HTTP协议的工作过程 3.…

LabVIEWCompactRIO 开发指南21 使用TCP/IP时处理孤立套接字

LabVIEWCompactRIO 开发指南21 使用TCP/IP时处理孤立套接字 无法重新建立侦听TCP套接字是设计基于TCP/IP的应用程序时最常见的挑战之一。此症状是由终止客户端或服务器应用程序后发生的孤立套接字引起的。如果按照本节中所述的技术设计代码&#xff0c;则可以避免此问题。本节…

大数据拥抱云原生 HashData助力资管数字化转型

5月16日&#xff0c;2023国际资管科技创业者与投资者大会“资管数据处理&#xff08;大模型&#xff09;技术”专场在上海举行。本次大会以“资产管理 数智技术”为主题&#xff0c;邀请企业、高校、投资机构等各方开展产业交流与讨论&#xff0c;共享共创行业机遇。 酷克数据…

GPT-5: 超越人类语言的模型,你还不了解一下?

目录 一、GPT-5时代引领者 二、技术特性 1&#xff0c;音频和视频处理 — 更强大的多模态处理能力 2&#xff0c;GPT-5颠覆影视制作&#xff1a;重写媒体消费时代 3&#xff0c;为机器人提供智慧大脑 4&#xff0c;更强的垂直行业应用 三、回顾一下GPT5被紧急叫停&…

设计模式之【命令模式】,方法调用的花式玩法

文章目录 一、什么是命令模式1、命令模式使用场景2、命令模式的主要角色3、命令模式优缺点4、命令模式注意事项及细节 二、使用示例1、命令模式的一般写法2、播放器功能案例3、遥控器案例 三、源码中的命令模式1、Thread 一、什么是命令模式 命令模式&#xff08;Command Patt…

图像分割标注工具——QuPath使用说明

0、QuPath资源一览 QuPath是一款病理学和生物图像定量分析的软件&#xff0c;支持多种标注方式。一些常用资源如下&#xff1a; 官网&#xff1a;QuPath 官方文档&#xff1a;https://qupath.readthedocs.io/en/stable/docs/intro/index.html 软件下载列表&#xff1a;http…

搜狗主动推送工具-搜狗推送接口自动推送

想要让自己的网站被搜狗快速收录&#xff0c;以下是一些优化建议&#xff1a; 提交网站地图&#xff1a;将网站地图提交到搜狗搜索引擎&#xff0c;能够让搜索引擎更快速地爬取和发现网站所有的页面。同时在网站地图中应该包含网站所有页面的链接&#xff0c;方便搜狗搜索引擎爬…

【读书笔记】《亲密关系》

作者&#xff1a;美国的罗兰米勒 刚拿到这本书的时候&#xff0c;就被最后将近100页的参考文献折服了&#xff0c;让我认为这本书极具专业性。 作者使用了14章&#xff0c;从人与人之间是如何相互吸引的&#xff0c;讲到如何相处与沟通&#xff0c;后又讲到如何面对冲突与解决矛…

openAI国内的免费镜像网站列表分享

1.ChatGPT For Free 地址&#xff1a;https://gpt4.gravityengine.cc/ 2.老北鼻AI智能助手 地址&#xff1a;https://739167295.ai201.live/ 3.AIChatOS 地址&#xff1a;https://chat.jinshutuan.com/#/chat/1684287150613 4.AIGPT 地址&#xff1a;http://20200.cn…

【Linux命令】mount / umount命令、查看文件的挂载情况(lsblk)

在Windows环境下&#xff0c;我们可以直接访问检测到的外部设备&#xff0c;如磁盘、U盘等&#xff1b;然而在Linux环境下&#xff0c;外部硬件设备如磁盘、SD卡等外部设备是无法直接访问的。因此就需要挂载。 参考链接&#xff1a;mount 详解 目录 1、什么是挂载&#xff1f;…

使用Vivado创建一个点亮FPGALED灯的项目

说明 1、本文针对没有使用过Vivado&#xff0c;也不知道如何用Vivado创建一个项目的朋友。 2、本文内容为用Vivado创建一个点亮FPGA LED灯项目的全部流程。 正文 1、创建一个新项目&#xff0c;点击创建新项目&#xff0c;并点击next。 2、选择项目名称和项目保存路径。 3、…

时间序列-相关性-ACF PACF CCF

一、自相关系数&#xff1a; 衡量的是同一个时间序列内的两个不同的时间段的相关性 弱平稳 If波动&#xff0c;波动幅度也是固定的。 相关图 不同时间间隔的相关系数算出来并且绘制在图中 例&#xff1a;(python) 分析&#xff1a; ①当时间间隔为0的时候&#xff0c;相关系…

【MongoDB】MongoDB分布式文件存储的数据库

一、数据库简介 1、数据库 数据库是按照数据结构来组织、存储和管理数据的仓库&#xff1b;我们的程序都是在内存中运行的&#xff0c;一旦程序运行结束或者计算机断电&#xff0c;程序运行中的数据都会丢失&#xff1b;所以我们就需要将一些程序运行的数据持久化到硬盘中&am…

计算机信息安全保护等级划分为五个安全级别

《计算机信息安全保护等级划分准则》将计算机信息安全保护等级划分为五个安全级别&#xff1a; 安全级别级别名称是否需要备案对公民、法人和其他组织的合法权益造成的损害程度对社会秩序、公共利益造成的损害程度对国家安全造成的损害程度适用范围重要程度第一级自主保护级无…