FPGA 图像边缘检测(Canny算子)

1 顶层代码

`timescale 1ns / 1ps
//边缘检测二阶微分算子:canny算子


module image_canny_edge_detect (
    input clk,
    input reset, //复位高电平有效

    input [10:0] img_width,
    input [ 9:0] img_height,
    input [ 7:0] low_threshold,
    input [ 7:0] high_threshold,

    input valid_i,
    input [15:0] rgb_565_i,  // 输入的16位RGB图像数据

    output        valid_o,
    output [15:0] rgb_565_o  // 输出的16位RGB图像数据
);


  //变量声明
  wire valid_gray;
  wire [7:0] img_data_gray;

  wire valid_gf;
  wire [7:0] img_data_gf;

  wire valid_sbl;
  wire [7:0] grad_mag;
  wire [10:0] grad_dx;
  wire [10:0] grad_dy;

  wire valid_nms;
  wire [7:0] img_data_nms;

  wire valid_db;
  wire [7:0] img_data_db;

  wire [23:0] img_data_i, img_data_o;
  assign img_data_i = {rgb_565_i[15:11], 3'b000, rgb_565_i[10:5], 2'b00, rgb_565_i[4:0], 3'b000};
  assign rgb_565_o  = {{img_data_o[23:19], img_data_o[15:10], img_data_o[7:3]}};


  //彩色图像灰度化
  image_rgb2gray u_image_rgb2gray (
      .clk       (clk),
      .reset     (reset),
      .valid_i   (valid_i),
      .img_data_i(img_data_i),
      .valid_o   (valid_gray),
      .img_data_o(img_data_gray)
  );

  ///高斯滤波
  image_gaussian_filter u_image_gaussian_filter (
      .clk       (clk),
      .reset     (reset),
      .img_width (img_width),
      .img_height(img_height),
      .valid_i   (valid_gray),
      .img_data_i(img_data_gray),
      .valid_o   (valid_gf),
      .img_data_o(img_data_gf)
  );

  ///Sobel算子
  image_sobel_edge u_image_sobel_edge (
      .clk       (clk),
      .reset     (reset),
      .img_width (img_width),
      .img_height(img_height),
      .valid_i   (valid_gf),
      .img_data_i(img_data_gf),
      .valid_o   (valid_sbl),
      .grad_mag  (grad_mag),
      .grad_dx   (grad_dx),
      .grad_dy   (grad_dy)
  );

  ///非极大值计算
  non_maximum_suppression u_non_maximum_suppression (
      .clk       (clk),
      .reset     (reset),
      .img_width (img_width),
      .img_height(img_height),
      .valid_i   (valid_sbl),
      .grad_mag  (grad_mag),
      .grad_dx   (grad_dx),
      .grad_dy   (grad_dy),
      .valid_o   (valid_nms),
      .img_data_o(img_data_nms)
  );

  双阈值
  //根据输入的低阈值和高阈值来判断,如果这个像素点大于高阈值,则赋值为255;如果低于低阈值,则赋值为0;
  double_threshold u_double_threshold (
      .clk           (clk),
      .reset         (reset),
      .img_width     (img_width),
      .img_height    (img_height),
      .low_threshold (low_threshold),
      .high_threshold(high_threshold),
      .valid_i       (valid_nms),
      .img_data_i    (img_data_nms),
      .valid_o       (valid_db),
      .img_data_o    (img_data_db)
  );

  assign valid_o = valid_db;
  assign img_data_o = {3{img_data_db}};

endmodule

2 彩色图变灰度图代码

`timescale 1ns / 1ps
//彩色图像灰度化



module image_rgb2gray (
    input clk,
    input reset,

    input valid_i,
    input [23:0] img_data_i,

    output valid_o,
    output [7:0] img_data_o
);

  //常量
  parameter MODE = 0;  //0表示加权平均法,1表示平均法 
  //Y=0.299*R十0.587*G+0.114*B
  parameter C0 = 9'd306;  //0.299*1024;
  parameter C1 = 10'd601;  //0.587*1024;
  parameter C2 = 7'd117;  //0.114*1024;

  //参数声明
  wire [7:0] R, G, B;

  assign {R, G, B} = img_data_i;

  generate
    if (MODE) begin

      reg valid_d1;
      reg [9:0] RGB_avr;

      reg valid_d2;
      reg [16:0] RGB_avr_m;

      reg valid_d3;
      reg [7:0] RGB_new;

      //平均法
      //1/3 * 512 = 171

      always @(posedge clk) begin
        if (reset) begin
          valid_d1 <= 'b0;
          RGB_avr  <= 'b0;
        end else begin
          valid_d1 <= valid_i;
          RGB_avr  <= R + G + B;
        end
      end

      //最大值不可能超过255*3*171 = 17'd130815
      always @(posedge clk) begin
        RGB_avr_m <= RGB_avr * 8'd171;
      end
      always @(posedge clk) begin
        if (reset) begin
          valid_d2 <= 'b0;
        end else begin
          valid_d2 <= valid_d1;
        end
      end

      //最大值不可能超过255
      always @(posedge clk) begin
        if (reset) begin
          valid_d3 <= 'b0;
          RGB_new  <= 'b0;
        end else begin
          valid_d3 <= valid_d2;
          RGB_new  <= RGB_avr_m[16:9];
        end
      end

      assign valid_o = valid_d3;
      assign img_data_o = {3{RGB_new}};

    end else begin

      //加权平均法
      reg valid_d1;
      reg [16:0] Y_R_m;
      reg [17:0] Y_G_m;
      reg [14:0] Y_B_m;

      reg valid_d2;
      reg [17:0] Y_s;//最大值,当RGB都等于255时,(C0 + C1 + C2)*255 = 1024*255;不会出现负数

      reg valid_d3;
      reg [7:0] Y;

      always @(posedge clk) begin
        Y_R_m <= R * C0;
        Y_G_m <= G * C1;
        Y_B_m <= B * C2;
      end

      always @(posedge clk) begin
        if (reset) begin
          valid_d1 <= 0;
        end else begin
          valid_d1 <= valid_i;
        end
      end

      always @(posedge clk) begin
        if (reset) begin
          Y_s <= 0;
          valid_d2 <= 0;
        end else begin
          if (valid_d1) begin
            Y_s <= Y_R_m + Y_G_m + Y_B_m;
          end
          valid_d2 <= valid_d1;
        end
      end

      always @(posedge clk) begin
        if (reset) begin
          Y <= 0;
          valid_d3 <= 0;
        end else begin
          if (valid_d2) begin
            Y <= Y_s[17:10];
          end
          valid_d3 <= valid_d2;
        end
      end

      assign valid_o = valid_d3;
      assign img_data_o = Y;

    end
  endgenerate


endmodule

3 3行缓存代码

`timescale 1ns / 1ps
//FIFO实现3行图像缓存



module image_line_buffer #(
    parameter W = 8
) (
    input wire clk,
    input wire reset,

    input wire [10:0] img_width,
    input wire [ 9:0] img_height,

    input wire valid_i,
    input wire [W-1:0] img_data_i,

    output reg valid_o,
    output reg [W-1:0] prev_line_data_o,
    output reg [W-1:0] cur_line_data_o,
    output reg [W-1:0] next_line_data_o
);

  //常量声明
  localparam N = 3;  //窗口大小

  //变量声明
  genvar i;
  integer j;
  wire [0:0] valid[0:N-1];
  wire [W-1:0] data[0:N-1];

  reg [10:0] out_data_cnt;
  reg [9:0] out_line_cnt;
  reg ch_valid;
  reg [W-1:0] ch_data[0:N-1];

  assign valid[0] = valid_i;
  assign data[0]  = img_data_i;

  //行缓存模块, 只需要缓存N-1个fifo即可
  generate
    for (i = 1; i < N; i = i + 1) begin : lb

      line_buffer #(
          .W(W)
      ) u_line_buffer (
          .clk      (clk),
          .reset    (reset),
          .img_width(img_width),
          .valid_i  (valid[i-1]),
          .data_i   (data[i-1]),
          .valid_o  (valid[i]),
          .data_o   (data[i])
      );
    end
  endgenerate

  //模式1,按照上一行、当前行、下一行输出
  //特殊情况,可根据需求设定,是复制还是给0
  //第1个行缓存,是整个画面的第1行时, 上一行数据不存在,复制第1个行缓存或者直接为0输出
  //第1个行缓存,是整个画面的最后1行时,下一行数据不存在,复制第1个行缓存输出
  always @(posedge clk) begin
    if (reset) begin
      for (j = 0; j < 3; j = j + 1) ch_data[j] <= 0;
    end else if (valid[N-2]) begin
      ch_data[1] <= data[1];
      if (out_line_cnt == 0) begin
        ch_data[2] <= 0;
        ch_data[0] <= data[0];
      end else if (out_line_cnt == img_height - 1) begin
        ch_data[2] <= data[2];
        ch_data[0] <= 0;
      end else begin
        ch_data[2] <= data[2];
        ch_data[0] <= data[0];
      end
    end
  end


  always @(posedge clk) begin
    if (reset) begin
      ch_valid <= 0;
      out_data_cnt <= 0;
      out_line_cnt <= 0;
    end else begin
      ch_valid <= valid[N-2];
      out_data_cnt <= valid[N-2] ? ((out_data_cnt == img_width - 1) ? 0 : out_data_cnt + 1) : out_data_cnt;
      out_line_cnt <= valid[N-2]&&(out_data_cnt == img_width - 1) ? ((out_line_cnt == img_height - 1) ? 0 : out_line_cnt + 1) : out_line_cnt;
    end
  end

  //单路输出
  always @(posedge clk) begin
    if (reset) begin
      valid_o <= 0;
      prev_line_data_o <= 0;
      cur_line_data_o <= 0;
      next_line_data_o <= 0;
    end else begin
      valid_o <= ch_valid;
      prev_line_data_o <= ch_data[2];
      cur_line_data_o <= ch_data[1];
      next_line_data_o <= ch_data[0];
    end
  end


endmodule

4 1行缓存代码

`timescale 1ns / 1ps
//FIFO实现1行图像缓存



module line_buffer #(
    parameter W = 8
) (
    input wire clk,
    input wire reset,

    input wire [10:0] img_width,

    input wire valid_i,
    input wire [W-1:0] data_i,

    output wire valid_o,
    output wire [W-1:0] data_o
);

  //变量声明
  reg [10:0] wr_data_cnt;
  wire rd_en;
  wire [11:0] fifo_data_count_w;

  //写入数据计数
  always @(posedge clk or posedge reset) begin
    if (reset) begin
      wr_data_cnt <= 0;
    end else begin
      wr_data_cnt <= valid_i && (wr_data_cnt < img_width) ? (wr_data_cnt + 1'b1) : wr_data_cnt;
    end
  end

  //assign rd_en = valid_i&&(wr_data_cnt == img_width) ? 1'b1 : 1'b0;
  //等价于
  assign rd_en   = valid_i && (fifo_data_count_w == img_width) ? 1'b1 : 1'b0;
  assign valid_o = rd_en;

  generate
    if (W == 8) begin

      fifo_line_buffer_w8 u_fifo_line_buffer_w8 (
          .clk       (clk),               // input wire clk
          .srst      (reset),             // input wire srst
          .din       (data_i),            // input wire [7 : 0] din
          .wr_en     (valid_i),           // input wire wr_en
          .rd_en     (rd_en),             // input wire rd_en
          .dout      (data_o),            // output wire [7 : 0] dout
          .full      (),                  // output wire full
          .empty     (),                  // output wire empty
          .data_count(fifo_data_count_w)  // output wire [11 : 0] data_count
      );

    end else begin

      fifo_line_buffer u_fifo_line_buffer (
          .clk       (clk),               // input wire clk
          .srst      (reset),             // input wire srst
          .din       (data_i),            // input wire [22 : 0] din
          .wr_en     (valid_i),           // input wire wr_en
          .rd_en     (rd_en),             // input wire rd_en
          .dout      (data_o),            // output wire [22 : 0] dout
          .full      (),                  // output wire full
          .empty     (),                  // output wire empty
          .data_count(fifo_data_count_w)  // output wire [11 : 0] data_count
      );

    end

  endgenerate


endmodule

 

 

 

 

5 高斯滤波代码

`timescale 1ns / 1ps
//  高斯滤波



module image_gaussian_filter (
    input wire clk,
    input wire reset,

    input wire [10:0] img_width,
    input wire [ 9:0] img_height,

    input wire valid_i,
    input wire [7:0] img_data_i,

    output reg valid_o,
    output reg [7:0] img_data_o
);

  //常量声明
  localparam MODE = 1;  //0表示彩色图像输出,1表示灰度图像输出

  //变量声明
  wire valid;
  wire [7:0] prev_line_data;
  wire [7:0] cur_line_data;
  wire [7:0] next_line_data;
  reg valid_d1;
  reg [7:0] prev_line_data_d1;
  reg [7:0] cur_line_data_d1;
  reg [7:0] next_line_data_d1;

  reg [7:0] prev_line_data_d2;
  reg [7:0] cur_line_data_d2;
  reg [7:0] next_line_data_d2;
  reg [7:0] x_cnt;

  reg valid_s;
  reg [7:0] prev_line_data_d2_s;
  reg [7:0] cur_line_data_d2_s;
  reg [7:0] next_line_data_d2_s;
  reg [7:0] prev_line_data_d1_s;
  reg [7:0] cur_line_data_d1_s;
  reg [7:0] next_line_data_d1_s;
  reg [7:0] prev_line_data_s;
  reg [7:0] cur_line_data_s;
  reg [7:0] next_line_data_s;

  wire [7:0] Y0, Y1, Y2;
  wire [7:0] Y3, Y4, Y5;
  wire [7:0] Y6, Y7, Y8;

  reg valid_s_d1;
  reg [9:0] Y_sum0;
  reg [10:0] Y_sum1;
  reg [9:0] Y_sum2;

  reg valid_s_d2;
  reg [14:0] Y_sum;
  wire [15:0] RGB_sum;
  wire [7:0] gray;

  image_line_buffer u_image_line_buffer (
      .clk             (clk),
      .reset           (reset),
      .img_width       (img_width),
      .img_height      (img_height),
      .valid_i         (valid_i),
      .img_data_i      (img_data_i),
      .valid_o         (valid),
      .prev_line_data_o(prev_line_data),
      .cur_line_data_o (cur_line_data),
      .next_line_data_o(next_line_data)
  );

  always @(posedge clk) begin
    if (reset) begin
      valid_d1 <= 0;
      prev_line_data_d1 <= 0;
      cur_line_data_d1 <= 0;
      next_line_data_d1 <= 0;
      prev_line_data_d2 <= 0;
      cur_line_data_d2 <= 0;
      next_line_data_d2 <= 0;
    end else begin
      valid_d1 <= valid;
      prev_line_data_d1 <= prev_line_data;
      cur_line_data_d1 <= cur_line_data;
      next_line_data_d1 <= next_line_data;
      prev_line_data_d2 <= prev_line_data_d1;
      cur_line_data_d2 <= cur_line_data_d1;
      next_line_data_d2 <= next_line_data_d1;
    end
  end

  //边界数据处理
  always @(posedge clk) begin
    if (reset) begin
      x_cnt <= 0;
    end else begin
      x_cnt <= valid_d1 ? ((x_cnt == img_width - 1) ? 0 : x_cnt + 1) : x_cnt;
    end
  end

  always @(posedge clk) begin
    if (reset) begin
      valid_s <= 0;
      prev_line_data_d2_s <= 0;
      cur_line_data_d2_s <= 0;
      next_line_data_d2_s <= 0;
      prev_line_data_d1_s <= 0;
      cur_line_data_d1_s <= 0;
      next_line_data_d1_s <= 0;
      prev_line_data_s <= 0;
      cur_line_data_s <= 0;
      next_line_data_s <= 0;
    end else begin
      valid_s <= valid_d1;
      prev_line_data_d1_s <= prev_line_data_d1;
      cur_line_data_d1_s <= cur_line_data_d1;
      next_line_data_d1_s <= next_line_data_d1;
      if (x_cnt == 0) begin
        prev_line_data_d2_s <= prev_line_data_d1;
        cur_line_data_d2_s <= cur_line_data_d1;
        next_line_data_d2_s <= next_line_data_d1;
        prev_line_data_s <= prev_line_data;
        cur_line_data_s <= cur_line_data;
        next_line_data_s <= next_line_data;
      end
      if (x_cnt == img_width - 1) begin
        prev_line_data_d2_s <= prev_line_data_d2;
        cur_line_data_d2_s <= cur_line_data_d2;
        next_line_data_d2_s <= next_line_data_d2;
        prev_line_data_s <= prev_line_data_d1;
        cur_line_data_s <= cur_line_data_d1;
        next_line_data_s <= next_line_data_d1;
      end else begin
        prev_line_data_d2_s <= prev_line_data_d2;
        cur_line_data_d2_s <= cur_line_data_d2;
        next_line_data_d2_s <= next_line_data_d2;
        prev_line_data_s <= prev_line_data;
        cur_line_data_s <= cur_line_data;
        next_line_data_s <= next_line_data;
      end
    end
  end

  assign Y0 = prev_line_data_d2_s;
  assign Y1 = cur_line_data_d2_s;
  assign Y2 = next_line_data_d2_s;
  assign Y3 = prev_line_data_d1_s;
  assign Y4 = cur_line_data_d1_s;
  assign Y5 = next_line_data_d1_s;
  assign Y6 = prev_line_data_s;
  assign Y7 = cur_line_data_s;
  assign Y8 = next_line_data_s;

  //高斯滤波模版
  /************
 [1. 2. 1.]
 [2. 4. 2.]
 [1. 2. 1.]
*************/

  always @(posedge clk) begin
    if (reset) begin
      valid_s_d1 <= 0;
      {Y_sum0, Y_sum1, Y_sum2} <= 0;
    end else if (valid_s) begin
      valid_s_d1 <= 1;
      Y_sum0 <= Y0 + {Y1, 1'b0} + Y2;
      Y_sum1 <= {Y3, 1'b0} + {Y4, 2'b0} + {Y5, 1'b0};
      Y_sum2 <= Y6 + {Y7, 1'b0} + Y8;
    end else valid_s_d1 <= 0;
  end


  //彩色图像 直接求和
  //灰度图像 1/3,扩大4bit,即16/3约等于5 = 4 + 1
  always @(posedge clk) begin
    if (reset) begin
      valid_s_d2 <= 0;
      Y_sum <= 0;
    end else if (valid_s_d1) begin
      valid_s_d2 <= 1;
      Y_sum <= Y_sum0 + Y_sum1 + Y_sum2;
    end else valid_s_d2 <= 0;
  end

  always @(posedge clk) begin
    if (reset) begin
      valid_o <= 0;
      img_data_o <= 0;
    end else if (valid_s_d2) begin
      valid_o <= 1;
      img_data_o <= Y_sum[11:4];
    end else begin
      valid_o <= 0;
    end
  end

endmodule

6 sobel边缘检测代码

`timescale 1ns / 1ps
//边缘检测一阶微分算子:Sobel算子



module image_sobel_edge (
    input wire clk,
    input wire reset,

    input wire [10:0] img_width,
    input wire [ 9:0] img_height,

    input wire valid_i,
    input wire [7:0] img_data_i,

    output reg valid_o,
    output reg [7:0] grad_mag,
    output reg [10:0] grad_dx,
    output reg [10:0] grad_dy
);

  //常量声明
  localparam N = 16;

  //变量声明
  wire valid;
  wire [7:0] prev_line_data;
  wire [7:0] cur_line_data;
  wire [7:0] next_line_data;
  reg valid_d1;
  reg [7:0] prev_line_data_d1;
  reg [7:0] cur_line_data_d1;
  reg [7:0] next_line_data_d1;

  reg [7:0] prev_line_data_d2;
  reg [7:0] cur_line_data_d2;
  reg [7:0] next_line_data_d2;
  reg [10:0] x_cnt;

  reg valid_s;
  reg [7:0] prev_line_data_d2_s;
  reg [7:0] cur_line_data_d2_s;
  reg [7:0] next_line_data_d2_s;
  reg [7:0] prev_line_data_d1_s;
  reg [7:0] cur_line_data_d1_s;
  reg [7:0] next_line_data_d1_s;
  reg [7:0] prev_line_data_s;
  reg [7:0] cur_line_data_s;
  reg [7:0] next_line_data_s;

  wire [7:0] Y0;
  wire [7:0] Y1;
  wire [7:0] Y2;
  wire [7:0] Y3;
  wire [7:0] Y4;
  wire [7:0] Y5;
  wire [7:0] Y6;
  wire [7:0] Y7;
  wire [7:0] Y8;

  reg valid_s_d1;
  wire [9:0] Gx_Y0_a;
  wire [9:0] Gx_Y1_a;
  wire [9:0] Gy_Y0_a;
  wire [9:0] Gy_Y1_a;
  reg Gx_Y_sign;
  reg [9:0] Gx_Y;
  reg Gy_Y_sign;
  reg [9:0] Gy_Y;

  reg valid_s_d2;
  reg Gx_Y_sign_d1;
  reg [19:0] Gx_Y_square;
  reg Gy_Y_sign_d1;
  reg [19:0] Gy_Y_square;
  wire [20:0] Gx_Gy_sum;

  reg [N-1:0] Gx_Y_sign_shift;
  reg [10*N-1:0] Gx_Y_shift;
  reg [N-1:0] Gy_Y_sign_shift;
  reg [10*N-1:0] Gy_Y_shift;

  wire valid_sqr;
  wire [10:0] data_sqr;

  image_line_buffer u_image_line_buffer (
      .clk             (clk),
      .reset           (reset),
      .img_width       (img_width),
      .img_height      (img_height),
      .valid_i         (valid_i),
      .img_data_i      (img_data_i),
      .valid_o         (valid),
      .prev_line_data_o(prev_line_data),
      .cur_line_data_o (cur_line_data),
      .next_line_data_o(next_line_data)
  );

  always @(posedge clk) begin
    if (reset) begin
      valid_d1 <= 0;
      prev_line_data_d1 <= 0;
      cur_line_data_d1 <= 0;
      next_line_data_d1 <= 0;
      prev_line_data_d2 <= 0;
      cur_line_data_d2 <= 0;
      next_line_data_d2 <= 0;
    end else begin
      valid_d1 <= valid;
      prev_line_data_d1 <= prev_line_data;
      cur_line_data_d1 <= cur_line_data;
      next_line_data_d1 <= next_line_data;
      prev_line_data_d2 <= prev_line_data_d1;
      cur_line_data_d2 <= cur_line_data_d1;
      next_line_data_d2 <= next_line_data_d1;
    end
  end

  //边界数据处理
  always @(posedge clk) begin
    if (reset) begin
      x_cnt <= 0;
    end else begin
      x_cnt <= valid_d1 ? ((x_cnt == img_width - 1) ? 0 : x_cnt + 1) : x_cnt;
    end
  end

  always @(posedge clk) begin
    if (reset) begin
      valid_s <= 0;
      prev_line_data_d2_s <= 0;
      cur_line_data_d2_s <= 0;
      next_line_data_d2_s <= 0;
      prev_line_data_d1_s <= 0;
      cur_line_data_d1_s <= 0;
      next_line_data_d1_s <= 0;
      prev_line_data_s <= 0;
      cur_line_data_s <= 0;
      next_line_data_s <= 0;
    end else begin
      valid_s <= valid_d1;
      prev_line_data_d1_s <= prev_line_data_d1;
      cur_line_data_d1_s <= cur_line_data_d1;
      next_line_data_d1_s <= next_line_data_d1;
      if (x_cnt == 0) begin
        prev_line_data_d2_s <= prev_line_data_d1;
        cur_line_data_d2_s <= cur_line_data_d1;
        next_line_data_d2_s <= next_line_data_d1;
        prev_line_data_s <= prev_line_data;
        cur_line_data_s <= cur_line_data;
        next_line_data_s <= next_line_data;
      end
      if (x_cnt == img_width - 1) begin
        prev_line_data_d2_s <= prev_line_data_d2;
        cur_line_data_d2_s <= cur_line_data_d2;
        next_line_data_d2_s <= next_line_data_d2;
        prev_line_data_s <= prev_line_data_d1;
        cur_line_data_s <= cur_line_data_d1;
        next_line_data_s <= next_line_data_d1;
      end else begin
        prev_line_data_d2_s <= prev_line_data_d2;
        cur_line_data_d2_s <= cur_line_data_d2;
        next_line_data_d2_s <= next_line_data_d2;
        prev_line_data_s <= prev_line_data;
        cur_line_data_s <= cur_line_data;
        next_line_data_s <= next_line_data;
      end
    end
  end

  assign Y0 = prev_line_data_d2_s;
  assign Y1 = cur_line_data_d2_s;
  assign Y2 = next_line_data_d2_s;
  assign Y3 = prev_line_data_d1_s;
  assign Y4 = cur_line_data_d1_s;
  assign Y5 = next_line_data_d1_s;
  assign Y6 = prev_line_data_s;
  assign Y7 = cur_line_data_s;
  assign Y8 = next_line_data_s;

  /Sobey算子
  /************
    [-1.  0.  1]  
    [-2.  0.  2]
Gx= [-1.  0.  1]
    [ 1.  2.  1]
    [ 0.  0.  0]
Gy= [-1. -2. -1]
*************/
  assign Gx_Y0_a = Y0 + {Y3, 1'b0} + Y6;
  assign Gx_Y1_a = Y2 + {Y5, 1'b0} + Y8;

  assign Gy_Y0_a = Y0 + {Y1, 1'b0} + Y2;
  assign Gy_Y1_a = Y6 + {Y7, 1'b0} + Y8;
  always @(posedge clk) begin
    if (reset) begin
      valid_s_d1 <= 0;
      {Gx_Y, Gy_Y} <= 0;
      {Gx_Y_sign, Gy_Y_sign} <= 0;
    end else if (valid_s) begin
      valid_s_d1 <= 1;
      Gx_Y <= (Gx_Y0_a > Gx_Y1_a) ? Gx_Y0_a - Gx_Y1_a : Gx_Y1_a - Gx_Y0_a;
      Gx_Y_sign <= (Gx_Y0_a > Gx_Y1_a) ? 1 : 0;
      Gy_Y <= (Gy_Y0_a > Gy_Y1_a) ? Gy_Y0_a - Gy_Y1_a : Gy_Y1_a - Gy_Y0_a;
      Gy_Y_sign <= (Gy_Y0_a > Gy_Y1_a) ? 1 : 0;
    end else valid_s_d1 <= 0;
  end

  //求平方
  always @(posedge clk) begin
    if (reset) begin
      valid_s_d2  <= 0;
      Gx_Y_square <= 0;
      Gy_Y_square <= 0;
    end else begin
      valid_s_d2  <= valid_s_d1;
      Gx_Y_square <= Gx_Y * Gx_Y;
      Gy_Y_square <= Gy_Y * Gy_Y;
    end
  end
  assign Gx_Gy_sum = Gx_Y_square + Gy_Y_square;

  //平方根
  cordic_square_root u_cordic_square_root (
      .aclk                   (clk),         // input wire aclk
      .s_axis_cartesian_tvalid(valid_s_d2),  // input wire s_axis_cartesian_tvalid
      .s_axis_cartesian_tdata (Gx_Gy_sum),   // input wire [23 : 0] s_axis_cartesian_tdata
      .m_axis_dout_tvalid     (valid_sqr),   // output wire m_axis_dout_tvalid
      .m_axis_dout_tdata      (data_sqr)     // output wire [15 : 0] m_axis_dout_tdata
  );

  always @(posedge clk) begin
    if (reset) begin
      Gx_Y_sign_shift <= 0;
      Gx_Y_shift <= 0;
      Gy_Y_sign_shift <= 0;
      Gy_Y_shift <= 0;
    end else begin
      Gx_Y_sign_shift <= {Gx_Y_sign_shift, Gx_Y_sign};
      Gx_Y_shift <= {Gx_Y_shift, Gx_Y};
      Gy_Y_sign_shift <= {Gy_Y_sign_shift, Gy_Y_sign};
      Gy_Y_shift <= {Gy_Y_shift, Gy_Y};
    end
  end

  always @(posedge clk) begin
    if (reset) begin
      valid_o  <= 0;
      grad_mag <= 0;
      grad_dx  <= 0;
      grad_dy  <= 0;
    end else if (valid_sqr) begin
      valid_o  <= 1;
      grad_mag <= data_sqr;
      grad_dx  <= {Gx_Y_sign_shift[N-1], Gx_Y_shift[N*10-1:(N-1)*10]};
      grad_dy  <= {Gy_Y_sign_shift[N-1], Gy_Y_shift[N*10-1:(N-1)*10]};
    end else begin
      valid_o <= 0;
    end
  end

endmodule

 

7 非极大值抑制代码

`timescale 1ns / 1ps
//  非极大值抑制



module non_maximum_suppression (
    input clk,
    input reset,

    input wire [10:0] img_width,
    input wire [ 9:0] img_height,

    input valid_i,
    input [7:0] grad_mag,
    input [10:0] grad_dx,
    input [10:0] grad_dy,

    output reg valid_o,
    output reg [7:0] img_data_o
);

  //常量
  localparam N = 24;

  //参数声明
  wire valid;
  wire [7:0] prev_line_data;
  wire [7:0] cur_line_data;
  wire [7:0] next_line_data;
  reg valid_d1;
  reg [7:0] prev_line_data_d1;
  reg [7:0] cur_line_data_d1;
  reg [7:0] next_line_data_d1;

  reg [7:0] prev_line_data_d2;
  reg [7:0] cur_line_data_d2;
  reg [7:0] next_line_data_d2;
  reg [10:0] x_cnt;

  reg valid_s;
  reg [7:0] prev_line_data_d2_s;
  reg [7:0] cur_line_data_d2_s;
  reg [7:0] next_line_data_d2_s;
  reg [7:0] prev_line_data_d1_s;
  reg [7:0] cur_line_data_d1_s;
  reg [7:0] next_line_data_d1_s;
  reg [7:0] prev_line_data_s;
  reg [7:0] cur_line_data_s;
  reg [7:0] next_line_data_s;

  wire [7:0] Y0, Y1, Y2;
  wire [7:0] Y3, Y4, Y5;
  wire [7:0] Y6, Y7, Y8;

  wire grad_valid;
  wire [21:0] grad_cur_line_data;

  reg valid_s_d1;
  reg grad_dx_sign;
  reg [9:0] grad_dx_abs;
  reg grad_dy_sign;
  reg [9:0] grad_dy_abs;

  reg [1:0] mode;
  reg [9:0] dividend, divisor;

  wire div_valid;
  wire [23:0] div_data;

  reg [2*N-1:0] mode_shift;
  wire mode_s;
  reg [72*N-1:0] Y_shift;
  wire [7:0] Y0_s, Y1_s, Y2_s;
  wire [7:0] Y3_s, Y4_s, Y5_s;
  wire [7:0] Y6_s, Y7_s, Y8_s;

  reg div_valid_d1;
  reg [7:0] grad1, grad2, grad3, grad4;
  reg [7:0] weight;
  reg [8:0] one_sub_weight;
  reg [7:0] Y4_s_d1;

  reg div_valid_d2;
  reg [15:0] grad1_m, grad2_m;
  reg [16:0] grad3_m, grad4_m;
  reg [7:0] Y4_s_d2;

  wire [16:0] t1, t2;

  /行视频数据缓存
  image_line_buffer u_image_line_buffer (
      .clk             (clk),
      .reset           (reset),
      .img_width       (img_width),
      .img_height      (img_height),
      .valid_i         (valid_i),
      .img_data_i      (grad_mag),
      .valid_o         (valid),
      .prev_line_data_o(prev_line_data),
      .cur_line_data_o (cur_line_data),
      .next_line_data_o(next_line_data)
  );

  always @(posedge clk) begin
    if (reset) begin
      valid_d1 <= 0;
      prev_line_data_d1 <= 0;
      cur_line_data_d1 <= 0;
      next_line_data_d1 <= 0;
      prev_line_data_d2 <= 0;
      cur_line_data_d2 <= 0;
      next_line_data_d2 <= 0;
    end else begin
      valid_d1 <= valid;
      prev_line_data_d1 <= prev_line_data;
      cur_line_data_d1 <= cur_line_data;
      next_line_data_d1 <= next_line_data;
      prev_line_data_d2 <= prev_line_data_d1;
      cur_line_data_d2 <= cur_line_data_d1;
      next_line_data_d2 <= next_line_data_d1;
    end
  end

  //边界数据处理
  always @(posedge clk) begin
    if (reset) begin
      x_cnt <= 0;
    end else begin
      x_cnt <= valid_d1 ? ((x_cnt == img_width - 1) ? 0 : x_cnt + 1) : x_cnt;
    end
  end

  always @(posedge clk) begin
    if (reset) begin
      valid_s <= 0;
      prev_line_data_d2_s <= 0;
      cur_line_data_d2_s <= 0;
      next_line_data_d2_s <= 0;
      prev_line_data_d1_s <= 0;
      cur_line_data_d1_s <= 0;
      next_line_data_d1_s <= 0;
      prev_line_data_s <= 0;
      cur_line_data_s <= 0;
      next_line_data_s <= 0;
    end else begin
      valid_s <= valid_d1;
      prev_line_data_d1_s <= prev_line_data_d1;
      cur_line_data_d1_s <= cur_line_data_d1;
      next_line_data_d1_s <= next_line_data_d1;
      if (x_cnt == 0) begin
        prev_line_data_d2_s <= prev_line_data_d1;
        cur_line_data_d2_s <= cur_line_data_d1;
        next_line_data_d2_s <= next_line_data_d1;
        prev_line_data_s <= prev_line_data;
        cur_line_data_s <= cur_line_data;
        next_line_data_s <= next_line_data;
      end
      if (x_cnt == img_width - 1) begin
        prev_line_data_d2_s <= prev_line_data_d2;
        cur_line_data_d2_s <= cur_line_data_d2;
        next_line_data_d2_s <= next_line_data_d2;
        prev_line_data_s <= prev_line_data_d1;
        cur_line_data_s <= cur_line_data_d1;
        next_line_data_s <= next_line_data_d1;
      end else begin
        prev_line_data_d2_s <= prev_line_data_d2;
        cur_line_data_d2_s <= cur_line_data_d2;
        next_line_data_d2_s <= next_line_data_d2;
        prev_line_data_s <= prev_line_data;
        cur_line_data_s <= cur_line_data;
        next_line_data_s <= next_line_data;
      end
    end
  end

  assign Y0 = prev_line_data_d2_s;
  assign Y1 = cur_line_data_d2_s;
  assign Y2 = next_line_data_d2_s;
  assign Y3 = prev_line_data_d1_s;
  assign Y4 = cur_line_data_d1_s;
  assign Y5 = next_line_data_d1_s;
  assign Y6 = prev_line_data_s;
  assign Y7 = cur_line_data_s;
  assign Y8 = next_line_data_s;

  /grad_dx和grad_dy行数据缓存
  image_line_buffer #(
      .W(21)
  ) u_image_grad_line_buffer (
      .clk             (clk),
      .reset           (reset),
      .img_width       (img_width),
      .img_height      (img_height),
      .valid_i         (valid_i),
      .img_data_i      ({grad_dx, grad_dy}),
      .valid_o         (grad_valid),
      .prev_line_data_o(),
      .cur_line_data_o (grad_cur_line_data),
      .next_line_data_o()
  );


  /非极大值限制计算
  //计算grad_dx,grad_dy绝对值
  always @(posedge clk) begin
    if (reset) begin
      {grad_dx_sign, grad_dx_abs} <= 0;
      {grad_dy_sign, grad_dy_abs} <= 0;
    end else begin
      grad_dx_sign <= grad_cur_line_data[21];
      grad_dx_abs  <= grad_cur_line_data[20:11];
      grad_dy_sign <= grad_cur_line_data[10];
      grad_dy_abs  <= grad_cur_line_data[9:0];
    end
  end

  //计算模式
  always @(posedge clk) begin
    if (reset) begin
      mode <= 0;
      {dividend, divisor} <= 0;
    end else begin
      if (grad_dx_abs > grad_dy_abs) begin
        mode <= (grad_dx_sign ^ grad_dy_sign) ? 0 : 1;
        dividend <= grad_dy_abs;
        divisor <= grad_dx_abs;
      end else begin
        mode <= (grad_dx_sign ^ grad_dy_sign) ? 2 : 3;
        dividend <= grad_dx_abs;
        divisor <= grad_dy_abs;
      end
    end
  end

  //除法计算
  div_gen_10x10 u_div_gen_10x10 (
      .aclk                  (clk),               // input wire aclk
      .s_axis_divisor_tvalid (valid_s),           // input wire s_axis_divisor_tvalid
      .s_axis_divisor_tdata  ({6'b0, divisor}),   // input wire [15 : 0] s_axis_divisor_tdata
      .s_axis_dividend_tvalid(valid_s),           // input wire s_axis_dividend_tvalid
      .s_axis_dividend_tdata ({6'b0, dividend}),  // input wire [15 : 0] s_axis_dividend_tdata
      .m_axis_dout_tvalid    (div_valid),         // output wire m_axis_dout_tvalid
      .m_axis_dout_tdata     (div_data)           // output wire [23 : 0] m_axis_dout_tdata
  );

  //同步延时
  always @(posedge clk) begin
    if (reset) begin
      mode_shift <= 0;
      Y_shift <= 0;
    end else begin
      mode_shift <= {mode_shift, mode};
      Y_shift <= {Y_shift, Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8};
    end
  end

  assign mode_s = mode_shift[2*N-1:2*(N-1)];
  assign {Y0_s, Y1_s, Y2_s, Y3_s, Y4_s, Y5_s, Y6_s, Y7_s, Y8_s} = Y_shift[72*N-1:72*(N-1)];

  //计算插值系数、插值数据
  always @(posedge clk) begin
    if (reset) begin
      div_valid_d1 <= 0;
      weight <= 0;
      one_sub_weight <= 0;
      Y4_s_d1 <= 0;
      {grad1, grad2, grad3, grad4} <= 0;
    end else begin
      div_valid_d1 <= div_valid;
      weight <= div_data[7:0];
      one_sub_weight <= 256 - div_data[7:0];
      Y4_s_d1 <= Y4_s;
      case (mode_s)
        0: begin
          grad1 <= Y7_s;
          grad2 <= Y1_s;
          grad3 <= Y8_s;
          grad4 <= Y0_s;
        end
        1: begin
          grad1 <= Y7_s;
          grad2 <= Y1_s;
          grad3 <= Y6_s;
          grad4 <= Y2_s;
        end
        2: begin
          grad1 <= Y5_s;
          grad2 <= Y3_s;
          grad3 <= Y8_s;
          grad4 <= Y0_s;
        end
        3: begin
          grad1 <= Y5_s;
          grad2 <= Y3_s;
          grad3 <= Y6_s;
          grad4 <= Y2_s;
        end
      endcase
    end
  end

  //计算极值t1\t2
  always @(posedge clk) begin
    if (reset) begin
      div_valid_d2 <= 0;
      Y4_s_d2 <= 0;
      {grad1_m, grad2_m, grad3_m, grad4_m} <= 0;
    end else begin
      div_valid_d2 <= div_valid_d1;
      Y4_s_d2 <= Y4_s_d1;
      grad1_m <= grad1 * weight;
      grad2_m <= grad2 * weight;
      grad3_m <= grad3 * one_sub_weight;
      grad4_m <= grad4 * one_sub_weight;
    end
  end

  assign t1 = grad1_m + grad3_m;
  assign t2 = grad2_m + grad4_m;

  //超过极值后,赋值为0
  always @(posedge clk) begin
    if (reset) begin
      valid_o <= 0;
      img_data_o <= 0;
    end else if (div_valid_d2) begin
      valid_o <= 1;
      img_data_o <= ({1'b0, Y4_s_d2} > t1[16:8]) && ({1'b0, Y4_s_d2} > t2[16:8]) ? Y4_s_d2 : 0;
    end else begin
      valid_o <= 0;
    end
  end

endmodule

 

 

8 双阈值代码

`timescale 1ns / 1ps
//双阈值



module double_threshold (
    input clk,
    input reset,

    input [10:0] img_width,
    input [ 9:0] img_height,
    input [ 7:0] low_threshold,
    input [ 7:0] high_threshold,

    input valid_i,
    input [7:0] img_data_i,

    output reg valid_o,
    output reg [7:0] img_data_o
);

  //常量声明
  localparam MODE = 1;  //0表示彩色图像输出,1表示灰度图像输出

  //变量声明
  wire valid;
  wire [7:0] prev_line_data;
  wire [7:0] cur_line_data;
  wire [7:0] next_line_data;
  reg valid_d1;
  reg [7:0] prev_line_data_d1;
  reg [7:0] cur_line_data_d1;
  reg [7:0] next_line_data_d1;

  reg [7:0] prev_line_data_d2;
  reg [7:0] cur_line_data_d2;
  reg [7:0] next_line_data_d2;
  reg [7:0] x_cnt;

  reg valid_s;
  reg [7:0] prev_line_data_d2_s;
  reg [7:0] cur_line_data_d2_s;
  reg [7:0] next_line_data_d2_s;
  reg [7:0] prev_line_data_d1_s;
  reg [7:0] cur_line_data_d1_s;
  reg [7:0] next_line_data_d1_s;
  reg [7:0] prev_line_data_s;
  reg [7:0] cur_line_data_s;
  reg [7:0] next_line_data_s;

  wire [7:0] Y0, Y1, Y2;
  wire [7:0] Y3, Y4, Y5;
  wire [7:0] Y6, Y7, Y8;

  image_line_buffer u_image_line_buffer (
      .clk             (clk),
      .reset           (reset),
      .img_width       (img_width),
      .img_height      (img_height),
      .valid_i         (valid_i),
      .img_data_i      (img_data_i),
      .valid_o         (valid),
      .prev_line_data_o(prev_line_data),
      .cur_line_data_o (cur_line_data),
      .next_line_data_o(next_line_data)
  );

  always @(posedge clk) begin
    if (reset) begin
      valid_d1 <= 0;
      prev_line_data_d1 <= 0;
      cur_line_data_d1 <= 0;
      next_line_data_d1 <= 0;
      prev_line_data_d2 <= 0;
      cur_line_data_d2 <= 0;
      next_line_data_d2 <= 0;
    end else begin
      valid_d1 <= valid;
      prev_line_data_d1 <= prev_line_data;
      cur_line_data_d1 <= cur_line_data;
      next_line_data_d1 <= next_line_data;
      prev_line_data_d2 <= prev_line_data_d1;
      cur_line_data_d2 <= cur_line_data_d1;
      next_line_data_d2 <= next_line_data_d1;
    end
  end

  //边界数据处理
  always @(posedge clk) begin
    if (reset) begin
      x_cnt <= 0;
    end else begin
      x_cnt <= valid_d1 ? ((x_cnt == img_width - 1) ? 0 : x_cnt + 1) : x_cnt;
    end
  end

  always @(posedge clk) begin
    if (reset) begin
      valid_s <= 0;
      prev_line_data_d2_s <= 0;
      cur_line_data_d2_s <= 0;
      next_line_data_d2_s <= 0;
      prev_line_data_d1_s <= 0;
      cur_line_data_d1_s <= 0;
      next_line_data_d1_s <= 0;
      prev_line_data_s <= 0;
      cur_line_data_s <= 0;
      next_line_data_s <= 0;
    end else begin
      valid_s <= valid_d1;
      prev_line_data_d1_s <= prev_line_data_d1;
      cur_line_data_d1_s <= cur_line_data_d1;
      next_line_data_d1_s <= next_line_data_d1;
      if (x_cnt == 0) begin
        prev_line_data_d2_s <= prev_line_data_d1;
        cur_line_data_d2_s <= cur_line_data_d1;
        next_line_data_d2_s <= next_line_data_d1;
        prev_line_data_s <= prev_line_data;
        cur_line_data_s <= cur_line_data;
        next_line_data_s <= next_line_data;
      end
      if (x_cnt == img_width - 1) begin
        prev_line_data_d2_s <= prev_line_data_d2;
        cur_line_data_d2_s <= cur_line_data_d2;
        next_line_data_d2_s <= next_line_data_d2;
        prev_line_data_s <= prev_line_data_d1;
        cur_line_data_s <= cur_line_data_d1;
        next_line_data_s <= next_line_data_d1;
      end else begin
        prev_line_data_d2_s <= prev_line_data_d2;
        cur_line_data_d2_s <= cur_line_data_d2;
        next_line_data_d2_s <= next_line_data_d2;
        prev_line_data_s <= prev_line_data;
        cur_line_data_s <= cur_line_data;
        next_line_data_s <= next_line_data;
      end
    end
  end

  assign Y0 = prev_line_data_d2_s;
  assign Y1 = cur_line_data_d2_s;
  assign Y2 = next_line_data_d2_s;
  assign Y3 = prev_line_data_d1_s;
  assign Y4 = cur_line_data_d1_s;
  assign Y5 = next_line_data_d1_s;
  assign Y6 = prev_line_data_s;
  assign Y7 = cur_line_data_s;
  assign Y8 = next_line_data_s;


  always @(posedge clk) begin
    if (reset) begin
      valid_o <= 0;
      img_data_o <= 0;
    end else if (valid_s) begin
      valid_o <= 1;
      if (Y4 < low_threshold) img_data_o <= 0;
      else if((Y0 > high_threshold)||(Y1 > high_threshold)||(Y2 > high_threshold)||
                (Y3 > high_threshold)||(Y4 > high_threshold)||(Y5 > high_threshold)||
                (Y6 > high_threshold)||(Y7 > high_threshold)||(Y8 > high_threshold))
        img_data_o <= 255;
      else img_data_o <= 0;
    end else begin
      valid_o <= 0;
    end
  end

endmodule

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

uniapp 中引入第三方组件后,更改组件的样式 -使用/deep/不生效

在我们使用Vue搭建项目的时候&#xff0c;我们经常会用到一些UI框架&#xff0c;如Element&#xff0c;iView&#xff0c;但是有时候我们又想去修改Ul框架的样式&#xff0c;当我们修改样式失败的时候&#xff0c;可以尝试一下/deep/&#xff0c;亲测有效。 那失败的原因是什么…

基于DBO-CNN-BiLSTM数据回归预测(多输入单输出),蜣螂优化算法优化CNN-BiLSTM-附代码

基于DBO-CNN-BiLSTM的数据回归预测是一种综合利用了深度学习中的多种技术的方法&#xff0c;包括卷积神经网络&#xff08;CNN&#xff09;、双向长短期记忆网络&#xff08;BiLSTM&#xff09;和注意力机制&#xff08;Attention&#xff09;。蜣螂优化算法用于优化CNN-BiLSTM…

揭秘’在家答答题,无需经验、无论男女、单号轻松日产200+的一个玩法

项目简介 公众号&#xff1a;老A程序站 这个项目是人人可参与的&#xff0c;无需支付任何费用&#xff0c;只需投入时间即可。每天的任务主要是回答问题。 项目 地 址 &#xff1a; laoa1.cn/1457.html 如果遇到不会的问题&#xff0c;可以直接使用百度进行搜索。我们通过…

【明道云】如何让用户可以新增但不能修改记录

【背景】 遇到一个需求场景&#xff0c;用户希望新增数据后锁住数据不让更改。 【分析】 在设计表单时直接将字段设置只读是不行的。字段设置只读将会直接让界面上此字段的前端组件不可编辑。包括新增时也无法填入。显然是不符合需求的。 需要既能新增&#xff0c;新增后又不…

5.6 物联网RK3399项目开发实录-Android开发之U-Boot 编译及使用(wulianjishu666)

物联网入门到项目实干案例下载&#xff1a; https://pan.baidu.com/s/1fHRxXBqRKTPvXKFOQsP80Q?pwdh5ug --------------------------------------------------------------------------------------------------------------------------------- U-Boot 使用 前言 RK U-B…

在香港服务器搭网站速度怎么样?

在香港服务器搭网站速度怎么样&#xff1f;一般要看用户所在地理位置&#xff0c;如果用户距离香港服务器较远&#xff0c;网络延迟会增加&#xff0c;导致加载速度变慢。 面对海外地区用户&#xff0c;香港作为亚洲连接海外的网络中转枢纽&#xff0c;多条国际海底电缆&#…

编译原理知识点整理

第一章 绪论 计算机语言发展历程 第一代语言&#xff1a;机器语言第二代语言&#xff1a;汇编语言第三代语言&#xff1a;高级语言(如C&#xff0c;C&#xff0c;Java等)第四代语言&#xff1a;极高级领域语言(如SQL)第五代语言&#xff1a;可视化配置语言第六代语言&#xff…

抢先看!界面控件DevExpress WPF 2024产品路线图预览(一)

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 本文将介绍2024年Dev…

事件穿透效果

讲述一下事件穿透的需求&#xff0c;大家可以根据实际情况来考虑是否采用这种方式来制作页面&#xff0c;&#xff08;项目中遇到了底部是地图&#xff0c;两侧面板&#xff0c;但是UI在设计的时候为了好看&#xff0c;会有很大的遮罩阴影部分&#xff0c;如果按照时间制作会导…

图书推荐|Bootstrap 5从入门到精通:视频教学版

示例源码、PPT课件、同步教学视频、作者微信答疑、教学大纲、其他丰富的教学资源 本书内容 《Bootstrap 5从入门到精通&#xff1a;视频教学版》结合示例和综合项目的演练&#xff0c;详细讲解Bootstrap开发技术&#xff0c;使读者快速掌握Bootstrap开发技能&#xff0c;提高使…

[SpringCloud] Feign Client 的创建 (二) (五)

文章目录 1.自动配置FeignAutoConfiguration2.生成 Feign Client2.1 从Feign Client子容器获取组件2.2 Feign Client子容器的创建2.3 构建Feign Client实例 1.自动配置FeignAutoConfiguration spring-cloud-starter-openfeign 包含了 spring-cloud-openfeign-core FeignAutoCo…

CSS实现小车旅行动画实现

小车旅行动画实现 效果展示 CSS 知识点 灵活使用 background 属性下的 repeating-linear-gradient 实现路面效果灵活运用 animation 属性与 transform 实现小车和其他元素的动画效果 动画场景分析 从效果图可以看出需要实现此动画的话&#xff0c;需要position属性控制元素…

机器学习(三)

神经网络: 神经网络是由具有适应性的简单单元组成的广泛并行互连的网络&#xff0c;它的组织能够模拟生物神经系统对真实世界物体所作出的交互反应。 f为激活(响应)函数: 理想激活函数是阶跃函数&#xff0c;0表示抑制神经元而1表示激活神经元。 多层前馈网络结构: BP(误差逆…

微服务demo(二)nacos服务注册与集中配置

环境&#xff1a;nacos1.3.0 一、服务注册 1、pom&#xff1a; 移步spring官网https://spring.io&#xff0c;查看集成Nacos所需依赖 找到对应版本点击进入查看集成说明 然后再里面找到集成配置样例&#xff0c;这里只截一张&#xff0c;其他集成内容继续向下找 我的&#x…

【Python】python+requests+excel+unittest+ddt实现接口自动化实例

目录 测试需求实现思路框架代码实例1. 环境准备和配置文件2. Excel接口数据及测试结果3. API封装4. 读取Excel数据5. 测试用例6. 日志和配置文件处理7. HTMLTestRunner生成可视化的html报告8. 报告通过飞书/邮件发送报告通过飞书发送报告通过邮件发送9. 入口函数10. 飞书Webhoo…

Day46:WEB攻防-注入工具SQLMAPTamper编写指纹修改高权限操作目录架构

目录 数据猜解-库表列数据&字典 权限操作-文件&命令&交互式 提交方法-POST&HEAD&JSON 绕过模块-Tamper脚本-使用&开发 分析拓展-代理&调试&指纹&风险&等级 知识点&#xff1a; 1、注入工具-SQLMAP-常规猜解&字典配置 2、注入…

Nagios工具

一 nagios 相关概念 Nagios 是一款开源的免费网络监视工具&#xff0c;能有效监控 Windows、Linux 和 Unix 的主机状态&#xff0c;交换机路由器等网络设置&#xff0c;打印机等。在系统或服务状态异常时发出邮件或短信报警第 一时间通知网站运维人员&#xff0c;在状态恢复后…

33.HarmonyOS App(JAVA)鸿蒙系统app数据库增删改查

33.HarmonyOS App(JAVA)鸿蒙系统app数据库增删改查 关系数据库 关系对象数据库&#xff08;ORM&#xff09; 应用偏好数据库 分布式数据库 关系型数据库&#xff08;Relational Database&#xff0c;RDB&#xff09;是一种基于关系模型来管理数据的数据库。HarmonyOS关系型…

构建图书管理系统:使用Python的Tkinter和PIL模块

本博客将介绍如何使用Python中的Tkinter库和PIL&#xff08;Python Imaging Library&#xff09;模块构建一个简单的图书管理系统。图书管理系统是一个常见的应用程序&#xff0c;用于管理图书馆或个人收藏的图书信息。我们将逐步展示系统的功能&#xff0c;包括添加图书、查询…

【机器学习】包裹式特征选择之序列后向选择法

&#x1f388;个人主页&#xff1a;豌豆射手^ &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;机器学习 &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff0c;让我们共同学习、交流进…