项目简述
我们上一篇文章讲解了MATLABl利用肤色检测模型进行人脸检测,也给出了完整的MATLAB代码。同学们学习本篇博客的时候一定要先学习上篇文章,因为上篇文章介绍了整个算法的流程,比看FPGA的实现要简单的多。
本篇博客,我们将利用FPGA实现一副图片中的人脸检测:PC机通过千兆网发送一幅图片经过肤色检测、腐蚀、定位之后将定位信息传递给USB3.0驱动端,再将原始图像转存到DDR3中,然后经过USB3.0将定位后的原始图像发送到上位机显示。
本次实验所用到的软硬件环境如下:
1、VIVADO2019.1软件环境
2、Modelsim10.7c仿真环境
3.米联客MA7035FA(100T)开发板
4、米联客USB3.0上位机软件
5、V3学院千兆网上位机
整个项目的流程图如上图,我们利用上面的程序框图进行书写便可以完成图像定位。
肤色检测
肤色检测的原理我们上一篇博客已经进行了介绍,首先将RGB分量信息转换成YYCrCb信息,其中Y是亮度信息、Cr表示红色信息、Cb表示绿色信息。然后利用红色分量、绿色分量信息进行肤色定位。
肤色检测代码
这里原理相信大家经过上篇博客的学习已经学会,这里我们直接给出相应的代码供大家学习:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : face_test.v
// Create Time : 2020-04-11 10:57:34
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module face_test(
//System Interfaces
input sclk ,
input rst_n ,
//Communication Interfaces
input [23:0] ycbcr_data ,
input ycbcr_flag ,
output reg [ 7:0] face_data ,
output reg face_flag
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
parameter CB_LOWER = 77;
parameter CB_UPPER = 127;
parameter CR_LOWER = 133;
parameter CR_UPPER = 173;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
face_data <= 8'd0;
else if(ycbcr_data[15:8] > CB_LOWER && ycbcr_data[15:8] < CB_UPPER && ycbcr_data[7:0] > CR_LOWER && ycbcr_data[7:0] < CR_UPPER)
face_data <= 8'd255;
else
face_data <= 8'd0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
face_flag <= 1'b0;
else
face_flag <= ycbcr_flag;
endmodule
肤色检测结果
我们会在最后给出最终工程的代码,这里为了简洁性不再给出部分代码。整体的实验结果图如下:
腐蚀图像
从上面的肤色检测图中,我们可以看出肤色检测之后有许多噪点,那么我们便使用腐蚀操作将上面的噪点腐蚀掉。其实最好的操作是先腐蚀再膨胀,这样可以将图像定位的更准确,但是我们因为简洁行的原因没有使用膨胀操作。其次这里我们使用的矩阵式1313的矩阵,并没有使用33的矩阵,因为矩阵太小没办法腐蚀掉全部的噪点。
腐蚀图像代码
这里我们直接给出相应的代码:
13*13矩阵模块代码,mat_13x13模块:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : mat_13x13.v
// Create Time : 2020-04-11 22:13:48
// Editor : sublime text3, tab size (2)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module mat_13x13(
//System Interfaces
input sclk ,
input rst_n ,
//Communication Interfaces
input [ 7:0] rx_data ,
input pi_flag ,
output wire [ 7:0] mat_row1 ,
output wire [ 7:0] mat_row2 ,
output wire [ 7:0] mat_row3 ,
output wire [ 7:0] mat_row4 ,
output wire [ 7:0] mat_row5 ,
output wire [ 7:0] mat_row6 ,
output wire [ 7:0] mat_row7 ,
output wire [ 7:0] mat_row8 ,
output wire [ 7:0] mat_row9 ,
output wire [ 7:0] mat_row10 ,
output wire [ 7:0] mat_row11 ,
output wire [ 7:0] mat_row12 ,
output wire [ 7:0] mat_row13 ,
output wire mat_flag
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
parameter COL_NUM = 1024 ;
parameter ROW_NUM = 768 ;
reg [10:0] col_cnt ;
reg [10:0] row_cnt ;
wire wr_en1 ;
wire wr_en2 ;
wire wr_en3 ;
wire wr_en4 ;
wire wr_en5 ;
wire wr_en6 ;
wire wr_en7 ;
wire wr_en8 ;
wire wr_en9 ;
wire wr_en10 ;
wire wr_en11 ;
wire wr_en12 ;
wire wr_en13 ;
wire rd_en1 ;
wire rd_en2 ;
wire rd_en3 ;
wire rd_en4 ;
wire rd_en5 ;
wire rd_en6 ;
wire rd_en7 ;
wire rd_en8 ;
wire rd_en9 ;
wire rd_en10 ;
wire rd_en11 ;
wire rd_en12 ;
wire rd_en13 ;
wire [ 7:0] fifo1_rd_data ;
wire [ 7:0] fifo2_rd_data ;
wire [ 7:0] fifo3_rd_data ;
wire [ 7:0] fifo4_rd_data ;
wire [ 7:0] fifo5_rd_data ;
wire [ 7:0] fifo6_rd_data ;
wire [ 7:0] fifo7_rd_data ;
wire [ 7:0] fifo8_rd_data ;
wire [ 7:0] fifo9_rd_data ;
wire [ 7:0] fifo10_rd_data ;
wire [ 7:0] fifo11_rd_data ;
wire [ 7:0] fifo12_rd_data ;
wire [ 7:0] fifo13_rd_data ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign wr_en1 = pi_flag;
assign wr_en2 = row_cnt >= 11'd1 ? pi_flag : 1'b0;
assign wr_en3 = row_cnt >= 11'd2 ? pi_flag : 1'b0;
assign wr_en4 = row_cnt >= 11'd3 ? pi_flag : 1'b0;
assign wr_en5 = row_cnt >= 11'd4 ? pi_flag : 1'b0;
assign wr_en6 = row_cnt >= 11'd5 ? pi_flag : 1'b0;
assign wr_en7 = row_cnt >= 11'd6 ? pi_flag : 1'b0;
assign wr_en8 = row_cnt >= 11'd7 ? pi_flag : 1'b0;
assign wr_en9 = row_cnt >= 11'd8 ? pi_flag : 1'b0;
assign wr_en10 = row_cnt >= 11'd9 ? pi_flag : 1'b0;
assign wr_en11 = row_cnt >= 11'd10 ? pi_flag : 1'b0;
assign wr_en12 = row_cnt >= 11'd11 ? pi_flag : 1'b0;
assign wr_en13 = row_cnt >= 11'd12 ? pi_flag : 1'b0;
assign rd_en1 = wr_en2;
assign rd_en2 = wr_en3;
assign rd_en3 = wr_en4;
assign rd_en4 = wr_en5;
assign rd_en5 = wr_en6;
assign rd_en6 = wr_en7;
assign rd_en7 = wr_en8;
assign rd_en8 = wr_en9;
assign rd_en9 = wr_en10;
assign rd_en10 = wr_en11;
assign rd_en11 = wr_en12;
assign rd_en12 = wr_en13;
assign rd_en13 = mat_flag;
assign mat_flag = row_cnt >= 11'd13 ? pi_flag : 1'b0;
assign mat_row1 = fifo1_rd_data;
assign mat_row2 = fifo2_rd_data;
assign mat_row3 = fifo3_rd_data;
assign mat_row4 = fifo4_rd_data;
assign mat_row5 = fifo5_rd_data;
assign mat_row6 = fifo6_rd_data;
assign mat_row7 = fifo7_rd_data;
assign mat_row8 = fifo8_rd_data;
assign mat_row9 = fifo9_rd_data;
assign mat_row10 = fifo10_rd_data;
assign mat_row11 = fifo11_rd_data;
assign mat_row12 = fifo12_rd_data;
assign mat_row13 = fifo13_rd_data;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
col_cnt <= 11'd0;
else if(col_cnt == COL_NUM-1 && pi_flag == 1'b1)
col_cnt <= 11'd0;
else if(pi_flag == 1'b1)
col_cnt <= col_cnt + 1'b1;
else
col_cnt <= col_cnt;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
row_cnt <= 11'd0;
else if(row_cnt == ROW_NUM-1 && col_cnt == COL_NUM-1 && pi_flag == 1'b1)
row_cnt <= 11'd0;
else if(col_cnt == COL_NUM-1 && pi_flag == 1'b1)
row_cnt <= row_cnt + 1'b1;
fifo_generator_4 mat_fifo1 (
.clk (sclk ), // input wire clk
.srst (~rst_n ), // input wire srst
.din (rx_data ), // input wire [7 : 0] din
.wr_en (wr_en1 ), // input wire wr_en
.rd_en (rd_en1 ), // input wire rd_en
.dout (fifo1_rd_data ), // output wire [7 : 0] dout
.full ( ), // output wire full
.empty ( ) // output wire empty
);
fifo_generator_4 mat_fifo2 (
.clk (sclk ), // input wire clk
.srst (~rst_n ), // input wire srst
.din (fifo1_rd_data ), // input wire [7 : 0] din
.wr_en (wr_en2 ), // input wire wr_en
.rd_en (rd_en2 ), // input wire rd_en
.dout (fifo2_rd_data ), // output wire [7 : 0] dout
.full ( ), // output wire full
.empty ( ) // output wire empty
);
fifo_generator_4 mat_fifo3 (
.clk (sclk ), // input wire clk
.srst (~rst_n ), // input wire srst
.din (fifo2_rd_data ), // input wire [7 : 0] din
.wr_en (wr_en3 ), // input wire wr_en
.rd_en (rd_en3 ), // input wire rd_en
.dout (fifo3_rd_data ), // output wire [7 : 0] dout
.full ( ), // output wire full
.empty ( ) // output wire empty
);
fifo_generator_4 mat_fifo4 (
.clk (sclk ), // input wire clk
.srst (~rst_n ), // input wire srst
.din (fifo3_rd_data ), // input wire [7 : 0] din
.wr_en (wr_en4 ), // input wire wr_en
.rd_en (rd_en4 ), // input wire rd_en
.dout (fifo4_rd_data ), // output wire [7 : 0] dout
.full ( ), // output wire full
.empty ( ) // output wire empty
);
fifo_generator_4 mat_fifo5 (
.clk (sclk ), // input wire clk
.srst (~rst_n ), // input wire srst
.din (fifo4_rd_data ), // input wire [7 : 0] din
.wr_en (wr_en5 ), // input wire wr_en
.rd_en (rd_en5 ), // input wire rd_en
.dout (fifo5_rd_data ), // output wire [7 : 0] dout
.full ( ), // output wire full
.empty ( ) // output wire empty
);
fifo_generator_4 mat_fifo6 (
.clk (sclk ), // input wire clk
.srst (~rst_n ), // input wire srst
.din (fifo5_rd_data ), // input wire [7 : 0] din
.wr_en (wr_en6 ), // input wire wr_en
.rd_en (rd_en6 ), // input wire rd_en
.dout (fifo6_rd_data ), // output wire [7 : 0] dout
.full ( ), // output wire full
.empty ( ) // output wire empty
);
fifo_generator_4 mat_fifo7 (
.clk (sclk ), // input wire clk
.srst (~rst_n ), // input wire srst
.din (fifo6_rd_data ), // input wire [7 : 0] din
.wr_en (wr_en7 ), // input wire wr_en
.rd_en (rd_en7 ), // input wire rd_en
.dout (fifo7_rd_data ), // output wire [7 : 0] dout
.full ( ), // output wire full
.empty ( ) // output wire empty
);
fifo_generator_4 mat_fifo8 (
.clk (sclk ), // input wire clk
.srst (~rst_n ), // input wire srst
.din (fifo7_rd_data ), // input wire [7 : 0] din
.wr_en (wr_en8 ), // input wire wr_en
.rd_en (rd_en8 ), // input wire rd_en
.dout (fifo8_rd_data ), // output wire [7 : 0] dout
.full ( ), // output wire full
.empty ( ) // output wire empty
);
fifo_generator_4 mat_fifo9 (
.clk (sclk ), // input wire clk
.srst (~rst_n ), // input wire srst
.din (fifo8_rd_data ), // input wire [7 : 0] din
.wr_en (wr_en9 ), // input wire wr_en
.rd_en (rd_en9 ), // input wire rd_en
.dout (fifo9_rd_data ), // output wire [7 : 0] dout
.full ( ), // output wire full
.empty ( ) // output wire empty
);
fifo_generator_4 mat_fifo10 (
.clk (sclk ), // input wire clk
.srst (~rst_n ), // input wire srst
.din (fifo9_rd_data ), // input wire [7 : 0] din
.wr_en (wr_en10 ), // input wire wr_en
.rd_en (rd_en10 ), // input wire rd_en
.dout (fifo10_rd_data ), // output wire [7 : 0] dout
.full ( ), // output wire full
.empty ( ) // output wire empty
);
fifo_generator_4 mat_fifo11 (
.clk (sclk ), // input wire clk
.srst (~rst_n ), // input wire srst
.din (fifo10_rd_data ), // input wire [7 : 0] din
.wr_en (wr_en11 ), // input wire wr_en
.rd_en (rd_en11 ), // input wire rd_en
.dout (fifo11_rd_data ), // output wire [7 : 0] dout
.full ( ), // output wire full
.empty ( ) // output wire empty
);
fifo_generator_4 mat_fifo12 (
.clk (sclk ), // input wire clk
.srst (~rst_n ), // input wire srst
.din (fifo11_rd_data ), // input wire [7 : 0] din
.wr_en (wr_en12 ), // input wire wr_en
.rd_en (rd_en12 ), // input wire rd_en
.dout (fifo12_rd_data ), // output wire [7 : 0] dout
.full ( ), // output wire full
.empty ( ) // output wire empty
);
fifo_generator_4 mat_fifo13 (
.clk (sclk ), // input wire clk
.srst (~rst_n ), // input wire srst
.din (fifo12_rd_data ), // input wire [7 : 0] din
.wr_en (wr_en13 ), // input wire wr_en
.rd_en (rd_en13 ), // input wire rd_en
.dout (fifo13_rd_data ), // output wire [7 : 0] dout
.full ( ), // output wire full
.empty ( ) // output wire empty
);
endmodule
腐蚀模块代码:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : erode.v
// Create Time : 2020-04-11 22:40:12
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module erode(
//System Interfaces
input sclk ,
input rst_n ,
//Communication Interfaces
input [ 7:0] rx_data ,
input pi_flag ,
output reg [ 7:0] tx_data ,
output wire po_flag
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
wire [ 7:0] mat_row1 ;
wire [ 7:0] mat_row2 ;
wire [ 7:0] mat_row3 ;
wire [ 7:0] mat_row4 ;
wire [ 7:0] mat_row5 ;
wire [ 7:0] mat_row6 ;
wire [ 7:0] mat_row7 ;
wire [ 7:0] mat_row8 ;
wire [ 7:0] mat_row9 ;
wire [ 7:0] mat_row10 ;
wire [ 7:0] mat_row11 ;
wire [ 7:0] mat_row12 ;
wire [ 7:0] mat_row13 ;
reg [ 7:0] mat_row1_r[12:0] ;
reg [ 7:0] mat_row2_r[12:0] ;
reg [ 7:0] mat_row3_r[12:0] ;
reg [ 7:0] mat_row4_r[12:0] ;
reg [ 7:0] mat_row5_r[12:0] ;
reg [ 7:0] mat_row6_r[12:0] ;
reg [ 7:0] mat_row7_r[12:0] ;
reg [ 7:0] mat_row8_r[12:0] ;
reg [ 7:0] mat_row9_r[12:0] ;
reg [ 7:0] mat_row10_r[12:0] ;
reg [ 7:0] mat_row11_r[12:0] ;
reg [ 7:0] mat_row12_r[12:0] ;
reg [ 7:0] mat_row13_r[12:0] ;
wire mat_flag ;
reg mat_flag_r1 ;
reg mat_flag_r2 ;
reg mat_flag_r3 ;
reg mat_flag_r4 ;
reg mat_flag_r5 ;
reg mat_flag_r6 ;
reg mat_flag_r7 ;
reg mat_flag_r8 ;
reg mat_flag_r9 ;
reg mat_flag_r10 ;
reg mat_flag_r11 ;
reg mat_flag_r12 ;
reg mat_flag_r13 ;
reg mat_flag_r14 ;
reg mat_flag_r15 ;
reg mat_flag_r16 ;
reg erode_flag1 ;
reg erode_flag2 ;
reg erode_flag3 ;
reg erode_flag4 ;
reg erode_flag5 ;
reg erode_flag6 ;
reg erode_flag7 ;
reg erode_flag8 ;
reg erode_flag9 ;
reg erode_flag10 ;
reg erode_flag11 ;
reg erode_flag12 ;
reg erode_flag13 ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign po_flag = mat_flag_r16 && mat_flag_r3;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)begin
mat_row1_r[0] <= 8'd0;
mat_row2_r[0] <= 8'd0;
mat_row3_r[0] <= 8'd0;
mat_row4_r[0] <= 8'd0;
mat_row5_r[0] <= 8'd0;
mat_row6_r[0] <= 8'd0;
mat_row7_r[0] <= 8'd0;
mat_row8_r[0] <= 8'd0;
mat_row9_r[0] <= 8'd0;
mat_row10_r[0] <= 8'd0;
mat_row11_r[0] <= 8'd0;
mat_row12_r[0] <= 8'd0;
mat_row13_r[0] <= 8'd0;
end else begin
mat_row1_r[0] <= mat_row1;
mat_row2_r[0] <= mat_row2;
mat_row3_r[0] <= mat_row3;
mat_row4_r[0] <= mat_row4;
mat_row5_r[0] <= mat_row5;
mat_row6_r[0] <= mat_row6;
mat_row7_r[0] <= mat_row7;
mat_row8_r[0] <= mat_row8;
mat_row9_r[0] <= mat_row9;
mat_row10_r[0] <= mat_row10;
mat_row11_r[0] <= mat_row11;
mat_row12_r[0] <= mat_row12;
mat_row13_r[0] <= mat_row13;
end
genvar i;
generate
for (i=1; i < 13; i=i+1)
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
mat_row1_r[i] <= 8'd0;
else
mat_row1_r[i] <= mat_row1_r[i-1];
endgenerate
generate
for (i=1; i < 13; i=i+1)
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
mat_row2_r[i] <= 8'd0;
else
mat_row2_r[i] <= mat_row2_r[i-1];
endgenerate
generate
for (i=1; i < 13; i=i+1)
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
mat_row3_r[i] <= 8'd0;
else
mat_row3_r[i] <= mat_row3_r[i-1];
endgenerate
generate
for (i=1; i < 13; i=i+1)
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
mat_row4_r[i] <= 8'd0;
else
mat_row4_r[i] <= mat_row4_r[i-1];
endgenerate
generate
for (i=1; i < 13; i=i+1)
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
mat_row5_r[i] <= 8'd0;
else
mat_row5_r[i] <= mat_row5_r[i-1];
endgenerate
generate
for (i=1; i < 13; i=i+1)
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
mat_row6_r[i] <= 8'd0;
else
mat_row6_r[i] <= mat_row6_r[i-1];
endgenerate
generate
for (i=1; i < 13; i=i+1)
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
mat_row7_r[i] <= 8'd0;
else
mat_row7_r[i] <= mat_row7_r[i-1];
endgenerate
generate
for (i=1; i < 13; i=i+1)
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
mat_row8_r[i] <= 8'd0;
else
mat_row8_r[i] <= mat_row8_r[i-1];
endgenerate
generate
for (i=1; i < 13; i=i+1)
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
mat_row9_r[i] <= 8'd0;
else
mat_row9_r[i] <= mat_row9_r[i-1];
endgenerate
generate
for (i=1; i < 13; i=i+1)
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
mat_row10_r[i] <= 8'd0;
else
mat_row10_r[i] <= mat_row10_r[i-1];
endgenerate
generate
for (i=1; i < 13; i=i+1)
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
mat_row11_r[i] <= 8'd0;
else
mat_row11_r[i] <= mat_row11_r[i-1];
endgenerate
generate
for (i=1; i < 13; i=i+1)
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
mat_row12_r[i] <= 8'd0;
else
mat_row12_r[i] <= mat_row12_r[i-1];
endgenerate
generate
for (i=1; i < 13; i=i+1)
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
mat_row13_r[i] <= 8'd0;
else
mat_row13_r[i] <= mat_row13_r[i-1];
endgenerate
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
erode_flag1 <= 1'b0;
else if(mat_row1_r[12] == 255 && mat_row1_r[11] == 255 && mat_row1_r[10] == 255 && mat_row1_r[9] == 255 && mat_row1_r[8] == 255 && mat_row1_r[7] == 255 &&
mat_row1_r[6] == 255 && mat_row1_r[5] == 255 && mat_row1_r[4] == 255 && mat_row1_r[3] == 255 && mat_row1_r[2] == 255 && mat_row1_r[1] == 255 && mat_row1_r[0] == 255)
erode_flag1 <= 1'b1;
else
erode_flag1 <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
erode_flag2 <= 1'b0;
else if(mat_row2_r[12] == 255 && mat_row2_r[11] == 255 && mat_row2_r[10] == 255 && mat_row2_r[9] == 255 && mat_row2_r[8] == 255 && mat_row2_r[7] == 255 &&
mat_row2_r[6] == 255 && mat_row2_r[5] == 255 && mat_row2_r[4] == 255 && mat_row2_r[3] == 255 && mat_row2_r[2] == 255 && mat_row2_r[1] == 255 && mat_row2_r[0] == 255)
erode_flag2 <= 1'b1;
else
erode_flag2 <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
erode_flag3 <= 1'b0;
else if(mat_row3_r[12] == 255 && mat_row3_r[11] == 255 && mat_row3_r[10] == 255 && mat_row3_r[9] == 255 && mat_row3_r[8] == 255 && mat_row3_r[7] == 255 &&
mat_row3_r[6] == 255 && mat_row3_r[5] == 255 && mat_row3_r[4] == 255 && mat_row3_r[3] == 255 && mat_row3_r[2] == 255 && mat_row3_r[1] == 255 && mat_row3_r[0] == 255)
erode_flag3 <= 1'b1;
else
erode_flag3 <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
erode_flag4 <= 1'b0;
else if(mat_row4_r[12] == 255 && mat_row4_r[11] == 255 && mat_row4_r[10] == 255 && mat_row4_r[9] == 255 && mat_row4_r[8] == 255 && mat_row4_r[7] == 255 &&
mat_row4_r[6] == 255 && mat_row4_r[5] == 255 && mat_row4_r[4] == 255 && mat_row4_r[3] == 255 && mat_row4_r[2] == 255 && mat_row4_r[1] == 255 && mat_row4_r[0] == 255)
erode_flag4 <= 1'b1;
else
erode_flag4 <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
erode_flag5 <= 1'b0;
else if(mat_row5_r[12] == 255 && mat_row5_r[11] == 255 && mat_row5_r[10] == 255 && mat_row5_r[9] == 255 && mat_row5_r[8] == 255 && mat_row5_r[7] == 255 &&
mat_row5_r[6] == 255 && mat_row5_r[5] == 255 && mat_row5_r[4] == 255 && mat_row5_r[3] == 255 && mat_row5_r[2] == 255 && mat_row5_r[1] == 255 && mat_row5_r[0] == 255)
erode_flag5 <= 1'b1;
else
erode_flag5 <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
erode_flag6 <= 1'b0;
else if(mat_row6_r[12] == 255 && mat_row6_r[11] == 255 && mat_row6_r[10] == 255 && mat_row6_r[9] == 255 && mat_row6_r[8] == 255 && mat_row6_r[7] == 255 &&
mat_row6_r[6] == 255 && mat_row6_r[5] == 255 && mat_row6_r[4] == 255 && mat_row6_r[3] == 255 && mat_row6_r[2] == 255 && mat_row6_r[1] == 255 && mat_row6_r[0] == 255)
erode_flag6 <= 1'b1;
else
erode_flag6 <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
erode_flag7 <= 1'b0;
else if(mat_row7_r[12] == 255 && mat_row7_r[11] == 255 && mat_row7_r[10] == 255 && mat_row7_r[9] == 255 && mat_row7_r[8] == 255 && mat_row7_r[7] == 255 &&
mat_row7_r[6] == 255 && mat_row7_r[5] == 255 && mat_row7_r[4] == 255 && mat_row7_r[3] == 255 && mat_row7_r[2] == 255 && mat_row7_r[1] == 255 && mat_row7_r[0] == 255)
erode_flag7 <= 1'b1;
else
erode_flag7 <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
erode_flag8 <= 1'b0;
else if(mat_row8_r[12] == 255 && mat_row8_r[11] == 255 && mat_row8_r[10] == 255 && mat_row8_r[9] == 255 && mat_row8_r[8] == 255 && mat_row8_r[7] == 255 &&
mat_row8_r[6] == 255 && mat_row8_r[5] == 255 && mat_row8_r[4] == 255 && mat_row8_r[3] == 255 && mat_row8_r[2] == 255 && mat_row8_r[1] == 255 && mat_row8_r[0] == 255)
erode_flag8 <= 1'b1;
else
erode_flag8 <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
erode_flag9 <= 1'b0;
else if(mat_row9_r[12] == 255 && mat_row9_r[11] == 255 && mat_row9_r[10] == 255 && mat_row9_r[9] == 255 && mat_row9_r[8] == 255 && mat_row9_r[7] == 255 &&
mat_row9_r[6] == 255 && mat_row9_r[5] == 255 && mat_row9_r[4] == 255 && mat_row9_r[3] == 255 && mat_row9_r[2] == 255 && mat_row9_r[1] == 255 && mat_row9_r[0] == 255)
erode_flag9 <= 1'b1;
else
erode_flag9 <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
erode_flag10 <= 1'b0;
else if(mat_row10_r[12] == 255 && mat_row10_r[11] == 255 && mat_row10_r[10] == 255 && mat_row10_r[9] == 255 && mat_row10_r[8] == 255 && mat_row10_r[7] == 255 &&
mat_row10_r[6] == 255 && mat_row10_r[5] == 255 && mat_row10_r[4] == 255 && mat_row10_r[3] == 255 && mat_row10_r[2] == 255 && mat_row10_r[1] == 255 && mat_row10_r[0] == 255)
erode_flag10 <= 1'b1;
else
erode_flag10 <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
erode_flag11 <= 1'b0;
else if(mat_row11_r[12] == 255 && mat_row11_r[11] == 255 && mat_row11_r[10] == 255 && mat_row11_r[9] == 255 && mat_row11_r[8] == 255 && mat_row11_r[7] == 255 &&
mat_row11_r[6] == 255 && mat_row11_r[5] == 255 && mat_row11_r[4] == 255 && mat_row11_r[3] == 255 && mat_row11_r[2] == 255 && mat_row11_r[1] == 255 && mat_row11_r[0] == 255)
erode_flag11 <= 1'b1;
else
erode_flag11 <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
erode_flag12 <= 1'b0;
else if(mat_row12_r[12] == 255 && mat_row12_r[11] == 255 && mat_row12_r[10] == 255 && mat_row12_r[9] == 255 && mat_row12_r[8] == 255 && mat_row12_r[7] == 255 &&
mat_row12_r[6] == 255 && mat_row12_r[5] == 255 && mat_row12_r[4] == 255 && mat_row12_r[3] == 255 && mat_row12_r[2] == 255 && mat_row12_r[1] == 255 && mat_row12_r[0] == 255)
erode_flag12 <= 1'b1;
else
erode_flag12 <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
erode_flag13 <= 1'b0;
else if(mat_row13_r[12] == 255 && mat_row13_r[11] == 255 && mat_row13_r[10] == 255 && mat_row13_r[9] == 255 && mat_row13_r[8] == 255 && mat_row13_r[7] == 255 &&
mat_row13_r[6] == 255 && mat_row13_r[5] == 255 && mat_row13_r[4] == 255 && mat_row13_r[3] == 255 && mat_row13_r[2] == 255 && mat_row13_r[1] == 255 && mat_row13_r[0] == 255)
erode_flag13 <= 1'b1;
else
erode_flag13 <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
tx_data <= 8'd0;
else if(erode_flag12 == 1'b1 && erode_flag11 == 1'b1 && erode_flag10 == 1'b1 && erode_flag9 == 1'b1 && erode_flag8 == 1'b1 && erode_flag7 == 1'b1 && erode_flag6 == 1'b1 &&
erode_flag5 == 1'b1 && erode_flag4 == 1'b1 && erode_flag3 == 1'b1 && erode_flag2 == 1'b1 && erode_flag1 == 1'b1 && erode_flag13 == 1'b1)
tx_data <= 8'd255;
else
tx_data <= 8'd0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)begin
mat_flag_r1 <= 1'b0;
mat_flag_r2 <= 1'b0;
mat_flag_r3 <= 1'b0;
mat_flag_r4 <= 1'b0;
mat_flag_r5 <= 1'b0;
mat_flag_r6 <= 1'b0;
mat_flag_r7 <= 1'b0;
mat_flag_r8 <= 1'b0;
mat_flag_r9 <= 1'b0;
mat_flag_r10 <= 1'b0;
mat_flag_r11 <= 1'b0;
mat_flag_r12 <= 1'b0;
mat_flag_r13 <= 1'b0;
mat_flag_r14 <= 1'b0;
mat_flag_r15 <= 1'b0;
mat_flag_r16 <= 1'b0;
end else begin
mat_flag_r1 <= mat_flag;
mat_flag_r2 <= mat_flag_r1;
mat_flag_r3 <= mat_flag_r2;
mat_flag_r4 <= mat_flag_r3;
mat_flag_r5 <= mat_flag_r4;
mat_flag_r6 <= mat_flag_r5;
mat_flag_r7 <= mat_flag_r6;
mat_flag_r8 <= mat_flag_r7;
mat_flag_r9 <= mat_flag_r8;
mat_flag_r10 <= mat_flag_r9;
mat_flag_r11 <= mat_flag_r10;
mat_flag_r12 <= mat_flag_r11;
mat_flag_r13 <= mat_flag_r12;
mat_flag_r14 <= mat_flag_r13;
mat_flag_r15 <= mat_flag_r14;
mat_flag_r16 <= mat_flag_r15;
end
mat_13x13 mat_13x13_inst(
//System Interfaces
.sclk (sclk ),
.rst_n (rst_n ),
//Communication Interfaces
.rx_data (rx_data ),
.pi_flag (pi_flag ),
.mat_row1 (mat_row1 ),
.mat_row2 (mat_row2 ),
.mat_row3 (mat_row3 ),
.mat_row4 (mat_row4 ),
.mat_row5 (mat_row5 ),
.mat_row6 (mat_row6 ),
.mat_row7 (mat_row7 ),
.mat_row8 (mat_row8 ),
.mat_row9 (mat_row9 ),
.mat_row10 (mat_row10 ),
.mat_row11 (mat_row11 ),
.mat_row12 (mat_row12 ),
.mat_row13 (mat_row13 ),
.mat_flag (mat_flag )
);
endmodule
上面的代码写的很简洁有技巧,很值得大家借鉴,因为13*13的矩阵涉及了太多的元素。
腐蚀之后的图像
腐蚀之后的图像:
图像定位
图像定位与画框的逻辑流程和MATLAB代码中的完全相同,我们这里不在多加赘述。
图像定位代码
图像定位的代码如下,face_seek模块:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : face_seek.v
// Create Time : 2020-04-13 22:47:21
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module face_seek(
//System Interfaces
input sclk ,
input rst_n ,
//Communication Interfaces
input [ 7:0] rx_data ,
input pi_flag ,
output reg [10:0] x_min ,
output reg [10:0] x_max ,
output reg [10:0] y_min ,
output reg [10:0] y_max ,
output reg po_flag
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
parameter ROW_NUM = 768-13 ;
parameter COL_NUM = 1024 ;
reg [10:0] row_cnt ;
reg [10:0] col_cnt ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
col_cnt <= 11'd0;
else if(col_cnt == COL_NUM-1 && pi_flag == 1'b1)
col_cnt <= 11'd0;
else if(pi_flag == 1'b1)
col_cnt <= col_cnt + 1'b1;
else
col_cnt <= col_cnt;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
row_cnt <= 11'd0;
else if(row_cnt == ROW_NUM-1 && col_cnt == COL_NUM-1 && pi_flag == 1'b1)
row_cnt <= 11'd0;
else if(col_cnt == COL_NUM-1 && pi_flag == 1'b1)
row_cnt <= row_cnt + 1'b1;
else
row_cnt <= row_cnt;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
po_flag <= 1'b0;
else if(row_cnt == ROW_NUM-1 && col_cnt == COL_NUM-1 && pi_flag == 1'b1)
po_flag <= 1'b1;
else
po_flag <= 1'b0;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
x_min <= 11'd1023;
else if(po_flag == 1'b1)
x_min <= 11'd1023;
else if(rx_data > 0 && pi_flag == 1'b1 && x_min > col_cnt)
x_min <= col_cnt;
else
x_min <= x_min;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
x_max <= 11'd0;
else if(po_flag == 1'b1)
x_max <= 11'd0;
else if(rx_data > 0 && pi_flag == 1'b1 && x_max < col_cnt)
x_max <= col_cnt;
else
x_max <= x_max;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
y_min <= 11'd755;
else if(po_flag == 1'b1)
y_min <= 11'd755;
else if(rx_data > 0 && pi_flag == 1'b1 && y_min > row_cnt)
y_min <= row_cnt;
else
y_min <= y_min;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
y_max <= 11'd0;
else if(po_flag == 1'b1)
y_max <= 11'd0;
else if(rx_data > 0 && pi_flag == 1'b1 && y_max < row_cnt)
y_max <= row_cnt;
else
y_max <= y_max;
endmodule
画框的代码在输出图像的部分进行操作,usb3_drive模块代码如下:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : usb3_drive.v
// Create Time : 2020-03-03 10:36:21
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module usb3_drive(
input rst_n ,
output wire USBSS_EN ,
input sclk ,
inout [15:0] data ,
inout [ 1:0] be ,
input rxf_n ,
input txf_n ,
output reg oe_n ,
output reg wr_n ,
output wire siwu_n ,
output reg rd_n ,
output wire wakeup ,
output wire [ 1:0] gpio ,
//Communication Interfaces
input [15:0] data_in ,
output wire data_req ,
input [10:0] x_min ,
input [10:0] x_max ,
input [10:0] y_min ,
input [10:0] y_max ,
input po_flag
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
parameter COL_NUM = 1024*2 ;
parameter ROW_NUM = 768 ;
parameter IDLE = 4'b0001 ;
parameter JUDGE = 4'b0010 ;
parameter READ = 4'b0100 ;
parameter WRITE = 4'b1000 ;
reg [ 3:0] state ;
wire fifo_wr ;
wire [15:0] data_wr ;
reg [12:0] col_cnt ;
reg [12:0] row_cnt ;
reg [10:0] x_min_r ;
reg [10:0] x_max_r ;
reg [10:0] y_min_r ;
reg [10:0] y_max_r ;
reg [15:0] data_o ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
assign USBSS_EN = 1'b1;
assign wakeup = 1'b1;
assign siwu_n = 1'b0;
assign gpio = 2'b00;
assign fifo_wr = (rd_n == 1'b0) && (rxf_n == 1'b0);
assign data_wr = (state == READ) ? data : 16'hzzzz;
assign data_req = ~((wr_n == 1'b0) && (txf_n == 1'b0));
assign data = (data_req == 1'b0) ? data_o : 16'hzzzz;
assign be = (state == WRITE) ? 2'b11 : 2'bzz;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
state <= IDLE;
else case(state)
IDLE : state <= JUDGE;
JUDGE : if(rxf_n == 1'b0)
state <= READ;
else if(txf_n == 1'b0)
state <= WRITE;
else
state <= JUDGE;
WRITE : if(txf_n == 1'b1)
state <= JUDGE;
else
state <= WRITE;
READ : if(rxf_n == 1'b1)
state <= JUDGE;
else
state <= READ;
default : state <= IDLE;
endcase
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
oe_n <= 1'b1;
else if(state == READ && rxf_n == 1'b1)
oe_n <= 1'b1;
else if(state == READ)
oe_n <= 1'b0;
else
oe_n <= oe_n;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
rd_n <= 1'b1;
else if(state == READ && rxf_n == 1'b1)
rd_n <= 1'b1;
else if(state == READ && oe_n == 1'b0)
rd_n <= 1'b0;
else
rd_n <= rd_n;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
wr_n <= 1'b1;
else if(state == WRITE && txf_n == 1'b1)
wr_n <= 1'b1;
else if(state == WRITE)
wr_n <= 1'b0;
else
wr_n <= wr_n;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
col_cnt <= 13'd0;
else if(data_req == 1'b0 && col_cnt == COL_NUM-1)
col_cnt <= 13'd0;
else if(data_req == 1'b0)
col_cnt <= col_cnt + 1'b1;
else
col_cnt <= col_cnt;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
row_cnt <= 13'd0;
else if(row_cnt == ROW_NUM-1 && data_req == 1'b0 && col_cnt == COL_NUM-1)
row_cnt <= 13'd0;
else if(data_req == 1'b0 && col_cnt == COL_NUM-1)
row_cnt <= row_cnt + 1'b1;
else
row_cnt <= row_cnt;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
x_min_r <= COL_NUM - 1'b1;
else if(po_flag == 1'b1)
x_min_r <= x_min;
else
x_min_r <= x_min_r;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
x_max_r <= 0;
else if(po_flag == 1'b1)
x_max_r <= x_max;
else
x_max_r <= x_max_r;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
y_min_r <= ROW_NUM - 1'b1;
else if(po_flag == 1'b1)
y_min_r <= y_min;
else
y_min_r <= y_min_r;
always @(posedge sclk or negedge rst_n)
if(rst_n == 1'b0)
y_max_r <= 0;
else if(po_flag == 1'b1)
y_max_r <= y_max;
else
y_max_r <= y_max_r;
always @(*)
if(row_cnt == y_min_r && col_cnt >= x_min_r*2 && col_cnt < x_max_r*2)
data_o <= 16'hffff;
else if(row_cnt == y_max_r && col_cnt >= x_min_r*2 && col_cnt < x_max_r*2)
data_o <= 16'hffff;
else if((col_cnt >= x_min_r*2 && col_cnt < (x_min_r+1)*2) && row_cnt >= y_min_r && row_cnt < y_max_r)
data_o <= 16'hffff;
else if((col_cnt >= x_max_r*2 && col_cnt < (x_max_r+1)*2) && row_cnt >= y_min_r && row_cnt < y_max_r)
data_o <= 16'hffff;
else if(row_cnt == y_min_r && col_cnt >= x_min_r*2 && col_cnt < x_max_r*2)
data_o <= 16'hffff;
else if(row_cnt == y_max_r && col_cnt >= x_min_r*2 && col_cnt < x_max_r*2)
data_o <= 16'hffff;
else
data_o <= data_in;
//========================================================================================\
//******************************* Debug **********************************
//========================================================================================/
ila_0 ila_0_inst (
.clk (sclk ), // input wire clk
.probe0 (x_min_r ), // input wire [10:0] probe0
.probe1 (x_max_r ), // input wire [10:0] probe1
.probe2 (y_min_r ), // input wire [10:0] probe2
.probe3 (y_max_r ), // input wire [10:0] probe3
.probe4 (po_flag ), // input wire [0:0] probe4
.probe5 (row_cnt ), // input wire [12:0] probe5
.probe6 (col_cnt ), // input wire [12:0] probe6
.probe7 (data_o ) // input wire [15:0] probe7
);
endmodule
最终图像结果
我们最终实验的结果如下:
从上面的图像可以看出我们成功的实现了图像定位。
这里因为CSDN博客字数的限制,工程源码我们将在第二篇博客中给出。需要的同学可以自取。
总结
创作不易,认为文章有帮助的同学们可以关注、点赞、转发支持。原工程在群中,需要的同学可以进群自取。或者对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群: