You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Linear Discriminant Analysis匹配ATT数据集训练测试集相似图像

解决方案实现

1. 核心功能:图像转一维向量实现

首先统一所有输入图像的分辨率(ATT人脸数据集默认分辨率为92*112,可直接使用该参数,自定义图像可按需调整),将图像转灰度后逐行拉平即可得到需求的一维向量。

首先封装人脸处理工具类,统一管理参数和训练数据:

// 人脸处理辅助类,封装向量转换、LDA训练相关数据
public class FaceProcessingHelper
{
    // 统一图像尺寸,可根据实际数据集调整
    public const int ImgWidth = 92;
    public const int ImgHeight = 112;
    // 向量总长度 = 宽*高
    public const int VectorLength = ImgWidth * ImgHeight;

    // 存储训练集所有图像的一维向量
    public List<double[]> TrainVectors { get; set; } = new List<double[]>();
    // 存储训练集向量对应的人脸标签/文件名
    public List<string> TrainLabels { get; set; } = new List<string>();
    // 训练集均值向量,你后续计算后可存在这里
    public double[] MeanVector { get; set; }
}

以下是图像转一维向量的实现方法:

// 输入Bitmap图像,输出灰度化后的一维向量
public static double[] BitmapToVector(Bitmap img)
{
    // 先把图像缩放到统一尺寸
    Bitmap resizedImg = new Bitmap(img, FaceProcessingHelper.ImgWidth, FaceProcessingHelper.ImgHeight);
    double[] vector = new double[FaceProcessingHelper.VectorLength];
    int index = 0;
    for (int y = 0; y < FaceProcessingHelper.ImgHeight; y++)
    {
        for (int x = 0; x < FaceProcessingHelper.ImgWidth; x++)
        {
            Color pixel = resizedImg.GetPixel(x, y);
            // 标准灰度转换公式,避免直接取单通道丢失信息
            double grayValue = pixel.R * 0.299 + pixel.G * 0.587 + pixel.B * 0.114;
            vector[index] = grayValue;
            index++;
        }
    }
    return vector;
}

该方法输出的数组结构和你示例的向量完全匹配,顺序为逐行从左到右读取像素灰度值。

2. 训练按钮(button1)逻辑完善

在Form1类中实例化全局工具类,补全训练逻辑:

public partial class Form1 : Form
{
    // 全局人脸处理对象,存储训练好的数据
    private FaceProcessingHelper _faceHelper = new FaceProcessingHelper();
    // 数据集路径,可根据你的实际路径修改
    private string _trainPath = @"C:\Users\TimothyFarCry5\Documents\visual studio 2015\Projects\LDA-FaceR\LDA-FaceR\ATTDataSet\Training";
    private string _testPath = @"C:\Users\TimothyFarCry5\Documents\visual studio 2015\Projects\LDA-FaceR\LDA-FaceR\ATTDataSet\Testing";

    public Form1()
    {
        InitializeComponent();
    }

    // 训练按钮点击事件
    private void button1_Click(object sender, EventArgs e)
    {
        // 清空上一次训练的缓存
        _faceHelper.TrainVectors.Clear();
        _faceHelper.TrainLabels.Clear();

        // 遍历训练文件夹下所有jpg图像
        string[] trainImgs = Directory.GetFiles(_trainPath, "*.jpg");
        foreach (string imgPath in trainImgs)
        {
            Bitmap bmp = new Bitmap(Image.FromFile(imgPath));
            // 转成向量存入训练集
            double[] vec = BitmapToVector(bmp);
            _faceHelper.TrainVectors.Add(vec);
            // 存储文件名作为标签,也可以按人脸ID打分类标签(LDA训练需要类别信息)
            _faceHelper.TrainLabels.Add(Path.GetFileName(imgPath));
        }

        // ========= 以下为你可以自行补充的LDA训练逻辑 =========
        // 1. 计算所有训练向量的均值向量,存入_faceHelper.MeanVector
        // 2. 所有训练向量减去均值向量得到中心化向量
        // 3. 计算类内散度矩阵、类间散度矩阵
        // 4. 求解广义特征值,取前K个最大特征值对应的特征向量作为投影矩阵
        // 5. 将所有训练向量投影到LDA特征空间,存储投影后的特征用于后续匹配

        MessageBox.Show($"训练完成,共加载{_faceHelper.TrainVectors.Count}张训练图像");
        // 显示第一张训练图像在original image框
        pictureBox1.Image = Image.FromFile(trainImgs[0]);
    }

3. 识别按钮(button2)逻辑框架

private void button2_Click(object sender, EventArgs e)
{
    if (_faceHelper.TrainVectors.Count == 0)
    {
        MessageBox.Show("请先完成训练再执行识别");
        return;
    }

    // 遍历测试文件夹所有图像
    string[] testImgs = Directory.GetFiles(_testPath, "*.jpg");
    foreach (string testImgPath in testImgs)
    {
        Bitmap testBmp = new Bitmap(Image.FromFile(testImgPath));
        // 测试图像转向量
        double[] testVec = BitmapToVector(testBmp);
        // ========= 以下为你可以自行补充的识别逻辑 =========
        // 1. 测试向量减去训练集均值向量中心化
        // 2. 投影到LDA特征空间得到测试特征
        // 3. 计算测试特征和所有训练集投影特征的欧式距离/余弦距离
        // 4. 取距离最小的训练样本作为匹配结果,得到对应索引matchIndex
        int matchIndex = 0; // 这里先写示例值,替换为实际匹配结果索引即可
        string matchImgPath = Path.Combine(_trainPath, _faceHelper.TrainLabels[matchIndex]);

        // 显示测试图像到original image框,匹配到的训练图像到recognized image框
        pictureBox1.Image = testBmp;
        pictureBox2.Image = Image.FromFile(matchImgPath);

        // 可选:每识别一张停顿看效果,不需要可删除
        MessageBox.Show($"当前测试图像:{Path.GetFileName(testImgPath)}\n匹配结果:{_faceHelper.TrainLabels[matchIndex]}");
    }
}

注意事项

  • 若你使用的图像尺寸不是92*112,修改FaceProcessingHelper里的宽高参数即可
  • LDA是有监督分类算法,训练时建议按人脸ID给样本打类别标签(比如S1文件夹下的所有图像标签都为1,S2的为2),不要直接用文件名,更便于计算类间散度
  • 数据集较大时可以用LockBits方法替代GetPixel加速像素读取,小数据集无需调整

内容的提问来源于stack exchange,提问作者user16612111

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 04:36:04