SVM的每一行训练矩阵的长度

Length of each row of training matrix for SVM

本文关键字:SVM 一行      更新时间:2023-10-16

我在此处使用openCV和svm与图像一起找到了与此主题相关的出色/全面帖子/答案。但是,我想从链接中的答案中阐明一些问题。(因为我没有足够的声誉来写评论)。

我一直在做什么: 我正在使用OpenCV SVM进行培训。通过计算每个图像的归一化平均R,G和B值来获得训练矩阵的功能。在训练矩阵中,每行中有4列(或每个图像中)。这些列对应于标签(1或0), ****在r通道****中归一化平均值, g b 频道。

顺便说一句,我的原始培训文件是一个文本文件,我仍将其转换为float [] [],甚至将其转换为垫子对象,以馈入OpenCV的SVM。文件的外观:

1 0.267053 0.321014 0.411933
1 0.262904 0.314294 0.422802


0 0.29101 0.337208 0.371782
0 0.261792 0.314494 0.423714

显然,这与链接的语句相矛盾,该链接指出每行的大小必须等于image 小>。是协议还是某种规则?我只是因为应该(如果是)应该是什么意思。

我的问题是,在构造训练矩阵时,每行的长度是否必须与图像的面积或大小相对应?就像我制作的训练矩阵一样,每行的长度仅为4。这是错误的吗?

此外,是否只有3个功能(3列)用于训练足够分类/用于SVM?请指导我走正确的道路,我怀疑我是否应该继续这样做,或者是否还有其他更好的方法解决问题。

我希望我能了解更多SVM步骤背后的概念。文章或相关样本将不胜感激!

每行的大小不必等效于图像大小。这取决于您的功能。使用平均值进行图像分类是不够的。只需考虑一下图片时如何对对象进行分类即可。您不计算平均值,但您可能会查看大脑处理背景中的轮廓,连接区域,有时是单个像素值。

因此,要获得更多功能,我有一个建议。计算每个列的特征提取部分的平均值。这可能会更有用。

,对于另一个功能提取,您可以使用PCA。通常,您可以连续提供所有像素值以进行训练SVM,但即使在200*200映像中,这也是40.000个功能,哇,这是如此之多。您需要减少此功能维度而不会丢失太多信息,这意味着保留可接受的差异百分比。因此,PCA用于此,降低了特征空间维度并以可接受的速率保留差异。

我将尝试向您展示如何使用PCA降低功能空间。首先,您需要获取图像,而不是按行滚动到垫子变量:

阅读CSV

void read_csv(const字符串和文件名,向量和图像,向量和标签,char saparator =';'){    std :: ifstream文件(filename.c_str(),ifstream :: in);    如果(!文件)    {        字符串error_message ="没有给出有效的输入文件,请检查给定的文件名。";        cv_error(1,error_message);    }    字符串线,路径,classLabel;    while(getline(文件,行))    {        链条乳(线);        getline(lines,路径,分离器);        getline(Liness,classLabel);        如果(!        {            MAT IM = IMREAD(路径,0);            images.push_back(im);            labels.push_back(atoi(classLabel.c_str()));        }    }}

滚行图:

滚动图像
Mat rollVectortoMat(const vector<Mat> &data) // data is vector of Mat images
{
   Mat dst(static_cast<int>(data.size()), data[0].rows*data[0].cols, CV_32FC1);
   for(unsigned int i = 0; i < data.size(); i++)
   {
      Mat image_row = data[i].clone().reshape(1,1);
      Mat row_i = dst.row(i);                                       
      image_row.convertTo(row_i,CV_32FC1, 1/255.);
   }
   return dst;
} 

MAIN

int main()
{
    PCA pca;
    vector<Mat> images_train;
    vector<Mat> images_test;
    vector<int> labels_train;
    vector<int> labels_test;
    read_csv("train1k.txt",images_train,labels_train);
    read_csv("test1k.txt",images_test,labels_test);
    Mat rawTrainData = rollVectortoMat(images_train);                       
    Mat rawTestData  = rollVectortoMat(images_test);                
    Mat trainLabels = getLabels(labels_train);
    Mat testLabels  = getLabels(labels_test);
    int pca_size = 500;
    Mat trainData(rawTrainData.rows, pca_size,rawTrainData.type());
    Mat testData(rawTestData.rows,pca_size,rawTestData.type());

    pca(rawTrainData,Mat(),CV_PCA_DATA_AS_ROW,pca_size);
    for(int i = 0; i < rawTrainData.rows ; i++)
        pca.project(rawTrainData.row(i),trainData.row(i));
    for(int i = 0; i < rawTestData.rows ; i++)
        pca.project(rawTestData.row(i),testData.row(i));
}

要总结,您读取了一个类似Image_path的CSV文件;标签。比滚动图像逐行滚动到垫子变量。您将PCA应用于500功能。我应用了这些PCA红色,以将200*200张图像(40000个功能)减少到500个功能大小。比我应用MLP对此进行了分类。该testdata和TrainData变量也可以与SVM一起使用。您也可以在我的帖子中检查如何使用MLP训练它:

OpenCV神经网络Sigmoid Output

如果图像的每个像素是您要训练SVM的功能,则每一行应列出所有功能,因此应列出所有像素。就您而言,看来您每个图像只有3个功能(平均R,G,B),因此没有任何问题。

当然,您可以很好地训练具有3个维度的SVM。但是忽略SVM,平均颜色是您图像的明智指标吗?