基于AdaBoost算法的人脸检测原理与实现

一、AdaBoost人脸检测原理

1.1 基本思想

AdaBoost(Adaptive Boosting)是一种集成学习算法,通过组合多个弱分类器来构建一个强分类器。在人脸检测中,每个弱分类器基于简单的Haar-like特征进行决策。

1.2 Haar-like特征

Haar-like特征是通过计算图像中相邻矩形区域的像素和之差得到的,能够捕捉人脸的局部特征:

  • 边缘特征
  • 线性特征
  • 中心环绕特征

1.3 AdaBoost训练过程

  1. 初始化权重:为每个训练样本分配相等的权重
  2. 迭代训练
    • 训练弱分类器(基于单个Haar特征)
    • 选择错误率最小的弱分类器
    • 更新样本权重(增加错分样本的权重)
    • 计算该弱分类器的权重
  3. 组合强分类器:加权组合所有弱分类器

1.4 级联分类器

为提高检测效率,使用级联结构:

  • 前几层用少量特征快速排除非人脸区域
  • 后续层用更多特征进行精细判断

二、MATLAB实现代码

%% 基于AdaBoost的人脸检测MATLAB实现
clear; close all; clc;

%% 参数设置
numWeakClassifiers = 100;      % 弱分类器数量
positiveSamples = 100;         % 正样本数量(人脸)
negativeSamples = 200;         % 负样本数量(非人脸)
imageSize = [24, 24];          % 图像尺寸

%% 生成训练数据(示例)
fprintf('生成训练数据...\n');
[trainFeatures, trainLabels] = generateTrainingData(positiveSamples, negativeSamples, imageSize);

%% 训练AdaBoost分类器
fprintf('训练AdaBoost分类器...\n');
[classifiers, alphas] = trainAdaBoost(trainFeatures, trainLabels, numWeakClassifiers);

%% 测试分类器
fprintf('测试分类器...\n');
testAccuracy = testClassifier(classifiers, alphas, trainFeatures, trainLabels);
fprintf('训练集准确率: %.2f%%\n', testAccuracy * 100);

%% 在测试图像上进行人脸检测
fprintf('进行人脸检测...\n');
testImageDetection(classifiers, alphas, imageSize);

%% 生成训练数据函数
function [features, labels] = generateTrainingData(posSamples, negSamples, imgSize)
    % 这里应该从实际数据集中加载
    % 为演示目的,生成模拟数据
    
    totalSamples = posSamples + negSamples;
    features = zeros(totalSamples, prod(imgSize));
    labels = zeros(totalSamples, 1);
    
    % 生成正样本(简单的人脸模式)
    for i = 1:posSamples
        img = generateFacePattern(imgSize);
        features(i, :) = img(:);
        labels(i) = 1;
    end
    
    % 生成负样本(随机纹理)
    for i = posSamples+1:totalSamples
        img = rand(imgSize);
        features(i, :) = img(:);
        labels(i) = -1;
    end
end

%% 生成简单的人脸模式
function faceImg = generateFacePattern(imgSize)
    faceImg = zeros(imgSize);
    center = imgSize / 2;
    radius = min(imgSize) * 0.3;
    
    % 创建椭圆人脸
    [X, Y] = meshgrid(1:imgSize(2), 1:imgSize(1));
    distance = sqrt((X - center(2)).^2 + (Y - center(1)).^2);
    faceImg(distance <= radius) = 1;
    
    % 添加噪声
    faceImg = faceImg + 0.1 * randn(imgSize);
end

%% AdaBoost训练函数
function [classifiers, alphas] = trainAdaBoost(features, labels, numClassifiers)
    [nSamples, nFeatures] = size(features);
    
    % 初始化样本权重
    weights = ones(nSamples, 1) / nSamples;
    
    classifiers = cell(numClassifiers, 1);
    alphas = zeros(numClassifiers, 1);
    
    for t = 1:numClassifiers
        % 归一化权重
        weights = weights / sum(weights);
        
        % 训练弱分类器(决策树桩)
        weakClassifier = trainWeakClassifier(features, labels, weights);
        
        % 计算分类误差
        predictions = predictWeakClassifier(weakClassifier, features);
        error = sum(weights .* (predictions ~= labels));
        
        % 计算分类器权重
        alpha = 0.5 * log((1 - error) / max(error, eps));
        
        % 更新样本权重
        weights = weights .* exp(-alpha * labels .* predictions);
        
        % 存储分类器
        classifiers{t} = weakClassifier;
        alphas(t) = alpha;
        
        if mod(t, 10) == 0
            fprintf('已完成 %d/%d 个弱分类器训练\n', t, numClassifiers);
        end
    end
end

%% 训练弱分类器(决策树桩)
function weakClassifier = trainWeakClassifier(features, labels, weights)
    [nSamples, nFeatures] = size(features);
    
    bestError = inf;
    bestClassifier = struct();
    
    % 随机选择部分特征进行搜索
    numFeaturesToTry = min(50, nFeatures);
    featureIndices = randperm(nFeatures, numFeaturesToTry);
    
    for i = 1:numFeaturesToTry
        featureIdx = featureIndices(i);
        featureValues = features(:, featureIdx);
        
        % 尝试不同的阈值
        thresholds = linspace(min(featureValues), max(featureValues), 20);
        
        for threshold = thresholds
            for polarity = [-1, 1]
                % 计算预测结果
                predictions = polarity * (2*(featureValues > threshold) - 1);
                
                % 计算加权误差
                error = sum(weights .* (predictions ~= labels));
                
                if error < bestError
                    bestError = error;
                    bestClassifier.featureIdx = featureIdx;
                    bestClassifier.threshold = threshold;
                    bestClassifier.polarity = polarity;
                end
            end
        end
    end
    
    weakClassifier = bestClassifier;
end

%% 弱分类器预测
function predictions = predictWeakClassifier(classifier, features)
    featureValues = features(:, classifier.featureIdx);
    predictions = classifier.polarity * (2*(featureValues > classifier.threshold) - 1);
end

%% 强分类器预测
function predictions = predictStrongClassifier(classifiers, alphas, features)
    nSamples = size(features, 1);
    nClassifiers = length(classifiers);
    
    finalScore = zeros(nSamples, 1);
    
    for t = 1:nClassifiers
        weakPredictions = predictWeakClassifier(classifiers{t}, features);
        finalScore = finalScore + alphas(t) * weakPredictions;
    end
    
    predictions = sign(finalScore);
end

%% 测试分类器
function accuracy = testClassifier(classifiers, alphas, features, labels)
    predictions = predictStrongClassifier(classifiers, alphas, features);
    accuracy = mean(predictions == labels);
end

%% 图像中的人脸检测
function testImageDetection(classifiers, alphas, trainingSize)
    % 读取测试图像
    try
        testImg = imread('test_face.jpg');
    catch
        % 如果没有测试图像,创建示例图像
        testImg = createSampleTestImage();
    end
    
    if size(testImg, 3) == 3
        testImg = rgb2gray(testImg);
    end
    
    testImg = im2double(testImg);
    
    figure;
    subplot(1, 2, 1);
    imshow(testImg);
    title('原始图像');
    
    % 多尺度检测
    scales = 0.8:0.1:1.5;
    detectedFaces = [];
    
    for scale = scales
        scaledImg = imresize(testImg, scale);
        
        [height, width] = size(scaledImg);
        windowSize = trainingSize;
        
        % 滑动窗口检测
        for y = 1:2:height - windowSize(1)
            for x = 1:2:width - windowSize(2)
                window = scaledImg(y:y+windowSize(1)-1, x:x+windowSize(2)-1);
                
                % 提取特征并分类
                features = window(:)';
                prediction = predictStrongClassifier(classifiers, alphas, features);
                
                if prediction == 1
                    % 转换回原始图像坐标
                    origX = round(x / scale);
                    origY = round(y / scale);
                    origWidth = round(windowSize(2) / scale);
                    origHeight = round(windowSize(1) / scale);
                    
                    detectedFaces = [detectedFaces; origX, origY, origWidth, origHeight];
                end
            end
        end
    end
    
    % 显示检测结果
    subplot(1, 2, 2);
    imshow(testImg);
    title('人脸检测结果');
    hold on;
    
    % 非极大值抑制
    if ~isempty(detectedFaces)
        keptFaces = nonMaxSuppression(detectedFaces);
        
        for i = 1:size(keptFaces, 1)
            face = keptFaces(i, :);
            rectangle('Position', face, 'EdgeColor', 'r', 'LineWidth', 2);
        end
    end
    
    fprintf('检测到 %d 个人脸\n', size(keptFaces, 1));
end

%% 非极大值抑制
function keptBoxes = nonMaxSuppression(boxes, threshold)
    if nargin < 2
        threshold = 0.3;
    end
    
    if isempty(boxes)
        keptBoxes = [];
        return;
    end
    
    x = boxes(:, 1);
    y = boxes(:, 2);
    w = boxes(:, 3);
    h = boxes(:, 4);
    
    areas = w .* h;
    [~, order] = sort(areas, 'descend');
    
    kept = true(size(boxes, 1), 1);
    
    for i = 1:length(order)
        if ~kept(order(i))
            continue;
        end
        
        for j = i+1:length(order)
            if ~kept(order(j))
                continue;
            end
            
            box1 = [x(order(i)), y(order(i)), w(order(i)), h(order(i))];
            box2 = [x(order(j)), y(order(j)), w(order(j)), h(order(j))];
            
            intersectionArea = rectint(box1, box2);
            unionArea = areas(order(i)) + areas(order(j)) - intersectionArea;
            
            overlap = intersectionArea / unionArea;
            
            if overlap > threshold
                kept(order(j)) = false;
            end
        end
    end
    
    keptBoxes = boxes(kept, :);
end

%% 创建示例测试图像
function sampleImg = createSampleTestImage()
    sampleImg = zeros(200, 200);
    
    % 添加多个人脸模式
    face1 = generateFacePattern([40, 40]);
    sampleImg(30:69, 50:89) = face1;
    
    face2 = generateFacePattern([35, 35]);
    sampleImg(100:134, 120:154) = face2;
    
    % 添加噪声
    sampleImg = sampleImg + 0.1 * randn(200, 200);
    sampleImg = im2uint8(mat2gray(sampleImg));
end

三、代码说明

3.1 主要函数

  1. generateTrainingData: 生成训练数据(实际应用中应从真实数据集加载)
  2. trainAdaBoost: AdaBoost主训练函数
  3. trainWeakClassifier: 训练弱分类器(决策树桩)
  4. testImageDetection: 在图像中进行多尺度人脸检测

3.2 关键特点

  • 多尺度检测: 在不同尺度下搜索人脸
  • 滑动窗口: 使用滑动窗口遍历图像
  • 非极大值抑制: 消除重叠的检测框

3.3 使用建议

  1. 使用真实的人脸数据集(如LFW、FDDB)替换模拟数据
  2. 使用积分图加速Haar特征计算
  3. 实现真正的Haar-like特征提取
  4. 使用更复杂的弱分类器结构

参考代码 基于AdaBoost算法的人脸检测原理+matlab代码 www.youwenfan.com/contentcnl/65477.html

这个实现展示了AdaBoost人脸检测的基本原理,在实际应用中需要结合OpenCV等库的优化实现以获得更好的性能。

posted @ 2025-11-13 16:27  躲雨小伙  阅读(22)  评论(0)    收藏  举报