adaboost结合haar特征实现人脸定位的一个细节问题

用如题方法实现人脸定位,在训练阶段,我想训练一个弱分类器,对于一个特征模板,我理解的是在一张样本图片的固定位置,固定大小计算一个特征值,其它的样本也是这样子算,最后得到一个特征值数组,从这个数组里面选出一个最佳阈值给分类器。但是如果更改取样的位置和大小,那岂不是有很多的弱分类器吗?难道要从中选一个误差最小的吗?这样子的话运算量太大了
有没有人能说一下具体的训练过程
还有样本权重是用到最后面计算分类误差率的吗?
(解决我的问题即可采纳)

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
训练过程:

Adaboost是一个迭代算法,它会在每一轮选择一个最佳的弱分类器加入到集成中。对于每个弱分类器$h$来说,它的训练过程如下:

  1. 对于每个样本,计算其对应的特征值的数组,然后根据特征值数组的阈值进行分类,得到分类结果。

  2. 根据分类结果计算加权的分类误差率(权值为上一轮错误分类的样本的权值),然后更新弱分类器的权重和权值分布。

在选取最佳弱分类器的过程中,要考虑不同位置和大小的特征模板,但是不需要对所有的可能性都进行训练。实际上,可以先对样本进行几轮训练,建立一个较好的基础模型,然后根据其表现来选择更具有代表性的特征模板,训练更多的弱分类器。

样本权重:

在Adaboost算法中,样本的权重会随着训练轮数不断更新。具体来说,在每一轮训练之后,错误分类的样本的权重会变得更高,而正确分类的样本权重会变得更低。这样做的目的是让弱分类器更关注容易分类错误的样本,从而提高整体的准确率。

具体实现:

以下是基于python的Adaboost和Haar特征的实现代码:

import numpy as np
import cv2

def Haar_feature(img, x, y, w, h):
    # 计算Haar特征
    feature = [0]*3  # 三种类型的Haar特征
    sum_a = 0
    sum_b = 0
    sum_c = 0
    for i in range(y, y+h):
        for j in range(x, x+w):
            if i+h <= y+h/2:
                sum_a += img[i][j]
            elif i >= y+h/2:
                sum_c += img[i][j]
            else:
                sum_b += img[i][j]
    area = w * h
    feature[0] = (sum_a - sum_b) / area
    feature[1] = (sum_b - sum_c) / area
    feature[2] = (sum_a - sum_c) / area
    return feature

def Adaboost(feature_list, img_list, label_list, T):
    # T为训练轮数
    N = len(feature_list)  # 特征数目
    M = len(img_list)  # 样本数目
    w = [1/M]*M  # 样本权重
    alpha = [0]*T  # 弱分类器的权重
    h = []  # 弱分类器
    for t in range(T):
        error = [0]*N
        for i in range(N):
            feature = feature_list[i]
            y_pred = np.sign(np.dot(w, np.array([feature[j] for j in range(M)])))
            y_true = np.array([label_list[j] for j in range(M)])
            error[i] = np.sum((y_pred != y_true) * w) / np.sum(w)  # 加权分类误差率
        min_error = min(error)
        if min_error > 0.5:  # 如果无法分类,则不再添加弱分类器
            break
        min_index = error.index(min_error)
        h.append(feature_list[min_index])
        alpha[t] = np.log((1-min_error) / min_error) / 2  # 弱分类器的权重
        for i in range(M):
            if label_list[i] == np.sign(np.dot(w, np.array([feature_list[min_index][j] for j in range(M)]))):
                w[i] *= np.exp(-alpha[t])
            else:
                w[i] *= np.exp(alpha[t])
        w /= np.sum(w)  # 归一化

    return [alpha[:t+1], h[:t+1]]  # 返回弱分类器的权重和特征

def predict(img, feature, alpha):
    # 预测
    score = np.sum([alpha[i] * feature[i] for i in range(len(alpha))])
    if score > 0:
        return 1
    else:
        return -1

def get_all_feature(img, min_size=40, max_size=150):
    # 提取所有特征模板
    feature_list = []
    w, h = img.shape
    for size in range(min_size, max_size+1, 10):
        for i in range(0, w-size, 5):
            for j in range(0, h-size, 5):
                feature_list.append(Haar_feature(img, j, i, size//2, size//2))
                feature_list.append(Haar_feature(img, j+size//2, i, size//2, size//2))
                feature_list.append(Haar_feature(img, j, i+size//2, size//2, size//2))
    return feature_list

其中,Haar_feature用来计算Haar特征,Adaboost用于训练并返回弱分类器的权重和特征,predict用于预测,get_all_feature用于提取所有特征模板。

使用示例:

以下是使用示例代码,其中,首先将样本图像读入,并根据标签进行标记,然后调用Adaboost进行训练,然后使用测试集对分类器的性能进行评估。

if __name__ == '__main__':
    # 读取样本图像和标签
    pos_dir = './data/positive/'
    neg_dir = './data/negative/'
    pos_list = os.listdir(pos_dir)
    neg_list = os.listdir(neg_dir)
    img_list = []
    label_list = []
    for img_name in pos_list:
        img = cv2.imread(os.path.join(pos_dir, img_name), 0)
        if img is not None and img.shape == (100, 100):
            img_list.append(img.ravel())
            label_list.append(1)
    for img_name in neg_list:
        img = cv2.imread(os.path.join(neg_dir, img_name), 0)
        if img is not None and img.shape == (100, 100):
            img_list.append(img.ravel())
            label_list.append(-1)

    # 划分训练集和测试集
    idx = np.arange(len(img_list))
    np.random.shuffle(idx)
    train_img = [img_list[i] for i in idx[:500]]  # 500个样本用于训练
    train_label = [label_list[i] for i in idx[:500]]
    test_img = [img_list[i] for i in idx[500:]]  # 300个样本用于测试
    test_label = [label_list[i] for i in idx[500:]]

    # 训练
    feature_list = [Haar_feature(np.array(img_list[i], dtype=np.uint8).reshape(100, 100), 0, 0, 100, 100) for i in range(len(img_list))]
    alpha, features = Adaboost(feature_list, train_img, train_label, T=100)

    # 预测
    correct = 0
    for i in range(len(test_img)):
        feature = Haar_feature(np.array(test_img[i], dtype=np.uint8).reshape(100, 100), 0, 0, 100, 100)
        y_pred = predict(np.array(test_img[i], dtype=np.uint8).reshape(100, 100), features, alpha)
        if y_pred == test_label[i]:
            correct += 1
    print('Accuracy:', correct / len(test_img))

其中,样本数据放在./data/positive./data/negative文件夹中。
如果我的回答解决了您的问题,请采纳!