Следующий код поможет вам начать работу с функциями train() и predict() в cv::ml::SVM; вот объяснение кода (код хорошо работает в opencv4.2). Входное изображение представляет собой подводное изображение из набора данных (тест доступен здесь https://li-chongyi.github.io/proj_benchmark.html). Первая часть кода имеет дело с компенсацией красного канала изображения, которая улучшает смещение цвета к голубоватому цвету изображения. Для компенсации красного канала использовалось уравнение 8 из статьи «Коррекция цвета на основе CFA» и «Улучшение на основе Retinex с плотными пикселями для подводных изображений». Изображение с компенсацией красного канала хранится в коде image2.
Затем в качестве обучающих данных выбирается прямоугольная часть изображения, содержащая только водяные пиксели. Данные обучения сортируются в матрицу из трех столбцов, в каждом из которых содержатся значения интенсивности красного, зеленого и синего соответственно (например, mx3).
Поскольку нам нужны два очка, то прямоугольная часть изображения, содержащая неводные пиксели, выбирается в качестве другой части данных.
Затем как данные только о воде, так и данные, не связанные с водой, объединяются для формирования обучающих данных. Матрица меток устроена так, что она содержит + 1 для пикселей воды и - 1 пикселей воды. Затем SVM управляется для работы с линейным ядром, но гамма также устанавливается со значением для работы с ядром 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 %d\n", 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 %d\n", 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 %d\n", 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 %d\n", 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: %d\t%d\t%d\t\n", 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: %d\t%d\t%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: %d\t%d\t%d\t\n", 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: %d\t%d\t%d\t\n", 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: %d\t%d\t%d\t\n", 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: %d\t%d\t%d\t\n", 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: %d\t%d\t%d\t\n", 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;
}
person
vahid_rowghanian
schedule
03.02.2021
other
? а почему вы ресайзите на 28х28? - person Miki   schedule 10.07.2015Mat1f
(без указателя), сделайтеother
Mat1b
, создайтеmat
, например:Mat1f mat(width*height, 1, 0.f)
, установите данные вmat
, например:mat(i*width+j) = float(other(i,j))
. - person Miki   schedule 10.07.2015