✅博主简介:本人擅长数据处理、建模仿真、程序设计、论文写作与指导,项目与课题经验交流。项目合作可私信或扫描文章底部二维码。
一、系统总体设计
该人脸检测与跟踪系统基于FPGA平台,主要硬件包括CMOS摄像头、TFT-LCD显示屏、SDRAM存储芯片以及CycloneIV系列FPGA主控芯片。系统通过摄像头实时采集图像,在FPGA中进行人脸检测与跟踪处理,最终在LCD屏上显示结果。设计中,使用Verilog HDL对各个模块进行编写,并通过Modelsim仿真验证每个模块的功能,确保其正确实现。
系统的主要功能流程如下:
- 摄像头实时采集图像数据,送入FPGA。
- 图像数据在FPGA中进行格式转换和预处理。
- 通过改进的肤色分割算法提取人脸区域。
- 形态学处理去除噪点,得到更精确的人脸区域。
- 对人脸区域进行检测、定位,并在LCD屏上进行矩形标记显示。
二、图像数据格式转换模块
由于摄像头采集到的图像数据通常以YCbCr422格式输出,而后续处理需要YCbCr444和RGB格式的数据,因此需要对采集到的数据进行格式转换。
1. YCbCr422转YCbCr444模块
YCbCr422格式是每两个像素共享一个色度值(Cb和Cr),而YCbCr444格式每个像素都有独立的色度值。为了提高人脸检测的准确性,需要将数据从YCbCr422转换为YCbCr444格式。
- 转换原理:对于每两个像素,YCbCr422只提供了一个Cb和Cr值。转换时,将Cb和Cr的值复制给两个像素,使其成为YCbCr444格式。
- 硬件实现:利用FPGA的并行处理能力,设计流水线结构,实现对每一行像素数据的快速转换。
2. YCbCr转RGB模块
后续的人脸检测和显示需要RGB格式的数据,因此需要将YCbCr444格式转换为RGB格式。
三、改进型椭圆肤色分割模块
人脸检测的关键在于准确识别人脸区域。为了有效提取人脸区域,采用了改进型椭圆肤色分割算法。该算法通过肤色特征区分人脸与非人脸区域。
1. 白平衡算法
在进行肤色分割前,首先应用白平衡算法调整图像的颜色偏差,减少不同光照条件对肤色检测的影响。
- 算法原理:根据图像的整体亮度信息,对图像的颜色分量进行均衡处理,使图像的颜色更接近真实场景。
2. 椭圆肤色分割
基于YCbCr色彩空间的肤色分割,定义了一个椭圆形肤色区域,用于区分人脸与背景。椭圆肤色分割算法在色度平面(Cb-Cr平面)上设置一个椭圆区域,判断每个像素是否属于肤色范围。
- 椭圆方程:通过设定Cb和Cr的中心和长短轴参数,确定椭圆区域。对于每个像素,如果其(Cb, Cr)值落在椭圆内,则判定为肤色像素。
- 硬件实现:在FPGA中利用比较和乘法器实现椭圆方程的判断,将满足条件的像素标记为人脸区域。
四、形态学处理模块
在肤色分割得到人脸区域后,图像中可能包含一些噪点或不完整的人脸区域。为此,使用形态学处理对图像进行进一步处理,包括腐蚀和膨胀操作。
- 腐蚀:去除图像中的孤立噪点,保留主要的人脸区域轮廓。
- 膨胀:增强人脸区域的连通性,使人脸区域更加完整。
通过形态学处理,可以进一步优化人脸区域的检测结果,提高定位的准确性。
五、人脸检测与定位模块
经过前面的处理,获得了候选的人脸区域。接下来需要对这些区域进行检测与定位,确定最终的人脸位置。
- 区域检测:通过扫描图像的肤色区域,找到可能的人脸区域。根据面积和形状特征筛选出符合人脸特征的区域。
- 定位与跟踪:对于确定的人脸区域,提取其边界框信息(矩形坐标),用于在显示屏上进行标记和跟踪。为了实现跟踪,使用卡尔曼滤波器或简单的移动平均算法,对人脸的位置进行平滑处理,跟踪人脸的运动轨迹。
六、人脸矩形标记与显示
人脸检测与定位后,系统需要在LCD屏上实时显示检测结果。通过对人脸区域进行矩形标记,将检测到的人脸框出,方便用户观察。
- 矩形标记:根据检测到的人脸区域坐标,在LCD屏的图像上绘制矩形框,标记出人脸位置。
- 实时显示:通过将标记后的图像数据发送至TFT-LCD显示屏,实时显示人脸检测与跟踪的结果。
-
module skin_segmentation ( input wire clk, input wire rst_n, input wire [7:0] Y, // Y分量 input wire [7:0] Cb, // Cb分量 input wire [7:0] Cr, // Cr分量 output reg skin_detected // 检测到肤色区域标志 ); // 椭圆参数 parameter Cb_center = 8'd104; // 椭圆中心Cb值 parameter Cr_center = 8'd150; // 椭圆中心Cr值 parameter A = 8'd23; // 长轴 parameter B = 8'd15; // 短轴 reg signed [15:0] cb_diff, cr_diff; reg signed [31:0] ellipse_val; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin skin_detected <= 1'b0; end else begin // 计算Cb和Cr差值 cb_diff <= Cb - Cb_center; cr_diff <= Cr - Cr_center; // 椭圆方程计算 ellipse_val <= (cb_diff * cb_diff) / (A * A) + (cr_diff * cr_diff) / (B * B); // 判断是否在椭圆内 if (ellipse_val <= 32'd1) skin_detected <= 1'b1; else skin_detected <= 1'b0; end end endmodule
3