我如何更新这个神经网络来使用图像像素数据

How do I update this Neural Net to use image pixel data

本文关键字:图像 像素 数据 像素数 神经网络 何更新 更新      更新时间:2023-10-16

我正在从这个字节鱼机器学习指南和代码学习神经网络。我理解得很好,但我想在前面的链接更新代码,使用图像像素数据而不是随机值作为输入数据。在上述代码的这一部分中:

cv::randu(trainingData,0,1);
cv::randu(testData,0,1);

训练矩阵和测试矩阵用随机数据填充。然后标签数据被添加到类矩阵中:

cv::Mat trainingClasses = labelData(trainingData, eq);
cv::Mat testClasses = labelData(testData, eq);

使用这个函数:

    // label data with equation
    cv::Mat labelData(cv::Mat points, int equation) {
      cv::Mat labels(points.rows, 1, CV_32FC1);
      for(int i = 0; i < points.rows; i++) {
        float x = points.at<float>(i,0);
        float y = points.at<float>(i,1);
        labels.at<float>(i, 0) = f(x, y, equation); 
 // the f() function used above
//is only a case statement with 5 
//switches in it eg on of the switches is:
//case 0:
//return y > sin(x*10) ? -1 : 1;
//break;
      }
      return labels;
    }

然后在这里的窗口中绘制点:

 plot_binary(trainingData, trainingClasses, "Training Data");
 plot_binary(testData, testClasses, "Test Data");

有以下功能:

;; Plot Data and Class function
void plot_binary(cv::Mat& data, cv::Mat& classes, string name) {
  cv::Mat plot(size, size, CV_8UC3);
  plot.setTo(cv::Scalar(255.0,255.0,255.0));
  for(int i = 0; i < data.rows; i++) {
    float x = data.at<float>(i,0) * size;
    float y = data.at<float>(i,1) * size;
    if(classes.at<float>(i, 0) > 0) {
      cv::circle(plot, Point(x,y), 2, CV_RGB(255,0,0),1);
    } else {
      cv::circle(plot, Point(x,y), 2, CV_RGB(0,255,0),1);
    }
  }
  imshow(name, plot);
}

据我所知,绘制的点表示输入数据乘以f()函数中的方程,并由预测函数用于预测在mlp, knn, svm等函数中绘制的点。我如何更新这里发生的事情来处理图像像素数据。

"我如何更新这里正在做的事情与图像像素数据"是一个广泛而通用的问题。请问您想用"图像像素数据"做什么?


你是否想要一个答案: 在机器学习算法(如ANN, SVM等)上使用"图像像素数据"可以做什么?

答案是一长串的东西,包括数千篇研究论文和数百篇博士论文。一些例子包括:基于图像内容、图像中的对象、图像中的模式等特征,对图像进行监督和/或非监督分类。可能性是无限的。您可能想看看这个:http://stuff.mit.edu/afs/athena/course/urop/profit/PDFS/EdwardTolson.pdf


现在,回到你原来的目标:"我想更新前面链接的代码,使用图像像素数据而不是随机值作为输入数据"…

实现技术很大程度上取决于你想做什么。我可以列举一两个简单的技术来从图像中提取特征向量,这可以被输入到你选择的任何机器学习算法中…

示例1:您可以从使用像素强度数据作为特征向量开始。你可以这样做:

  1. 使用

    加载图像
     Mat image = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE);
    
  2. 使用 Resize 将图像调整为更小的区域。您可能希望从较小的图像尺寸开始,例如8x8或10x10像素。

  3. 遍历图像矩阵,有点像这样:

     for(int row = 0; row < img.rows; ++row) 
     {
      uchar* p = img.ptr(row);
      for(int col = 0; col < img.cols; ++col) 
        {
        *p++  //points to each pixel value in turn assuming a CV_8UC1 greyscale image 
        }
      }
    

    所有像素值的集合将为您提供该图像的特征向量。

  4. 现在假设你有两类图像。对于您生成的每一组特征向量,您必须准备(用于监督分类)一个相应的标签Mat(有点像您提到的示例)。它需要包含所有特征向量的类标签(例如,0和1)。

  5. 现在输入特征向量和标签Mat到你的机器学习代码,看看会发生什么。

然而,仅基于图像像素数据的图像分类能力是相当有限的。有成千上万种提取图像特征的技术,其中大多数依赖于应用领域。

例二:

我将用另一个提取特征向量的例子来结束,在某些情况下,这将被证明比简单的图像像素值更有效。

你可以使用直方图定向梯度描述符来获得更好的效果,使用如下:

cv::HOGDescriptor hog;
vector<float> descriptors;
hog.compute(mat, descriptors);

向量描述符是你的特征向量。

hogdescriptor,当与SVM一起使用时,提供了一个体面的分类机制。


你可以将图像的像素数据放入名为trainingData的Mat中,使用类似于以下内容:

 cv::Mat labelData(cv::Mat points, int equation) 
 {
  cv::Mat labels(points.rows, 1, CV_32FC1);
  for(int i = 0; i < points.rows; i++) 
           {
         float x = points.at<float>(i,0);
         float y = points.at<float>(i,1);
         labels.at<float>(i, 0) = f(x, y, equation);
    }
  return labels;
 } 

现在,我们将返回一组像素数据,而不是labelData。一种明显的方法是使用图像本身作为特征向量。然而,openCV中的一些机器学习算法,包括ANN、SVM等,需要对输入数据进行特殊的格式化。

你可以试试这样做:

 cv::Mat trainingData(cv::Mat image) 
 {
  cv::Mat trainingVector(image.rows*image.cols, 1, CV_32FC1);
  for(int i = 0; i < image.rows; i++) 
           {
               for(int j = 0; j < image.cols; j++) 
                   {
            float valueOfPixel = image.at<float>(i,j);
            trainingVector.at<float>((i*image.cols)+j, 0) = valueOfPixel;
                    }
    }
  return trainingVector;
 } 

(请在使用前重新检查代码的语法,我只是在这里键入)

因此,上面的块有效地将图像的2D矩阵变为1D数组。现在,如何和在哪里使用它取决于你的需求。

请在调用机器学习模块之前进行必要的修改。


希望这能回答你的问题。

谢谢。