基于肤色模型和中值滤波的手部检测算法FPGA实现,包括tb测试文件和MATLAB辅助验证

136 阅读2分钟

1.算法运行效果图预览

RTL图:

0c42c5c36783742623f84d21641b2306_82780907_202403101201510496379195_Expires=1710043911&Signature=%2FU7u1LG3vY3zTQnYON6275XeJGQ%3D&domain=8.jpeg

 

仿真图:

5383c477499df811be51d70c84a56e7b_82780907_202403101201210070348611_Expires=1710043881&Signature=Y%2Fm0qEG2cFwQ0ggFZhnphcjbSmY%3D&domain=8.jpeg  

导入到matlab显示效果如下:

78026006790a27fbba52b7ae0a52ccc8_82780907_202403101200440334557523_Expires=1710043844&Signature=%2FlIAIM%2Bht2NcamYQkuJSveYFc0o%3D&domain=8.jpeg  

2.算法运行软件版本

matlab2022a

 

vivado2019.2

 

3.算法理论概述

       在计算机视觉领域,基于肤色模型和中值滤波的手部检测方法是一种常见的初步定位策略。该方法主要分为两大部分:肤色分割以区分出图像中的皮肤区域,以及中值滤波以消除噪声并保持关键边缘信息。

 

3.1 肤色模型建立与应用

       肤色模型是基于人手的肤色特征建立的一种颜色空间表示或概率分布模型,用于识别图像中的肤色像素点。一种常用的肤色模型是在YCbCr色彩空间下构建:

b209bc6f43e64a88be612329a7ef6bb0_82780907_202403101159050817625860_Expires=1710043745&Signature=pmFTqrqGxbbwoI%2BZM5ojs%2BD1aJ8%3D&domain=8.png

 

       其中 R、G、B 分别代表RGB三通道的像素值,Y 是亮度分量,Cb 和 Cr 是色度分量。根据统计分析,在特定范围内的 Cb 和 Cr 值可以很好地表征肤色。例如:

baa6d31c933bf758975400f6db2b8671_82780907_202403101158550973348734_Expires=1710043736&Signature=Q4Ibeofb2QnL9%2Fh1X3iFgRQo4UQ%3D&domain=8.png

3.2 中值滤波器的运用

        在初步确定肤色区域后,为了去除如光照变化、传感器噪声等导致的非结构噪声,通常采用 中值滤波 方法来平滑处理肤色区域:

5fc4fee8df50d2105d0b868bcfe8ec98_82780907_202403101158460270173770_Expires=1710043726&Signature=RpHFHxT9RcAqdsEWFZMeV24DjUM%3D&domain=8.png

        结合肤色模型与中值滤波的手部检测算法能够有效地从复杂背景中分离出手部区域。实际应用时,还需要考虑光照、视角变化等因素的影响,并可能结合其他高级计算机视觉技术(如机器学习分类器或深度学习模型)进行精确的手部姿态估计和跟踪。

 

 

 

 

4.部分核心程序 ``timescale 1ns / 1ps

 

module TEST();

 

reg i_clk;

reg i_rst;

reg [7:0] Isave[0:220000];

integer fids;

 

 

integer dat;

integer Pix_begin;

integer Sizes;

 

 

initial

begin

        fids = $fopen("D:\FPGA_Proj\FPGAtest\code\test.bmp","rb");

        dat  = $fread(Isave,fids);

        //有效像素起始位置

        Pix_begin = {Isave[13], Isave[12], Isave[11], Isave[10]};

        //尺寸

        Sizes     = {Isave[5], Isave[4], Isave[3], Isave[2]};

 

        $fclose(fids);

end

 

initial

begin

i_clk=1;

i_rst=1;

#1000

i_rst=0;

end

 

always #5  i_clk=~i_clk;

 

 

integer jj=0;

reg [7:0]R;

reg [7:0]G;

reg [7:0]B;

always@(posedge i_clk)

begin

        R<=Isave[jj+2];//这个datas可以用于输入到FPGA的后期处理

        G<=Isave[jj+1];//这个datas可以用于输入到FPGA的后期处理

        B<=Isave[jj];//这个datas可以用于输入到FPGA的后期处理

        jj<=jj+3;

end

 

 

wire [7:0]o_Rmed,o_Gmed,o_Bmed;

wire [7:0]o_Y;// Y

wire [7:0]o_Cr;// Y

wire [7:0]o_Cb;// Y

wire [7:0]o_hand_check;

 

 

tops tops_u(

.i_clk (i_clk),

.i_rst (i_rst),

.i_R   (R),

.i_G   (G),

.i_B   (B),

.o_Rmed       (o_Rmed),

.o_Gmed       (o_Gmed),

.o_Bmed       (o_Bmed),

.o_Y          (o_Y),// Y

.o_Cr         (o_Cr),// Y

.o_Cb         (o_Cb),// Y

.o_hand_check (o_hand_check)

);

 

integer fout1;

initial begin

 fout1 = $fopen("hand.txt","w");

end

 

always @ (posedge i_clk)

 begin

    if(jj<=65536*3+54 & jj>54)

        $fwrite(fout1,"%d\n",o_hand_check);

        else

        $fwrite(fout1,"%d\n",0);

end

endmodule`