使用芯片为ZYNQ—7020,基于野火FPGA ZYNQ开发板

使用芯片为ZYNQ—7020,基于野火FPGA ZYNQ开发板

肤色模型简介

YCrCb也称为YUV,主要用于优化彩色视频信号的传输。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。其中,Cr反映了RGB输入信号红色部分与RGB信号亮度值之间的差异。而Cb反映的是RGB输入信号蓝色部分与RGB信号亮度值之间的差异。
  肤色检测 77<=Cb<=127 133<=Cr<=173 可以认为为肤色

MATLAB实现

clear all; close all; clc;

% -------------------------------------------------------------------------
% Read PC image to Matlab
IMG1 = imread('../doc/1920_1080.jpg');    % 读取jpg图像
h = size(IMG1,1);         % 读取图像高度
w = size(IMG1,2);         % 读取图像宽度
subplot(121);imshow(IMG1);title('识别前');
IMG2=rgb2ycbcr(IMG1);
% -------------------------------------------------------------------------
% Relized by user logic
% Y = ( R*76 + G*150 + B*29) >>8
% Cb = (-R*43 - G*84 + B*128 + 32768) >>8
% Cr = ( R*128 - G*107 - B*20  + 32768) >>8
IMG1 = double(IMG1);    
IMG_YCbCr = zeros(h,w,3);
Face      = zeros(h,w,3);  
for i = 1 : h
    for j = 1 : w
        IMG_YCbCr(i,j, 1) = bitshift(( IMG1(i,j,1)*76 + IMG1(i,j,2)*150 + IMG1(i,j,3)*29),-8);
        IMG_YCbCr(i,j,2) = bitshift((-IMG1(i,j,1)*43 - IMG1(i,j,2)*84 + IMG1(i,j,3)*128 + 32768),-8);
        IMG_YCbCr(i,j,3) = bitshift(( IMG1(i,j,1)*128 - IMG1(i,j,2)*107 - IMG1(i,j,3)*20 + 32768),-8);
    end
end
% 77<=Cb<=127        133<=Cr<=173 可以认为为肤色
for i = 1 : h
    for j = 1 : w
        if((77<=IMG_YCbCr(i,j,2))&&(IMG_YCbCr(i,j,2)<=127)&&(133<=IMG_YCbCr(i,j,3)&&(IMG_YCbCr(i,j,2)<=173)))
                Face(i,j,:) =  IMG1(i,j,:);
        else
                Face(i,j,:) = 0;
         end 
    end
end

% -------------------------------------------------------------------------
% Display Y Cb Cr Channel
IMG_YCbCr = uint8(IMG_YCbCr); 
Face      =uint8(Face);
subplot(122); imshow(Face);  title('识别后人脸');

识别效果
image.png

FPGA实现

基本流程:从pl端 OV5640摄像头,通过AXI HP总线将数据缓存至ps端的ddr3之中,pl端读取ps端ddr3中的摄像头数据,转换为YCbCr数据,判断肤色,输出(肤色数据输出为24’hFFFFFF,其余为0),经过两次中值滤波(买的摄像头噪点太多),一次腐蚀(只能对二值化数据操作),一次均值滤波,之后判断人脸数据位置,在原图上绘制绿色边框。(部分代码参考FPGA实现人脸检测 - 咸鱼IC - 博客园)

OV5640摄像头配置

参考小梅哥《基于HDL的FPGA逻辑设计与验证教程V3.5.2》-基于 DDR3 的串口传图帧缓存系统设计实现 配置好的或者使用其他FPGA芯片的可以跳过本章节
PLL设置

image.png
  50MHz用于LCD屏幕的显示,200MHz用于DDR3数据的读取

ZYNQ核添加

与小梅哥中,** Block Design 与 ZYNQ 核 ** 小章节一致,唯一不同的是,
image.png
在此界面处,需要同时使能ps端串口,使得ps端工作,不然只使用ps端的ddr3时,ps端并不会不工作,我们添加一个串口程序,使得ps端运行。在vitis中,选择默认模板时,选择 Hello world 模板就可以 操作如下:
image.png
在此界面选中uart0,点击变绿即可。(需要根据自己开发板串口管脚选择)
image.png
  在此界面可以配置串口参数(波特率啥的)
之后按照小梅哥的操作,生成system代码即可
image.png

pl端读取ps端ddr3 FIFO封装

参考 小梅哥FIFO 转 AXI4 接口模块设计 也可以使用我的代码,经过修改,支持乒乓操作。

摄像头寄存器配置

跳过 ** 可以使用我的代码**

肤色识别

首先将摄像头读取的数据转换成YCbCr数据,并且判断人脸数据,并输出

`timescale 1ns / 1ps
//
//例化程序示例
//  RGB888_YCbCr_Face inst_RGB888_YCbCr_Face
//    (
//    .sys_clk    (sys_clk  ), 
//    .sys_rst_n  (sys_rst_n),
//  //input------------------------------------------  
//    .rgb888     (rgb888   ),  //输入的RGB888数据 24bit
//    .rgb_de     (rgb_de   ),  //de使能信号
//    .rgb_hsync  (rgb_hsync),  //行同步信号
//    .rgb_vsync  (rgb_vsync),  //场同步信号
//  //output-----------------------------------------
//    .face_data  (face_data),  //输出的人脸数据 人脸为黑色,其余为白色 24bit
//    .face_de    (face_de  ),  //延时4个时钟周期
//    .face_hsync (face_hsync),
//    .face_vsync (face_vsync),
//     );
// Create Date: 2024/03/26 20:42:44
// Design Name: FRZ
// Module Name: RGB888_YCbCr_Face
// Description: 
//                  将RGB888数据转换成YCbCr数据,并且检测人脸 输入为RGB888数据,输出为处理后的人脸数据RGB888  人脸为黑色,其余为白色
// Dependencies: 
//                  2116815480@qq.com
//                  https://www.cnblogs.com/fangrunze
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//


module RGB888_YCbCr_Face(
    input   wire            sys_clk     ,
    input   wire            sys_rst_n   ,
//input----------------------------------    
    input   wire [23:0]     rgb888      ,
    input   wire            rgb_de      ,   //de使能信号
    input   wire            rgb_hsync   ,   //行同步信号
    input   wire            rgb_vsync   ,   //场同步信号
//output---------------------------------
    output  reg  [23:0]     face_data   ,   //肤色数据 1 像素位置为人脸 0不是
    output  wire            face_de     ,   //延时4个时钟周期
    output  wire            face_hsync  ,
    output  wire            face_vsync                  
    
    );

//wire define
wire [7:0] R;   //R分量
wire [7:0] G;   //G分量
wire [7:0] B;   //B分量
//reg defien
reg [15:0]   R1 ,R2 , R3     ;
reg [15:0]   G1 ,G2 , G3     ;
reg [15:0]   B1 ,B2 , B3     ;
reg [15:0]   Y1 , Cb1 , Cr1  ;
reg [7:0]    Y , Cb , Cr     ; //转换出的YCbCr数据
reg [3:0]   rgb_de_r        ; //rgb信号延时4个时钟周期
reg [3:0]   rgb_hsync_r     ;
reg [3:0]   rgb_vsync_r     ;

//R G B 分量赋值
assign R = rgb888[23:16];
assign G = rgb888[15:8];
assign B = rgb888[7:0];

/*********************************************
//Refer to full/pc range YCbCr format
    Y   =  R*0.299 + G*0.587 + B*0.114
    Cb  = -R*0.169 - G*0.331 + B*0.5   + 128
    Cr  =  R*0.5   - G*0.419 - B*0.081 + 128
--->      
    Y   = (76 *R + 150*G + 29 *B)>>8
    Cb  = (-43*R - 84 *G + 128*B + 32768)>>8
    Cr  = (128*R - 107*G - 20 *B + 32768)>>8
**********************************************/

//clk1 乘法
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)begin
            {R1,G1,B1} <= {16'd0, 16'd0, 16'd0};
            {R2,G2,B2} <= {16'd0, 16'd0, 16'd0};
            {R3,G3,B3} <= {16'd0, 16'd0, 16'd0};
        end
        else begin  
            {R1,G1,B1} <= { {R * 16'd76},  {G * 16'd150}, {B * 16'd29 } };
            {R2,G2,B2} <= { {R * 16'd43},  {G * 16'd84},  {B * 16'd128} };
            {R3,G3,B3} <= { {R * 16'd128}, {G * 16'd107}, {B * 16'd20 } };
        end
    end

//clk2 相加
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)begin
            {Y1,Cb1,Cr1} <= {1'b0, 1'b0, 1'b0};
        end
        else begin
            Y1  <= R1 + G1 + B1 ;
            Cb1 <= B2 - R2 - G2 + 16'd32768;
            Cr1 <= R3 - G3 - B3 + 16'd32768;
        end
    end

//clk3 右移8位,取高8位即可
    always @(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
            {Y,Cb,Cr} <= {1'b0, 1'b0, 1'b0};
        else begin
            Y  <= Y1[15:8];
            Cb <= Cb1[15:8];
            Cr <= Cr1[15:8];
        end
    end

//clk4 肤色检测 77<=Cb<=127        133<=Cr<=173 可以认为为肤色
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        face_data <= 1'd0;
    else if((Cb >= 77) && (Cb <= 127) && (Cr >= 133) && (Cr <= 173) )
        face_data <= 24'hFFFFFF;
    else
        face_data <= 1'b0;    
end

//rgb信号同步 延时4个周期
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        rgb_de_r    <= 1'b0;
        rgb_hsync_r <= 1'b0;
        rgb_vsync_r <= 1'b0;
    end
    else begin
        rgb_de_r    <= {rgb_de_r[2:0],    rgb_de};
        rgb_hsync_r <= {rgb_hsync_r[2:0], rgb_hsync};
        rgb_vsync_r <= {rgb_vsync_r[2:0], rgb_vsync};
    end
end

assign face_de    = rgb_de_r[3];
assign face_hsync = rgb_hsync_r[3];
assign face_vsync = rgb_vsync_r[3];

endmodule

之后由于我买的摄像头噪声太大,使用了两次中值滤波。

`timescale 1ns / 1ps
//
// 例化程序示例
// median_filter inst_median_filter
// (
//     .sys_clk    (sys_clk             ),  //LCD驱动时钟
//     .sys_rst_n  (sys_rst_n           ),  //系统复位
// //input----------------------------------
//     .data_in    (data_in             ),  //输入数据
//     .data_in_valid(data_in_valid     ),  //数据有效信号
//     .data_in_hs (data_in_hs          ),  //行同步信号
//     .data_in_vs (data_in_vs          ),  //场同步信号
// //output---------------------------------
//     .data_out   (data_out            ),  //输出的中值数据
//     .data_out_valid(data_out_valid   ),  //数据有效信号
//     .data_out_hs(data_out_hs         ),  //行同步信号
//     .data_out_vs(data_out_vs         )   //场同步信号
// );
// 
// Create Date: 2024/06/13 15:06:59
// Design Name: 
// Module Name: median filter
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
//              中值滤波器
// Dependencies: 
//                  2116815480@qq.com
//                  https://www.cnblogs.com/fangrunze              
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//


module median_filter(
    input   wire        sys_clk     ,
    input   wire        sys_rst_n   ,
//input----------------------------------
    input   wire [7:0]  data_in     ,   //输入的数据
    input   wire        data_in_valid,   //数据有效信号
    input   wire        data_in_hs  ,   //行同步信号
    input   wire        data_in_vs  ,   //场同步信号
//output---------------------------------
    output  wire [7:0]  data_out    ,   //输出的中值数据
    output  reg         data_out_valid, //数据有效信号
    output  reg         data_out_hs ,   //行同步信号
    output  reg         data_out_vs                  
    );

//wire define
//line data
    wire [7:0] line0_data;
    wire [7:0] line1_data;
    wire [7:0] line2_data;

    wire [7:0] line0_max;
    wire [7:0] line0_mid;
    wire [7:0] line0_min;

    wire [7:0] line1_max;
    wire [7:0] line1_mid;
    wire [7:0] line1_min;

    wire [7:0] line2_max;
    wire [7:0] line2_mid;
    wire [7:0] line2_min;

    wire [7:0] max_max;
    wire [7:0] max_mid;
    wire [7:0] max_min;

    wire [7:0] mid_max;
    wire [7:0] mid_mid;
    wire [7:0] mid_min;

    wire [7:0] min_max;
    wire [7:0] min_mid;
    wire [7:0] min_min;

    wire [7:0] matrix_mid;
    //reg define
    //matrix 3x3 data
    reg  [7:0] row0_col0;
    reg  [7:0] row0_col1;
    reg  [7:0] row0_col2;

    reg  [7:0] row1_col0;
    reg  [7:0] row1_col1;
    reg  [7:0] row1_col2;

    reg  [7:0] row2_col0;
    reg  [7:0] row2_col1;
    reg  [7:0] row2_col2;  

    reg   data_in_valid_dly1;
    reg   data_in_valid_dly2;
    reg   data_in_valid_dly3;
    reg   data_in_hs_dly1;
    reg   data_in_hs_dly2;
    reg   data_in_hs_dly3;
    reg   data_in_vs_dly1;
    reg   data_in_vs_dly2;
    reg   data_in_vs_dly3; 


//----------------------------------------------------
// matrix 3x3 data
// row0_col0   row0_col1   row0_col2
// row1_col0   row1_col1   row1_col2
// row2_col0   row2_col1   row2_col2
//----------------------------------------------------
assign line2_data = data_in;
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        row0_col0 <= 'd0;
        row0_col1 <= 'd0;
        row0_col2 <= 'd0;
        row1_col0 <= 'd0;
        row1_col1 <= 'd0;
        row1_col2 <= 'd0;
        row2_col0 <= 'd0;
        row2_col1 <= 'd0;
        row2_col2 <= 'd0;
    end
    else if((!data_in_hs) && (!data_in_vs))begin
        if(data_in_valid) begin
            row0_col2 <= line0_data;
            row0_col1 <= row0_col2;
            row0_col0 <= row0_col1; 

            row1_col2 <= line1_data;
            row1_col1 <= row1_col2;
            row1_col0 <= row1_col1;

            row2_col2 <= line2_data;
            row2_col1 <= row2_col2;
            row2_col0 <= row2_col1;
        end
        else begin
            row0_col2 <= row0_col2;
            row0_col1 <= row0_col1;
            row0_col0 <= row0_col0;

            row1_col2 <= row1_col2;
            row1_col1 <= row1_col1;
            row1_col0 <= row1_col0;

            row2_col2 <= row2_col2;
            row2_col1 <= row2_col1;
            row2_col0 <= row2_col0;
        end
    end
    else begin
        row0_col0 <= 'd0;
        row0_col1 <= 'd0;
        row0_col2 <= 'd0;

        row1_col0 <= 'd0;
        row1_col1 <= 'd0;
        row1_col2 <= 'd0;

        row2_col0 <= 'd0;
        row2_col1 <= 'd0;
        row2_col2 <= 'd0;
    end
end
//----------------------------------------------------
//延时三个时钟
//----------------------------------------------------
always @(posedge sys_clk)
begin
  data_in_valid_dly1 <= data_in_valid;
  data_in_valid_dly2 <= data_in_valid_dly1;
  data_in_valid_dly3 <= data_in_valid_dly2;

  data_in_hs_dly1    <= data_in_hs;
  data_in_hs_dly2    <= data_in_hs_dly1;
  data_in_hs_dly3    <= data_in_hs_dly2;

  data_in_vs_dly1    <= data_in_vs;
  data_in_vs_dly2    <= data_in_vs_dly1;
  data_in_vs_dly3    <= data_in_vs_dly2;
end
//----------------------------------------------------
//获得maxtrix 3x3 data
//----------------------------------------------------

shift_register_2taps shift_register_2taps(
  .sys_clk       (sys_clk           ), //输入时钟
  .shiftin       (data_in       ), //输入数据
  .shiftin_valid (data_in_valid ), //输入数据有效信号

  .shiftout      (              ), 
  .taps0x        (line0_data    ), //输出数据
  .taps1x        (line1_data    )  //输出数据
);
//----------------------------------------------------
// 计算3x3矩阵的中值  第0行
//----------------------------------------------------
sort sort_line0
(
    .sys_clk        (sys_clk            ),  //pixel clk              
    .sys_rst_n      (sys_rst_n          ),  //复位信号
    //input----------------------------------
    .data0_in       (row0_col0          ),  //输入的第0行数据
    .data1_in       (row0_col1          ),  //输入的第1行数据
    .data2_in       (row0_col2          ),  //输入的第2行数据
    .data_in_valid  (data_in_valid_dly1 ),  //数据有效信号
    //output---------------------------------
    .data_max_out   (line0_max          ),  //最大值
    .data_mid_out   (line0_mid          ),  //最小值
    .data_min_out   (line0_min          ),  //中值 
    .data_out_valid (                   )   //输出的数据有效信
);

//----------------------------------------------------
// 计算3x3矩阵的中值  第1行
//----------------------------------------------------
sort sort_line1
(
    .sys_clk        (sys_clk            ),  //pixel clk              
    .sys_rst_n      (sys_rst_n          ),  //复位信号
    //input----------------------------------
    .data0_in       (row1_col0          ),  //输入的第0行数据
    .data1_in       (row1_col1          ),  //输入的第1行数据
    .data2_in       (row1_col2          ),  //输入的第2行数据
    .data_in_valid  (data_in_valid_dly1 ),  //数据有效信号
    //output---------------------------------
    .data_max_out   (line1_max          ),  //最大值
    .data_mid_out   (line1_mid          ),  //最小值
    .data_min_out   (line1_min          ),  //中值 
    .data_out_valid (                   )   //输出的数据有效信
);
//----------------------------------------------------
// 计算3x3矩阵的中值  第2行
//----------------------------------------------------
sort sort_line2
(
    .sys_clk        (sys_clk            ),  //pixel clk              
    .sys_rst_n      (sys_rst_n          ),  //复位信号
    //input----------------------------------
    .data0_in       (row2_col0          ),  //输入的第0行数据
    .data1_in       (row2_col1          ),  //输入的第1行数据
    .data2_in       (row2_col2          ),  //输入的第2行数据
    .data_in_valid  (data_in_valid_dly1 ),  //数据有效信号
    //output---------------------------------
    .data_max_out   (line2_max          ),  //最大值
    .data_mid_out   (line2_mid          ),  //最小值
    .data_min_out   (line2_min          ),  //中值 
    .data_out_valid (                   )   //输出的数据有效信
);
//----------------------------------------------------
//line0_max line1_max line2_max
//----------------------------------------------------
sort sort_max
(
    .sys_clk        (sys_clk            ),  //pixel clk              
    .sys_rst_n      (sys_rst_n          ),  //复位信号
    //input----------------------------------
    .data0_in       (line0_max          ),  //输入的第0行数据
    .data1_in       (line1_max          ),  //输入的第1行数据
    .data2_in       (line2_max          ),  //输入的第2行数据
    .data_in_valid  (data_in_valid_dly2 ),  //数据有效信号
    //output---------------------------------
    .data_max_out   (max_max            ),  //最大值
    .data_mid_out   (max_mid            ),  //最小值
    .data_min_out   (max_min            ),  //中值 
    .data_out_valid (                   )   //输出的数据有效信
);
//----------------------------------------------------
//line0_mid line1_mid line2_mid
//----------------------------------------------------
sort sort_mid
(
    .sys_clk        (sys_clk            ),  //pixel clk              
    .sys_rst_n      (sys_rst_n          ),  //复位信号
    //input----------------------------------
    .data0_in       (line0_mid          ),  //输入的第0行数据
    .data1_in       (line1_mid          ),  //输入的第1行数据
    .data2_in       (line2_mid          ),  //输入的第2行数据
    .data_in_valid  (data_in_valid_dly2 ),  //数据有效信号
    //output---------------------------------
    .data_max_out   (mid_max            ),  //最大值
    .data_mid_out   (mid_mid            ),  //最小值
    .data_min_out   (mid_min            ),  //中值 
    .data_out_valid (                   )   //输出的数据有效信
);
//----------------------------------------------------
//line0_min line1_min line2_min
//----------------------------------------------------
sort sort_min
(
    .sys_clk        (sys_clk            ),  //pixel clk              
    .sys_rst_n      (sys_rst_n          ),  //复位信号
    //input----------------------------------
    .data0_in       (line0_min          ),  //输入的第0行数据
    .data1_in       (line1_min          ),  //输入的第1行数据
    .data2_in       (line2_min          ),  //输入的第2行数据
    .data_in_valid  (data_in_valid_dly2 ),  //数据有效信号
    //output---------------------------------
    .data_max_out   (min_max            ),  //最大值
    .data_mid_out   (min_mid            ),  //最小值
    .data_min_out   (min_min            ),  //中值 
    .data_out_valid (                   )   //输出的数据有效信
);
//----------------------------------------------------
//
//----------------------------------------------------
sort sort_all
(
    .sys_clk        (sys_clk            ),  //pixel clk              
    .sys_rst_n      (sys_rst_n          ),  //复位信号
    //input----------------------------------
    .data0_in       (max_min          ),  //输入的第0行数据
    .data1_in       (mid_mid          ),  //输入的第1行数据
    .data2_in       (min_max          ),  //输入的第2行数据
    .data_in_valid  (data_in_valid_dly3 ),  //数据有效信号
    //output---------------------------------
    .data_max_out   (                   ),  //最大值
    .data_mid_out   (matrix_mid         ),  //最小值
    .data_min_out   (                   ),  //中值 
    .data_out_valid (                   )   //输出的数据有效信
);
assign data_out = matrix_mid;
//----------------------------------------------------
//对齐输出信号
//----------------------------------------------------
always @(posedge sys_clk)
begin
  data_out_valid <= data_in_valid_dly3;
  data_out_hs    <= data_in_hs_dly3;
  data_out_vs    <= data_in_vs_dly3;
end
endmodule

其中构建3*3像素矩阵则使用的为 移位寄存器 IP核 具体可以查看 小梅哥 灰度图像中值滤波设计实现(HDMI 和 TFT 显示) **
这里有一个bug:移位寄存器在每一帧的第一行开始,会输出前一帧的最后两行数据(移位寄存器特性),这会导致后边肤色边界判断异常。具体现象参考:生成3x3矩阵(3):shift ip核 - 咸鱼IC - 博客园
换帧数据的问题。解决办法:最后肤色边界判断时,屏蔽前两行数据。**
腐蚀操作:

`timescale 1ns / 1ps
//
// 例化程序示例
// Erode inst_Erode(
//.sys_clk            (sys_clk        ) ,
//.sys_rst_n          (sys_rst_n      ) ,
input----------------------------------
//.data_in            (data_in        ) ,   //输入的RGB数据
//.data_in_valid      (data_in_valid  ) ,   //数据有效信号
//.data_in_hs         (data_in_hs     ) ,   //行同步信号
//.data_in_vs        (data_in_vs    ) ,   //场同步信号
output---------------------------------
//.erode_out          (erode_out      ) ,   //输出的数据
//.erode_out_valid    (erode_out_valid) ,
//.erode_out_hs       (erode_out_hs   ) ,   //行同步信号
//.erode_out_vs       (erode_out_vs   )     //场同步信号    
// );
// Create Date: 2024/06/13 17:06:23
// Design Name: 
// Module Name: Erode
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
//              腐蚀处理,输入必须为二值图像
// Dependencies: 
//                  2116815480@qq.com
//                  https://www.cnblogs.com/fangrunze  
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


    module Erode(
input   wire        sys_clk         ,
input   wire        sys_rst_n       ,
//input----------------------------------
input   wire [7:0]  data_in         ,   //输入的RGB数据
input   wire        data_in_valid   ,   //数据有效信号
input   wire        data_in_hs      ,   //行同步信号
input   wire        data_in_vs      ,   //场同步信号
//output---------------------------------
output  wire [7:0]  erode_out         ,   //输出的数据
output  reg        erode_out_valid   ,
output  reg        erode_out_hs      ,   //行同步信号
output  reg        erode_out_vs          //场同步信号
);
    wire [7:0] line0_data;
    wire [7:0] line1_data;
     wire [7:0] line2_data;
//reg define
    //matrix 3x3 data
    reg  [7:0] row0_col0;
    reg  [7:0] row0_col1;
    reg  [7:0] row0_col2;

    reg  [7:0] row1_col0;
    reg  [7:0] row1_col1;
    reg  [7:0] row1_col2;

    reg  [7:0] row2_col0;
    reg  [7:0] row2_col1;
    reg  [7:0] row2_col2; 

    reg        erode_out_valid_dly1 ;
    reg        erode_out_valid_dly2 ;
    reg        erode_out_hs_dly1    ;
    reg        erode_out_hs_dly2    ;
    reg        erode_out_vs_dly1    ;
    reg        erode_out_vs_dly2    ;
    reg [7:0] erode  ; 
    reg [7:0] erode_1;
    reg [7:0] erode_2;
    reg [7:0] erode_3;
//----------------------------------------------------
// matrix 3x3 data
// row0_col0   row0_col1   row0_col2
// row1_col0   row1_col1   row1_col2
// row2_col0   row2_col1   row2_col2
//----------------------------------------------------
assign line2_data = data_in;
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        row0_col0 <= 'd0;
        row0_col1 <= 'd0;
        row0_col2 <= 'd0;
        row1_col0 <= 'd0;
        row1_col1 <= 'd0;
        row1_col2 <= 'd0;
        row2_col0 <= 'd0;
        row2_col1 <= 'd0;
        row2_col2 <= 'd0;
    end
    else if((!data_in_hs) && (!data_in_vs))begin
        if(data_in_valid) begin
            row0_col2 <= line0_data;
            row0_col1 <= row0_col2;
            row0_col0 <= row0_col1; 

            row1_col2 <= line1_data;
            row1_col1 <= row1_col2;
            row1_col0 <= row1_col1;

            row2_col2 <= line2_data;
            row2_col1 <= row2_col2;
            row2_col0 <= row2_col1;
        end
        else begin
            row0_col2 <= row0_col2;
            row0_col1 <= row0_col1;
            row0_col0 <= row0_col0;

            row1_col2 <= row1_col2;
            row1_col1 <= row1_col1;
            row1_col0 <= row1_col0;

            row2_col2 <= row2_col2;
            row2_col1 <= row2_col1;
            row2_col0 <= row2_col0;
        end
    end
    else begin
        row0_col0 <= 'd0;
        row0_col1 <= 'd0;
        row0_col2 <= 'd0;

        row1_col0 <= 'd0;
        row1_col1 <= 'd0;
        row1_col2 <= 'd0;

        row2_col0 <= 'd0;
        row2_col1 <= 'd0;
        row2_col2 <= 'd0;
    end
end
//----------------------------------------------------
//获得maxtrix 3x3 data
//----------------------------------------------------
shift_register_2taps erode_shift(
  .sys_clk       (sys_clk           ), //输入时钟
  .shiftin       (data_in       ), //输入数据
  .shiftin_valid (data_in_valid ), //输入数据有效信号

  .shiftout      (              ), 
  .taps0x        (line0_data    ), //输出数据
  .taps1x        (line1_data    )  //输出数据
);
//----------------------------------------------------
//腐蚀
//----------------------------------------------------
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        erode_1 <= 'd0;
        erode_2 <= 'd0;
        erode_3 <= 'd0;
    end
    else if(data_in_valid) begin
        erode_1 <= row0_col0 && row0_col1 && row0_col2;
        erode_2 <= row1_col0 && row1_col1 && row1_col2;
        erode_3 <= row2_col0 && row2_col1 && row2_col2;
    end
    else begin
        erode_1 <= 'd0;
        erode_2 <= 'd0;
        erode_3 <= 'd0;
    end
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        erode <= 'd0;
    end
    else 
        erode <= erode_1 && erode_2 && erode_3;
end
assign erode_out = erode ? 8'hff : 8'h00;
//----------------------------------------------------
//对齐时序
//----------------------------------------------------
always @(posedge sys_clk) begin
    erode_out_valid_dly1 <= data_in_valid;
    erode_out_valid_dly2 <= erode_out_valid_dly1;
    erode_out_valid <= erode_out_valid_dly2;

    erode_out_hs_dly1 <= data_in_hs;
    erode_out_hs_dly2 <= erode_out_hs_dly1;
    erode_out_hs <= erode_out_hs_dly2;

    erode_out_vs_dly1 <= data_in_vs;
    erode_out_vs_dly2 <= erode_out_vs_dly1;
    erode_out_vs <= erode_out_vs_dly2;     
end

endmodule

也是为了进一步的降噪 腐蚀操作针对二值化数据,这也是为什么最后才做均值滤波,均值滤波之后,就不是二值化数据了
均值滤波:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/05/11 19:32:21
// Design Name: 
// Module Name: mean_filter
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module mean_filter
(
    input   wire                sys_clk         ,  //LCD驱动时钟
    input   wire                sys_rst_n       ,  //系统复位
    input   wire                data_in_valid   ,  //输入数据有效信号
    input   wire    [7:0]       data_in         ,  //输入数据
    input   wire                data_in_hs      ,  //输入数据水平同步信号
    input   wire                data_in_vs      ,  //输入数据垂直同步信号
 //   input   wire                data_in_de      ,  //输入数据使能信号

//    output  reg                 data_out_de     ,  //输出数据使能信号
    output  reg                 data_out_valid  ,  //输出数据有效信号
    output  wire     [7:0]      data_out        ,  //输出数据
    output  reg                 data_out_hs     ,  //输出数据水平同步信号
    output  reg                 data_out_vs        //输出数据垂直同步信号
    );
//wire define
//line data
wire [7:0] line0_data;
wire [7:0] line1_data;
wire [7:0] line2_data;
//reg define
//matrix 3x3 data
reg  [7:0] row0_col0;
reg  [7:0] row0_col1;
reg  [7:0] row0_col2;

reg  [7:0] row1_col0;
reg  [7:0] row1_col1;
reg  [7:0] row1_col2;

reg  [7:0] row2_col0;
reg  [7:0] row2_col1;
reg  [7:0] row2_col2;

reg  [10:0]   sum_data            ;
reg           data_in_valid_dly1  ;
reg           data_in_hs_dly1     ;
reg           data_in_vs_dly1     ;
//reg           data_in_de_dly1     ;
assign line2_data = data_in;

//----------------------------------------------------
// matrix 3x3 data
// row0_col0   row0_col1   row0_col2
// row1_col0   row1_col1   row1_col2
// row2_col0   row2_col1   row2_col2
//----------------------------------------------------
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        row0_col0 <= 'd0;
        row0_col1 <= 'd0;
        row0_col2 <= 'd0;
        row1_col0 <= 'd0;
        row1_col1 <= 'd0;
        row1_col2 <= 'd0;
        row2_col0 <= 'd0;
        row2_col1 <= 'd0;
        row2_col2 <= 'd0;
    end
    else if((!data_in_hs) && (!data_in_vs))begin
        if(data_in_valid) begin
            row0_col2 <= line0_data;
            row0_col1 <= row0_col2;
            row0_col0 <= row0_col1; 

            row1_col2 <= line1_data;
            row1_col1 <= row1_col2;
            row1_col0 <= row1_col1;

            row2_col2 <= line2_data;
            row2_col1 <= row2_col2;
            row2_col0 <= row2_col1;
        end
        else begin
            row0_col2 <= row0_col2;
            row0_col1 <= row0_col1;
            row0_col0 <= row0_col0;

            row1_col2 <= row1_col2;
            row1_col1 <= row1_col1;
            row1_col0 <= row1_col0;

            row2_col2 <= row2_col2;
            row2_col1 <= row2_col1;
            row2_col0 <= row2_col0;
        end
    end
    else begin
        row0_col0 <= 'd0;
        row0_col1 <= 'd0;
        row0_col2 <= 'd0;

        row1_col0 <= 'd0;
        row1_col1 <= 'd0;
        row1_col2 <= 'd0;

        row2_col0 <= 'd0;
        row2_col1 <= 'd0;
        row2_col2 <= 'd0;
    end
end

//----------------------------------------------------
//赋值需要一个周期 则需要将输入的信号延迟一个周期
//----------------------------------------------------
always @(posedge sys_clk) begin
    data_in_valid_dly1 <= data_in_valid;
    data_in_hs_dly1    <= data_in_hs;
    data_in_vs_dly1    <= data_in_vs;
//    data_in_de_dly1    <= data_in_de;
end


//----------------------------------------------------
// 计算3x3矩阵的和 乘以3641 
//----------------------------------------------------
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        sum_data <= 'd0;
    end
    else if(data_in_valid_dly1) begin
            sum_data <= (row0_col0 + row0_col1 + row0_col2 
                        + row1_col0              + row1_col2 
                        + row2_col0 + row2_col1 + row2_col2);
        end
    else begin
        sum_data <= sum_data;
    end

end

assign data_out = sum_data>>3; //对data_sum右移15位,并且进行四舍五入


//----------------------------------------------------
//输出信号赋值
//----------------------------------------------------
always @(posedge sys_clk) begin
    data_out_valid <= data_in_valid_dly1;
    data_out_hs    <= data_in_hs_dly1;
    data_out_vs    <= data_in_vs_dly1;
    //data_out_de    <= data_in_de_dly1;
end

//----------------------------------------------------
//获得maxtrix 3x3 data
//----------------------------------------------------
shift_register_2taps shift_register_mean(
  .sys_clk       (sys_clk           ), //输入时钟
  .shiftin       (data_in       ), //输入数据
  .shiftin_valid (data_in_valid ), //输入数据有效信号

  .shiftout      (              ), 
  .taps0x        (line0_data    ), //输出数据
  .taps1x        (line1_data    )  //输出数据
);
endmodule

边界判断 参考:

`timescale 1ns / 1ps
//
//例化程序示例
//  face_box_select#(
//      .IMG_WIDTH  (IMG_WIDTH ),   //图片宽度
//      .IMG_HEIGHT (IMG_HEIGHT)    //图片长度
//  )
//  inst_face_box_select
//  (
//      .sys_clk    (sys_clk   ), 
//      .sys_rst_n  (sys_rst_n ), 
//  //input------------------------------------------
//      .rgb888     (rgb888    ), //原始数据 24bit   
//      .face_de    (face_de   ), //人脸数据de使能信号
//      .face_hsync (face_hsync), //人脸数据行同步信号
//      .face_vsync (face_vsync), //人脸数据场同步信号
//      .face_data_1  (face_data_1 ), //人脸数据 24bit
//  //output-----------------------------------------
//      .box_de     (box_de    ), 
//      .box_hsync  (box_hsync ), //行同步信号
//      .box_vsync  (box_vsync ), //场同步信号
//      .box_data   (box_data  )  //24bit
//  );
// 
// Create Date: 2024/04/02 12:39:46
// Design Name: FRZ
// Module Name: face_box_select
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 输入原始数据以及处理过的人脸数据,输出被框选住人脸的原始数据
// Dependencies: 
//          2116815480@qq.com
//          https://www.cnblogs.com/fangrunze
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module face_box_select#(
parameter    IMG_WIDTH  = 'd480         ,     //图片宽度
parameter    IMG_HEIGHT = 'd272               //图片长度
)
(
input   wire                sys_clk     ,
input   wire                sys_rst_n   ,
//input----------------------------------
input   wire [23:0]         rgb888      ,   //原始数据
input   wire                rgb_de      ,
input   wire                rgb_hsync   ,   //行同步信号
input   wire                rgb_vsync   ,   //场同步信号

input   wire                face_de     ,   //人脸数据de使能信号
input   wire                face_hsync  ,   //人脸数据行同步信号 低电平有效
input   wire                face_vsync  ,   //人脸数据场同步信号 低电平有效
input   wire    [7:0]       face_data   ,   //人脸数据
//output---------------------------------
output  reg                 box_de      ,
output  reg                 box_hsync   ,   //行同步信号 低电平有效
output  reg                 box_vsync   ,   //场同步信号 低电平有效
output  reg     [23:0]      box_data        //24bit
    );

//reg define
reg                          face_vsync_r     ; //场同步信号延时一拍
reg             [11:0]       face_x           ; //人脸数据坐标
reg             [11:0]       face_y           ;
reg             [11:0]       face_x_min       ; //人脸范围
reg             [11:0]       face_x_max       ;
reg             [11:0]       face_y_min       ;
reg             [11:0]       face_y_max       ;
reg             [11:0]       reg_face_x_min   ;
reg             [11:0]       reg_face_x_max   ;
reg             [11:0]       reg_face_y_min   ;
reg             [11:0]       reg_face_y_max   ;
reg             [23:0]       rgb888_r1        ;
reg             [23:0]       rgb888_r2        ;
reg             [23:0]       rgb888_r3        ;
reg             [23:0]       rgb888_r4        ;
//wire define

wire    pose_face_vsync ; //场同步信号上升沿
wire    nege_face_vsync ; //场同步信号下降沿

//=========================================================================
//==场同步信号上升、下降沿检测
//=========================================================================
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        face_vsync_r <= 1'b0 ;
    else
        face_vsync_r <= face_vsync ;
end

assign pose_face_vsync = face_vsync && (~face_vsync_r)   ; //场同步信号上升沿
assign nege_face_vsync = (~face_vsync) && face_vsync_r   ; //场同步信号下降沿
//=========================================================================
//==输入人脸像素数据坐标
//=========================================================================
    //x坐标
always @(posedge sys_clk or negedge sys_rst_n) begin 
    if(!sys_rst_n)
        face_x <= 1'b0;
    else if(face_de) begin
        if(face_x == IMG_WIDTH - 1'b1)
            face_x <= 1'b0;
        else
            face_x <= face_x + 1'b1;
    end
    else
        face_x <= face_x;
end
    //y坐标
always @(posedge sys_clk or negedge sys_rst_n) begin 
    if(!sys_rst_n)
        face_y <= 1'b0;
    else if(face_x == IMG_WIDTH - 1'b1 && face_de)begin
        if(face_y == IMG_HEIGHT - 1'b1)
            face_y <= 1'b0;
        else
            face_y <= face_y + 1'b1;
    end
    else
        face_y <= face_y;
    end

//=========================================================================
//==确定人脸的x、y坐标范围
//=========================================================================
wire [7:0] face_data_1;
assign face_data_1 = (face_y > 1)? face_data : 8'h00; //人脸数据第两行无效 移位寄存器特性
    //face_x_min
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        face_x_min <= IMG_WIDTH;
    else if(nege_face_vsync)
        face_x_min <= IMG_WIDTH;
    else if(face_data_1 == 8'hFF && face_x_min > face_x && face_de)
        face_x_min <= face_x;
end
    //face_x_max
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        face_x_max <= 1'b0;
    else if(nege_face_vsync)
        face_x_max <= 1'b0;
    else if(face_data_1 == 8'hFF && face_x_max < face_x && face_de)
        face_x_max <= face_x;
end
    //face_y_min
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        face_y_min <= IMG_HEIGHT;
    else if(nege_face_vsync)
        face_y_min <= IMG_HEIGHT;
    else if(face_data_1 == 8'hFF && face_y_min > face_y && face_de)
        face_y_min <= face_y;
end
    //face_y_max
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)
        face_y_max <= 1'b0;
    else if(nege_face_vsync)
        face_y_max <= 1'b0;
    else if(face_data_1 == 8'hFF && face_y_max < face_y && face_de)
        face_y_max <= face_y;
end

//=========================================================================
//==保存坐标
//=========================================================================
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        reg_face_x_min <= 1'b0;
        reg_face_x_max <= 1'b0;
        reg_face_y_min <= 1'b0;
        reg_face_y_max <= 1'b0;
    end
    else if(pose_face_vsync)begin
        reg_face_x_min <= face_x_min;
        reg_face_x_max <= face_x_max;
        reg_face_y_min <= face_y_min;
        reg_face_y_max <= face_y_max;
    end
    else begin
        reg_face_x_min <= reg_face_x_min;
        reg_face_x_max <= reg_face_x_max;
        reg_face_y_min <= reg_face_y_min;
        reg_face_y_max <= reg_face_y_max;
    end
end

=========================================================================
==原始数据数据延时4拍    rgb转YCbCr算法延时4拍
=========================================================================
//always @(posedge sys_clk or negedge sys_rst_n) begin
//    if(!sys_rst_n)begin
//        rgb888_r1 <= 1'b0;
//        rgb888_r2 <= 1'b0;
//        rgb888_r3 <= 1'b0;
//        rgb888_r4 <= 1'b0;
//    end
//    else begin
//        rgb888_r1 <= rgb888   ;
//        rgb888_r2 <= rgb888_r1;
//        rgb888_r3 <= rgb888_r2;
//        rgb888_r4 <= rgb888_r3;
//    end
//end
//

//=========================================================================
//==处理后数据输出
//=========================================================================
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n)begin
        box_de    <= 1'b0;
        box_hsync <= 1'b0;
        box_vsync <= 1'b0;
        box_data  <= 1'b0;
    end
    else if(face_x == reg_face_x_min 
    && face_y>=reg_face_y_min && face_y<=reg_face_y_max )begin
        box_de    <= rgb_de    ;
        box_hsync <= rgb_hsync ;
        box_vsync <= rgb_vsync ;
        box_data  <= 24'h00FF00 ; //绿色边框
            end
    else if(face_x == reg_face_x_max 
            && face_y>=reg_face_y_min && face_y<=reg_face_y_max )begin
        box_de    <= rgb_de    ;
        box_hsync <= rgb_hsync ;
        box_vsync <= rgb_vsync ;
        box_data  <= 24'h00FF00 ; //绿色边框
            end
    else if(face_y == reg_face_y_min
    && face_x>=reg_face_x_min && face_x<=reg_face_x_max )begin
        box_de    <= rgb_de    ;
        box_hsync <= rgb_hsync ;
        box_vsync <= rgb_vsync ;
        box_data  <= 24'h00FF00 ; //绿色边框
    end
    else if(face_y == reg_face_y_max  
    && face_x>=reg_face_x_min && face_x<=reg_face_x_max )begin
        box_de    <= rgb_de    ;
        box_hsync <= rgb_hsync ;
        box_vsync <= rgb_vsync ;
        box_data  <= 24'h00FF00 ; //绿色边框
            end
    else begin
        box_de    <= rgb_de    ;
        box_hsync <= rgb_hsync ;
        box_vsync <= rgb_vsync ;
        box_data  <= rgb888  ; //绿色边框
    end
end
endmodule

FPGA实现人脸检测 - 咸鱼IC - 博客园
注意:边界判断时需要注意输入的hs、vs信号为低电平有效,还是高电平有效 上边说的移位寄存器的问题使用:assign face_data_1 = (face_y > 1)? face_data : 8’h00; //人脸数据第两行无效 移位寄存器特性 解决

工程源码:

链接: https://pan.baidu.com/s/1iHwRqPcZJTe4-9pRzRU0-w?pwd=fdt6 提取码: fdt6 复制这段内容后打开百度网盘手机App,操作更方便哦
所有的代码 均在这里,大家自取。
上文中涉及的小梅哥的教材
链接: https://pan.baidu.com/s/1o9pmkgHDI3qkS16UKT9soQ?pwd=9kec 提取码: 9kec 复制这段内容后打开百度网盘手机App,操作更方便哦

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

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

相关文章

轻松获取指定日期所在周的周一和周日

哈喽&#xff0c;大家好呀&#xff0c;好久不见&#xff01;今天是一篇浅记。根据传入日期自动获取所在周一和周日… 正常基操方法&#xff0c;根据传入日期自动获取所在周一和周日。注意传入日期是周日的情况哈&#xff0c;需要往前推7天才是周一。 楼主方法中已处理&#xf…

为何Proteus用户争相拥抱SmartEDA?揭秘背后的强大吸引力!

在电路设计与仿真领域&#xff0c;Proteus一度以其稳定性能和丰富功能赢得了众多用户的青睐。然而&#xff0c;近年来&#xff0c;越来越多的Proteus用户开始转向SmartEDA&#xff0c;这一新兴电路仿真软件正迅速崭露头角&#xff0c;成为行业内的翘楚。那么&#xff0c;究竟是…

数据模型——饮食记录

数据模型——饮食记录 本次实验完成饮食记录的数据模型&#xff0c;如下图所示 该饮食记录模型与上次的记录项数据模式定义处理方式相同&#xff0c;我们首先分析其数据结构&#xff0c;我们发现首先有早餐、午餐、晚餐等记录类型数据模型&#xff0c;其包括了id、类型名称、类…

几个小实验

小实验 shh远程管理 ssh是一种安全通道协议&#xff0c;只能用来实现字符界面的远程登录。远程复制&#xff0c;远程文本传输。 ssh对通信双方的数据进行了加密。 用户名和密码登录 密钥对认证方式&#xff08;可以实现免密登录&#xff09; ssh 22 网络层 传输层 数据传…

龙虎斗(2018)c++

题目描述 输入 输出 样例输入&#xff0c;输出 输入 #1 输出 #1 6 2 2 3 2 3 2 3 4 6 5 2 输入 #2 输出 #2 6 …

最新技术:跨境电商源码,应对多国市场需求,让您轻松开展全球业务!

随着全球化进程的不断推进&#xff0c;跨境电商已成为企业拓展国际市场的重要途径。为了满足不同国家和地区消费者不断增长的需求&#xff0c;跨境电商源码应运而生&#xff0c;为企业提供了便捷高效的全球化业务发展方案。 一、全球化运营的关键 跨境电商源码的核心功能在于…

GaussDB技术解读——GaussDB架构介绍(五)

GaussDB架构介绍&#xff08;四&#xff09;从云原生关键技术架构&关键技术方案两方面对GaussDB云原生架构进行了解读&#xff0c;本篇将从关键技术方案的事务存储组件、SQL引擎组件、DCS组件、实时分析组件等方面继续介绍GaussDB云原生架构。 目录 事务存储组件 1、本地…

零基础入门学用Arduino 第四部分(三)

重要的内容写在前面&#xff1a; 该系列是以up主太极创客的零基础入门学用Arduino教程为基础制作的学习笔记。个人把这个教程学完之后&#xff0c;整体感觉是很好的&#xff0c;如果有条件的可以先学习一些相关课程&#xff0c;学起来会更加轻松&#xff0c;相关课程有数字电路…

《EDA技术》同步十三进制计数器实验报告

摘要&#xff1a; 本实验通过Multsim和Quartus软件完成对同步十三进制计数器的仿真&#xff0c;运用Quartus软件编VHDL程序&#xff0c;实现波形图的生成&#xff0c;并且运用Multsim软件进行电路图仿真。同时&#xff0c;加深 对数字电路和VHDL语言的理解&#xff0c;提高实验…

2024 年 Python 基于 Kimi 智能助手 Moonshot Ai 模型搭建微信机器人(更新中)

注册 Kimi 开放平台 Kimi&#xff1a;https://www.moonshot.cn/ Kimi智能助手是北京月之暗面科技有限公司&#xff08;Moonshot AI&#xff09;于2023年10月9日推出的一款人工智能助手&#xff0c;主要为用户提供高效、便捷的信息服务。它具备多项强大功能&#xff0c;包括多…

04 Pytorch tensor

一&#xff1a;老版本的 variable 二&#xff1a;新版 tensor 曾经&#xff1a;求导相关 如今&#xff1a;数据相关 –dtype: 张量的数据类型&#xff0c;三大类&#xff0c;共9种。torch.FloatTensor, torch.cuda.FloatTensor –shape: 张量的形状。如&#xff1a;&#x…

k8s学习--Kruise Rollouts 基本使用

文章目录 Kruise Rollouts简介什么是 Kruise Rollouts&#xff1f;核心功能 应用环境一、OpenKruise部署1.安装helm客户端工具2. 通过 helm 安装 二、Kruise Rollouts 安装2. kubectl plugin安装 三、Kruise Rollouts 基本使用(多批次发布)1. 使用Deployment部署应用2.准备Roll…

[Cloud Networking] SPDY 协议

文章目录 1. 背景2. SPDY 之前3. SPDY 项目目标4. SPDY 功能特点4.1 SPDY基本功能4.2 SPDY高级功能 1. 背景 TCP是通用的、可靠的传输协议&#xff0c;提供保证交付、重复抑制、按顺序交付、流量控制、拥塞避免和其他传输特性。 HTTP是提供基本请求/响应语义的应用层协议。 不…

网格布局之重复轨道

网格布局之重复轨道 欢迎关注&#xff1a;xssy5431 小拾岁月 参考链接&#xff1a;https://mp.weixin.qq.com/s/FQboZRMhdOFWqVDZ5JScDg 点击查看 使用场景 在网页开发中&#xff0c;我们尝尝会遇到宫格布局&#xff0c;比如&#xff1a;3 * 3&#xff0c;4 * 4布局等等。 …

6月19日(周三)A股行情总结:A股震荡收跌,恒生科技指数大涨3%,10年期国债期货转涨续创新高

内容提要 车路云概念延续昨日涨势&#xff0c;华铭智能20CM 3连板。贵金属及PEEK材料概念全日走强&#xff1b;港股有色金属及能源股走强&#xff0c;紫金矿业涨超3%&#xff0c;中石油涨超3%。国债期货午后全线转涨&#xff0c;10年期主力合约涨0.05%报104.925元&#xff0c;…

7zip安装后压缩包图标显示空白解决办法

记录安装7zip软件后&#xff0c;出现了如下的图标是空白的问题: &#xff08;虽然我最终解决了但是我不确定是哪一步起的作用&#xff0c;但是我也懒得再情景复现了。&#xff09; 我的解决过程是&#xff1a; 在开始菜单栏搜索“7zip ”然后点击“打开。 然后点击 &#xf…

HTTP!!!

HTTP 一 : 请求报文1.2 : 首行1.3 :请求头(header)1.4 : 空行1.5 : 正文 body 二: 响应报文2.2 : 首行 三 : URL 一 : 请求报文 一个HTTP 请求报文, 分成四个部分 首行 GET https://cn.bing.com/?FORMZ9FD1 HTTP/1.1请求头(header)空行正文(body) 1.2 : 首行 首行又分为三个…

CobaltStrike后渗透进阶篇

0x01 网络钓鱼攻击 钓鱼攻击简介 钓鱼攻击主要通过生成的木马诱使受害者运行后上线&#xff0c;其中木马一般都伪装成正常的程序。与此同时配合钓鱼网站可帮助攻击者模拟真实网站诱骗受害者访问&#xff0c;达到获取账号密码、上线木马等目的。接下来主要介绍后门程序的生成及…

自动化测试接口测试前的【准备及思路】

1、什么是接口测试 客户端&#xff08;前端&#xff09;与服务端&#xff08;后端&#xff09;的关系&#xff0c;一般小编会理解为“服务端负责赚钱养家&#xff0c;客户端负责貌美如花”。客户端更注重的是功能呈现及用户体验&#xff0c;怎么将强大的功能精彩的界面呈现给不…

云上战场:ToDesk云电脑、青椒云、顺网云全面对决

前言 记得端午放假期间&#xff0c;我已经在旅游的路上了&#xff0c;老板突然发短信&#xff0c;让我给他画个图&#xff0c;我手上的战斗机已经是十年前的老古董了(平常一直用的公司电脑&#xff0c;也没想过要换)&#xff0c;压根满足不了老板的任务要求&#xff0c;不得已&…