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*Bparameter 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;generateif (MODE) beginreg 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 = 171always @(posedge clk) beginif (reset) beginvalid_d1 <= 'b0;RGB_avr <= 'b0;end else beginvalid_d1 <= valid_i;RGB_avr <= R + G + B;endend//最大值不可能超过255*3*171 = 17'd130815always @(posedge clk) beginRGB_avr_m <= RGB_avr * 8'd171;endalways @(posedge clk) beginif (reset) beginvalid_d2 <= 'b0;end else beginvalid_d2 <= valid_d1;endend//最大值不可能超过255always @(posedge clk) beginif (reset) beginvalid_d3 <= 'b0;RGB_new <= 'b0;end else beginvalid_d3 <= valid_d2;RGB_new <= RGB_avr_m[16:9];endendassign 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) beginY_R_m <= R * C0;Y_G_m <= G * C1;Y_B_m <= B * C2;endalways @(posedge clk) beginif (reset) beginvalid_d1 <= 0;end else beginvalid_d1 <= valid_i;endendalways @(posedge clk) beginif (reset) beginY_s <= 0;valid_d2 <= 0;end else beginif (valid_d1) beginY_s <= Y_R_m + Y_G_m + Y_B_m;endvalid_d2 <= valid_d1;endendalways @(posedge clk) beginif (reset) beginY <= 0;valid_d3 <= 0;end else beginif (valid_d2) beginY <= Y_s[17:10];endvalid_d3 <= valid_d2;endendassign valid_o = valid_d3;assign img_data_o = Y;endendgenerateendmodule
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即可generatefor (i = 1; i < N; i = i + 1) begin : lbline_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]));endendgenerate//模式1,按照上一行、当前行、下一行输出//特殊情况,可根据需求设定,是复制还是给0//第1个行缓存,是整个画面的第1行时, 上一行数据不存在,复制第1个行缓存或者直接为0输出//第1个行缓存,是整个画面的最后1行时,下一行数据不存在,复制第1个行缓存输出always @(posedge clk) beginif (reset) beginfor (j = 0; j < 3; j = j + 1) ch_data[j] <= 0;end else if (valid[N-2]) beginch_data[1] <= data[1];if (out_line_cnt == 0) beginch_data[2] <= 0;ch_data[0] <= data[0];end else if (out_line_cnt == img_height - 1) beginch_data[2] <= data[2];ch_data[0] <= 0;end else beginch_data[2] <= data[2];ch_data[0] <= data[0];endendendalways @(posedge clk) beginif (reset) beginch_valid <= 0;out_data_cnt <= 0;out_line_cnt <= 0;end else beginch_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;endend//单路输出always @(posedge clk) beginif (reset) beginvalid_o <= 0;prev_line_data_o <= 0;cur_line_data_o <= 0;next_line_data_o <= 0;end else beginvalid_o <= ch_valid;prev_line_data_o <= ch_data[2];cur_line_data_o <= ch_data[1];next_line_data_o <= ch_data[0];endendendmodule
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) beginif (reset) beginwr_data_cnt <= 0;end else beginwr_data_cnt <= valid_i && (wr_data_cnt < img_width) ? (wr_data_cnt + 1'b1) : wr_data_cnt;endend//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;generateif (W == 8) beginfifo_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 beginfifo_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);endendgenerateendmodule
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) beginif (reset) beginvalid_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 beginvalid_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;endend//边界数据处理always @(posedge clk) beginif (reset) beginx_cnt <= 0;end else beginx_cnt <= valid_d1 ? ((x_cnt == img_width - 1) ? 0 : x_cnt + 1) : x_cnt;endendalways @(posedge clk) beginif (reset) beginvalid_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 beginvalid_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) beginprev_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;endif (x_cnt == img_width - 1) beginprev_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 beginprev_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;endendendassign 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) beginif (reset) beginvalid_s_d1 <= 0;{Y_sum0, Y_sum1, Y_sum2} <= 0;end else if (valid_s) beginvalid_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 + 1always @(posedge clk) beginif (reset) beginvalid_s_d2 <= 0;Y_sum <= 0;end else if (valid_s_d1) beginvalid_s_d2 <= 1;Y_sum <= Y_sum0 + Y_sum1 + Y_sum2;end else valid_s_d2 <= 0;endalways @(posedge clk) beginif (reset) beginvalid_o <= 0;img_data_o <= 0;end else if (valid_s_d2) beginvalid_o <= 1;img_data_o <= Y_sum[11:4];end else beginvalid_o <= 0;endendendmodule
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) beginif (reset) beginvalid_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 beginvalid_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;endend//边界数据处理always @(posedge clk) beginif (reset) beginx_cnt <= 0;end else beginx_cnt <= valid_d1 ? ((x_cnt == img_width - 1) ? 0 : x_cnt + 1) : x_cnt;endendalways @(posedge clk) beginif (reset) beginvalid_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 beginvalid_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) beginprev_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;endif (x_cnt == img_width - 1) beginprev_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 beginprev_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;endendendassign 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) beginif (reset) beginvalid_s_d1 <= 0;{Gx_Y, Gy_Y} <= 0;{Gx_Y_sign, Gy_Y_sign} <= 0;end else if (valid_s) beginvalid_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) beginif (reset) beginvalid_s_d2 <= 0;Gx_Y_square <= 0;Gy_Y_square <= 0;end else beginvalid_s_d2 <= valid_s_d1;Gx_Y_square <= Gx_Y * Gx_Y;Gy_Y_square <= Gy_Y * Gy_Y;endendassign 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) beginif (reset) beginGx_Y_sign_shift <= 0;Gx_Y_shift <= 0;Gy_Y_sign_shift <= 0;Gy_Y_shift <= 0;end else beginGx_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};endendalways @(posedge clk) beginif (reset) beginvalid_o <= 0;grad_mag <= 0;grad_dx <= 0;grad_dy <= 0;end else if (valid_sqr) beginvalid_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 beginvalid_o <= 0;endendendmodule
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) beginif (reset) beginvalid_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 beginvalid_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;endend//边界数据处理always @(posedge clk) beginif (reset) beginx_cnt <= 0;end else beginx_cnt <= valid_d1 ? ((x_cnt == img_width - 1) ? 0 : x_cnt + 1) : x_cnt;endendalways @(posedge clk) beginif (reset) beginvalid_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 beginvalid_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) beginprev_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;endif (x_cnt == img_width - 1) beginprev_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 beginprev_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;endendendassign 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) beginif (reset) begin{grad_dx_sign, grad_dx_abs} <= 0;{grad_dy_sign, grad_dy_abs} <= 0;end else begingrad_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];endend//计算模式always @(posedge clk) beginif (reset) beginmode <= 0;{dividend, divisor} <= 0;end else beginif (grad_dx_abs > grad_dy_abs) beginmode <= (grad_dx_sign ^ grad_dy_sign) ? 0 : 1;dividend <= grad_dy_abs;divisor <= grad_dx_abs;end else beginmode <= (grad_dx_sign ^ grad_dy_sign) ? 2 : 3;dividend <= grad_dx_abs;divisor <= grad_dy_abs;endendend//除法计算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) beginif (reset) beginmode_shift <= 0;Y_shift <= 0;end else beginmode_shift <= {mode_shift, mode};Y_shift <= {Y_shift, Y0, Y1, Y2, Y3, Y4, Y5, Y6, Y7, Y8};endendassign 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) beginif (reset) begindiv_valid_d1 <= 0;weight <= 0;one_sub_weight <= 0;Y4_s_d1 <= 0;{grad1, grad2, grad3, grad4} <= 0;end else begindiv_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: begingrad1 <= Y7_s;grad2 <= Y1_s;grad3 <= Y8_s;grad4 <= Y0_s;end1: begingrad1 <= Y7_s;grad2 <= Y1_s;grad3 <= Y6_s;grad4 <= Y2_s;end2: begingrad1 <= Y5_s;grad2 <= Y3_s;grad3 <= Y8_s;grad4 <= Y0_s;end3: begingrad1 <= Y5_s;grad2 <= Y3_s;grad3 <= Y6_s;grad4 <= Y2_s;endendcaseendend//计算极值t1\t2always @(posedge clk) beginif (reset) begindiv_valid_d2 <= 0;Y4_s_d2 <= 0;{grad1_m, grad2_m, grad3_m, grad4_m} <= 0;end else begindiv_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;endendassign t1 = grad1_m + grad3_m;assign t2 = grad2_m + grad4_m;//超过极值后,赋值为0always @(posedge clk) beginif (reset) beginvalid_o <= 0;img_data_o <= 0;end else if (div_valid_d2) beginvalid_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 beginvalid_o <= 0;endendendmodule
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) beginif (reset) beginvalid_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 beginvalid_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;endend//边界数据处理always @(posedge clk) beginif (reset) beginx_cnt <= 0;end else beginx_cnt <= valid_d1 ? ((x_cnt == img_width - 1) ? 0 : x_cnt + 1) : x_cnt;endendalways @(posedge clk) beginif (reset) beginvalid_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 beginvalid_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) beginprev_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;endif (x_cnt == img_width - 1) beginprev_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 beginprev_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;endendendassign 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) beginif (reset) beginvalid_o <= 0;img_data_o <= 0;end else if (valid_s) beginvalid_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 beginvalid_o <= 0;endendendmodule
相关文章:

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 va…...

2024.3.28学习笔记
今日学习韩顺平java0200_韩顺平Java_对象机制练习_哔哩哔哩_bilibili 今日学习p286-p294 继承 继承可以解决代码复用,让我们的编程更加靠近人类思维,当多个类存在相同的属性和方法时,可以从这些类中抽象出父类,在父类中定义这些…...

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

寄主机显示器被快递搞坏了怎么办?怎么破?
大家好,我是平泽裕也。 最近,我在社区里看到很多关于开学后弟弟寄来的电脑显示器被快递损坏的帖子。 看到它真的让我感到难过。 如果有人的数码产品被快递损坏了,我会伤心很久。 那么今天就跟大家聊聊寄快递的一些小技巧。 作为一名曾经的…...
python爬虫-bs4
python爬虫-bs4 目录 python爬虫-bs4说明安装导入 基础用法解析对象获取文本Tag对象获取HTML中的标签内容find参数获取标签属性获取所有标签获取标签名嵌套获取子节点和父节点 说明 BeautifulSoup 是一个HTML/XML的解析器,主要的功能也是如何解析和提取 HTML/XML 数…...

SpringBoot学习之ElasticSearch下载安装和启动(Mac版)(三十一)
本篇是接上一篇Windows版本,需要Windows版本的请看上一篇,这里我们继续把Elasticsearch简称为ES,以下都是这样。 一、下载 登录Elasticsearch官网,地址是:Download Elasticsearch | Elastic 进入以后,网页会自动识别系统给你提示Mac版本的下载链接按钮 二、安装 下载…...

OC对象 - Block解决循环引用
文章目录 OC对象 - Block解决循环引用前言1. 循环引用示例1.1 分析 2. 解决思路3. ARC下3.1 __weak3.2 __unsafe_unretained3.3 __block 4. MRC下4.1 __unsafe_unretain....4.1 __block 5. 总结5.1 ARC下5.2 MRC下 OC对象 - Block解决循环引用 前言 本章将会通过一个循环引用…...

Java设计模式之装饰器模式
装饰器模式是一种结构型设计模式,它允许动态地将责任附加到对象上。装饰器模式是通过创建一个包装对象,也就是装饰器,来包裹真实对象,从而实现对真实对象的功能增强。装饰器模式可以在不修改原有对象的情况下,动态地添…...
Java基础知识总结(25)
代理模式 什么是代理模式? 代理模式是指,为其他对象提供一种代理以控制这个对象的访问。一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户和目标对象之间起到中介的作用。换句话说,代理模式,是在不修…...
Vue3 实现基于token 用户登录
前后端分离情况下,实现的大致思路 1 第一次登录的时候,前端调用后端的登录接口,发送用户名与密码 2 后端收到请求,验证用户名和密码,验证成功 给前端返回一个token 3 前段拿到token 将token 存储进localStorage 和…...

在word中显示Euclid Math One公式的问题及解决(latex公式,无需插件)
问题:想要在word中显示形如latex中的花体字母 网上大多解决办法是安装Euclid Math One。安装后发现单独的符号插入可行,但是公式中选择该字体时依然显示默认字体。 解决办法:插入公式后,勾选左上角的latex 在公式块中键入latex代码…...

江协科技STM32:按键控制LED光敏传感器控制蜂鸣器
按键控制LED LED模块 左上角PA0用上拉输入模式,如果此时引脚悬空,PA0就是高电平,这种方式下,按下按键,引脚为低电平,松下按键,引脚为高电平 右上角PA0,把上拉电阻想象成弹簧 当按键…...
最佳矢量绘图设计软件Sketch for Mac v99.5 最新中文激活版
Sketch for Mac是一款功能强大的矢量绘图软件,它提供了简单易用的界面和丰富的工具,让用户能够轻松创建精美的设计作品。 软件下载:Sketch for Mac v99.5 最新中文激活版 Sketch具有直观的布局和智能的工具,使得设计师能够快速实现…...

【IntelliJ IDEA】运行测试报错解决方案(附图)
IntelliJ IDEA 版本 2023.3.4 (Ultimate Edition) 测试报错信息 命令行过长。 通过 JAR 清单或通过类路径文件缩短命令行,然后重新运行 解决方案 修改运行配置,里面如果没有缩短命令行,需要再修改选项里面勾选缩短命令行让其显示&#x…...
【Kotlin】List、Set、Map简介
1 List Java 的 List、Set、Map 介绍见 → Java容器及其常用方法汇总。 1.1 创建 List 1.1.1 emptyList var list emptyList<String>() // 创建空List 1.1.2 List 构造函数 var list1 List(3) { "abc" } // [abc, abc, abc] var list2 ArrayList<In…...

OpenCV 形态学处理函数
四、形态学处理(膨胀,腐蚀,开闭运算)_getstructuringelement()函数作用-CSDN博客 数字图像处理(c opencv):形态学图像处理-morphologyEx函数实现腐蚀膨胀、开闭运算、击中-击不中变换、形态学梯度、顶帽黑帽变换 - 知乎…...
互联网摸鱼日报(2024-03-27)
互联网摸鱼日报(2024-03-27) 36氪新闻 谈“肉”色变,预制菜“顶流”要完? 欧美监管机构出重拳,苹果和谷歌都要被拆分了吗? 为什么产品经理的薪资待遇,这么高? AI PC:一场浩荡的革命 二氧化…...

2014年认证杯SPSSPRO杯数学建模B题(第二阶段)位图的处理算法全过程文档及程序
2014年认证杯SPSSPRO杯数学建模 B题 位图的处理算法 原题再现: 图形(或图像)在计算机里主要有两种存储和表示方法。矢量图是使用点、直线或多边形等基于数学方程的几何对象来描述图形,位图则使用像素来描述图像。一般来说&#…...

C++基本语法
C是如何工作的 文章目录 C是如何工作的1、新建Hello World工程1.1使用Visual Studio新建项目1.2 HelloWorld1.2.1 命名空间1.2.2 输出输出 1.3 注释1.4 函数1.4.1 使用有返回的函数1.4.2 自定义函数 1、新建Hello World工程 1.1使用Visual Studio新建项目 按照下面的图片&…...

Node Sass does not yet support your current environment
项目运行时报错:Node Sass does not yet support your current environment 原因是node版本过高。 解决办法: 使用nvm管理node版本,(如何安装nvm?请点击跳转) 具体步骤如下: 1.查看当前node…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

19c补丁后oracle属主变化,导致不能识别磁盘组
补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录
ASP.NET Core 是一个跨平台的开源框架,用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录,以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...
Oracle查询表空间大小
1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...
Qt Widget类解析与代码注释
#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码,写上注释 当然可以!这段代码是 Qt …...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

转转集团旗下首家二手多品类循环仓店“超级转转”开业
6月9日,国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解,“超级…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...