cv::mat preparation for svm::predict



我是OpenCv的新手,正在从OpenCv2.4过渡到OpenCv3…我已经训练SVM分类器存储在*.xml文件。

我在转换过程中的问题是如何准备cv::Mat正确,以便它可以输入cv::ml::SVM预测。

CvMat* NumExtractor::prepareDataSVM(cv::Mat & other){
      resize(other, other, Size(28,28));
      cv::Size s = other.size();
      int width = (int)s.width;
      int height = (int)s.height;
      cv::Mat ret = other.clone();
      CvMat* mat = cvCreateMat(width*height, 1, CV_32FC1);
      for(int i = 0; i < height; ++i)
      {
          for(int j = 0; j < width; ++j)
          {
             mat.data.fl[i*width+j] = (float)other.at<uchar>(i,j);
          }
      }
      return mat;
   }

但是我正在努力如何用cv::Mat做到这一点。有人能帮帮我吗?

编辑:我想明白了。我使用了错误的API来存储值

下面的代码可以帮助您开始使用cv::ml::SVM的train()和predict()函数;下面是代码的解释(代码在openv4.2中运行良好)。输入图像是来自数据集的水下图像(这里有基准测试https://li-chongyi.github.io/proj_benchmark.html)。代码的第一部分处理图像的红色通道补偿,该补偿改善了图像的色差。对于红色通道补偿,论文中的公式8;基于CFA的水下图像色彩校正和基于密集像素的视网膜增强已经用过了。红色通道补偿图像存储在代码中的image2中。

然后,选择图像中仅包含水像素的矩形部分作为训练数据。训练数据被分类成一个3列矩阵,每列分别保存红、绿、蓝强度值(例如mx3)。

由于我们需要两个玻璃杯,那么图像中包含非水像素的矩形部分被选择作为数据的另一部分。

然后,将只有水的数据和没有水的数据连接起来,形成训练数据。标签矩阵被安排成水像素+ 1和水像素- 1。然后设法使支持向量机与线性核一起运行,但也为gamma设置一个值以便与RBF核一起运行。{输入图像}

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/ml/ml.hpp>
using namespace cv;
using namespace cv::ml;
using namespace std;

int main()
{
    std::cout << "Hello World!n";
    //read an image
    Mat image = imread("9554.png", 1);
    //check for existance of data
    if (!image.data) 
    { printf("no image data.n"); return -1; }
    //planes is a vector for holding rgb channels separately
    //std::vector<Mat> planes;
    Mat planes[3];
    //split the image into channels
    //planes[2] is the red channel
    split(image, planes);
    // converting planes from uchar to double
    planes[0].convertTo(planes[0], CV_64FC1);
    planes[1].convertTo(planes[1], CV_64FC1);
    planes[2].convertTo(planes[2], CV_64FC1);
    // defining coefficients of green and blue channel for blending
    double a = 0.05, b = 0.95;
    
    //sum_im stores pixelwise sum of Red, Green and Blue planes
    Mat imBlendNormal_B_G, sum_im;
    //converting to double
    imBlendNormal_B_G.convertTo(imBlendNormal_B_G, CV_64FC1);
    sum_im.convertTo(sum_im, CV_64FC1);
    //blending green and blue planes with a and b coefficients
    // and 0.0 offset(or gamma)
    addWeighted(planes[1], a, planes[0], b, 0.0, imBlendNormal_B_G);
    // sum of red, green and blue pixel in two addWeighted calls
    addWeighted(planes[2], 1.0, planes[1], 1.0, 0.0, sum_im);
    addWeighted(planes[0], 1.0, sum_im, 1.0, 0.0, sum_im);
    //dividing blended green and blue image to total RGB sum
    divide(imBlendNormal_B_G, sum_im, imBlendNormal_B_G);
    //defining average kernel 3x3
    Mat avg3x3_kernel = (Mat_<double>(3, 3) << 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0, 1.0 / 9.0);
    
    //defining matrices for storing 3x3 average of blue and green planes
    Mat blueAverage, greenAverage;
    // converting to double type
    blueAverage.convertTo(blueAverage, CV_64FC1);
    greenAverage.convertTo(greenAverage, CV_64FC1);
    // taking 3x3 average
    filter2D(planes[0], blueAverage, planes[0].depth(), avg3x3_kernel);
    filter2D(planes[1], greenAverage, planes[1].depth(), avg3x3_kernel);
    //imBlendAverage_B_G_R: for blending of averaged green and blue channels
    Mat imBlendAverage_B_G_R; 
    //convert to double
    imBlendAverage_B_G_R.convertTo(imBlendAverage_B_G_R, CV_64FC1);
    //blend averaged green and blue with a and b coeffs
    addWeighted(greenAverage, a, blueAverage, b, 0.0, imBlendAverage_B_G_R);
    
    //differentiate red values
    addWeighted(imBlendAverage_B_G_R, 1.0, planes[2], -1.0, 0.0, imBlendAverage_B_G_R);
    //CompensationTermRed: storing finally compensated red channel intensities
    Mat CompensationTermRed; 
    //coverting to double
    CompensationTermRed.convertTo(CompensationTermRed, CV_64FC1);
    //multiplication term
    CompensationTermRed = imBlendAverage_B_G_R.mul(imBlendNormal_B_G);
    //final add term
    addWeighted(CompensationTermRed, 1.0, planes[2], 1.0, 0.0, CompensationTermRed);
    
    // assign new red channel values to planes[2]
    planes[2] = CompensationTermRed;
    Mat image2;
    cv::merge(planes, 3, image2); 
    image2.convertTo(image2, CV_8UC3);
    imshow("merge",image2);
    printf("ndims of image2 (merge): %d  %dn", image2.rows, image2.cols);
    //defining rectangle of coordination
    Rect waterrect(5,5,365,135);
    
    // water only image 
    Mat WaterOnlyImage = image(waterrect);
    imshow("water only image", WaterOnlyImage);    
    
    // separating WaterOnlyImage planes
    Mat WaterOnlyPlanes[3];
    split(WaterOnlyImage, WaterOnlyPlanes);
    printf("size of WaterOnlyPlanes[0]: %d  %d  %dn", WaterOnlyPlanes[0].rows,WaterOnlyPlanes[0].cols, WaterOnlyPlanes[0].channels());
    // vector of each plane
    Mat WaterOnlyRedVector, WaterOnlyGreenVector, WaterOnlyBlueVector;
    // reshape each plane into vector separately
    // column vector
    WaterOnlyRedVector = WaterOnlyPlanes[2].reshape(0, 1).t();
    WaterOnlyGreenVector = WaterOnlyPlanes[1].reshape(0, 1).t();
    WaterOnlyBlueVector = WaterOnlyPlanes[0].reshape(0, 1).t();
    printf("WaterOnlyRedVector size: %d  %d  %dn", WaterOnlyRedVector.rows, WaterOnlyRedVector.cols, WaterOnlyRedVector.channels());
    
    // (row*com)x3 vector holding all RGB pixels of water
    // (WaterOnlyRedVector.rows, 3);
    Mat WaterOnlyRGBVector;
    // concatenation of three vectors values using hconcat
    // hconcate: horizontal concatenation
    hconcat(WaterOnlyRedVector, WaterOnlyGreenVector, WaterOnlyRGBVector);
    hconcat(WaterOnlyRGBVector, WaterOnlyBlueVector, WaterOnlyRGBVector);
    printf("WaterOnlyRGBVector dims is: %d  %d  %dn", WaterOnlyRGBVector.rows, WaterOnlyRGBVector.cols, WaterOnlyRGBVector.channels());
    
    // label vector for water pixels, all preset one
    Mat WaterOnlyLabelVector_float = Mat::ones(WaterOnlyRGBVector.rows, 1, CV_32SC1);
    printf("WaterOnlyLabelVector_float dims: %dt%dt%dtn", WaterOnlyLabelVector_float.rows, WaterOnlyLabelVector_float.cols, WaterOnlyLabelVector_float.channels());
    //std::cout << WaterOnlyLabelVector_float << "n";
    // defining non water coordination
    Rect nonWaterRect(1, 400, 640, 320);
    //non water image
    Mat NonWaterImage = image(nonWaterRect);
    imshow("non water image", NonWaterImage);
    //holding plited nonwater image planes
    Mat NonWaterPlanes[3];
    //split nonwater image sample
    split(NonWaterImage, NonWaterPlanes);
    printf("NonWaterPlanes[0] dims: %dt%dt%d n", NonWaterPlanes[0].rows, NonWaterPlanes[0].cols, NonWaterPlanes[0].channels());
    // 3 column vector for each of rgb planes
    Mat NonWaterRedVector, NonWaterGreenVector, NonWaterBlueVector;
    // reshaping each plane to get a column vector Mx1
    NonWaterRedVector = NonWaterPlanes[2].reshape(0, 1).t();//red 1st
    NonWaterGreenVector = NonWaterPlanes[1].reshape(0, 1).t();//green 2nd
    NonWaterBlueVector = NonWaterPlanes[0].reshape(0, 1).t();//blue
    printf("NonWaterGreenVector size is: %dt%dt%dtn", NonWaterGreenVector.rows, NonWaterGreenVector.cols, NonWaterGreenVector.channels());
    
    // Mx3 vector holding all RGB pixels of NonWater
    Mat NonWaterRGBVector;
    // concatenate 3 column vec into one place (Mx3)
    cv::hconcat(NonWaterRedVector, NonWaterGreenVector, NonWaterRGBVector);
    cv::hconcat(NonWaterRGBVector, NonWaterBlueVector, NonWaterRGBVector);
    printf("NonWaterRGBVector dims: %dt%dt%dtn", NonWaterRGBVector.rows, NonWaterRGBVector.cols, NonWaterRGBVector.channels());
    // label vector for NonWater pixels
    Mat NonWaterLabelVector_float = cv::Mat::zeros(NonWaterRGBVector.rows, 1, CV_32SC1) - 1.0;
    printf("NonWaterLabelVector_float dims: %dt%dt%dtn", NonWaterLabelVector_float.rows, NonWaterLabelVector_float.cols, NonWaterLabelVector_float.channels());
    //cout << NonWaterLabelVector_float << "n";
    
    // label matrix for all data
    Mat AllLabelVector_float;
    cv::vconcat(WaterOnlyLabelVector_float, NonWaterLabelVector_float, AllLabelVector_float);
    printf("AllLabelVector_float dims:  %dt%dt%dtn", AllLabelVector_float.rows, AllLabelVector_float.cols, AllLabelVector_float.channels());
    //concatenation of all training data
    // uchar mat
    Mat AllTrainingDataVector_uchar;
    cv::vconcat(WaterOnlyRGBVector, NonWaterRGBVector, AllTrainingDataVector_uchar);
    // convert to double
    Mat AllTrainingDataVector_float;
    AllTrainingDataVector_uchar.convertTo(AllTrainingDataVector_float, CV_32F);
    printf("AllTrainingDataVector_float dims: %dt%dt%dtn", AllTrainingDataVector_float.rows, AllTrainingDataVector_float.cols, AllTrainingDataVector_float.channels());
    //std::cout << AllTrainingDataVector_float << "n";
    
    // define support vector machine
    Ptr<ml::SVM> WaterSVMParams = ml::SVM::create();
    WaterSVMParams->setType(cv::ml::SVM::C_SVC);
    WaterSVMParams->setKernel(cv::ml::SVM::RBF);
    WaterSVMParams->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER,100,1e-6));
    WaterSVMParams->setGamma(0.000000001);
    // train data
    WaterSVMParams->train(AllTrainingDataVector_float, ROW_SAMPLE, AllLabelVector_float);
    // prediction responses image
    Mat WaterPredictionImage = Mat::zeros(image.rows, image.cols, CV_8UC3);
    // blue for water and green for nonwater
    Vec3b green(0, 255, 0), blue(255, 0, 0);
    // loop to fill the response image with prediction colors
    for (int i = 0; i < image.rows; i++)
    {
        for (int j = 0; j < image.cols; j++) {
            // getting one pixel at (i,j)
            Vec3b oneTestPixel = image.at<Vec3b>(i, j);
            // getting rgb vals
            float oneTestPixelRed = (float)oneTestPixel.val[2];
            float oneTestPixelGreen = (float)oneTestPixel.val[1];
            float oneTestPixelBlue = (float)oneTestPixel.val[0];
            Mat samplePixelMat = (Mat_<float>(1, 3) << oneTestPixelRed, oneTestPixelGreen, oneTestPixelBlue);
            //cout <<"curret test pixel:t" << samplePixelMat << "n";
            float responseSVM = WaterSVMParams->predict(samplePixelMat);
            if (responseSVM == 1.0) {
                WaterPredictionImage.at<Vec3b>(i, j) = blue;
            }
            if (responseSVM == -1.0) {
                WaterPredictionImage.at<Vec3b>(i, j) = green;
            }
        }//end of for j
    }//end of for i
    
    imshow("WaterPredictionImage-Linear Kernel", WaterPredictionImage);
        
    waitKey(0);
    return 0;
}

相关内容

  • 没有找到相关文章

最新更新