https://blog.csdn.net/shi923281339/article/details/77094757
1.理解SVM
請移步支持向量機(jī)通俗導(dǎo)論腥椒,通俗易懂月腋,這里不在贅述纤垂。
2.opencv中的SVM
opencv中對svm的介紹:Support Vector Machines for Non-Linearly Separable Data
官方測試代碼:我做了詳細(xì)的標(biāo)注:
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::ml;
int main(int, char**)
{
? ? // Data for visual representation
? ? int width = 512, height = 512;
? ? // zeros就是搞成全0矩陣
? ? Mat image = Mat::zeros(height, width, CV_8UC3);
? ? // Set up training data
? ? //! [setup1]
? ? //設(shè)置訓(xùn)練數(shù)據(jù)
? ? int labels[4] = { 1, -1, -1, -1 };? // 每個樣本點對應(yīng)的類
? ? float trainingData[4][2] = { { 501, 10 }, { 255, 10 }, { 501, 255 }, { 10, 501 } };
? ? //! [setup1]
? ? //! [setup2]
? ? // 將訓(xùn)練數(shù)據(jù)存入浮點型Mat中
? ? Mat trainingDataMat(4, 2, CV_32FC1, trainingData);
? ? // 使用OpenCV里面的機(jī)器學(xué)習(xí)算法時,要保證給的labelData的數(shù)據(jù)格式為”有符號的整型數(shù)”,
? ? // ”CV_32FC1”就是錯誤的一種形式倦沧,應(yīng)該使用”CV_32SC1”
? ? Mat labelsMat(4, 1, CV_32SC1, labels);
? ? //! [setup2]
? ? // Train the SVM
? ? //! [init]
? ? // 這里的svm是一個指針
? ? Ptr<SVM> svm = SVM::create();
? ? svm->setType(SVM::C_SVC);? // 文本選擇
? ? svm->setKernel(SVM::LINEAR);
? ? // TermCriteria是一個結(jié)構(gòu)體蔗怠,包括終止的類型墩弯,迭代次數(shù)或者元素數(shù)量,精度寞射。
? ? svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));
? ? //! [init]
? ? //! [train],ROW_SAMPLE指每次訓(xùn)練樣本的一行
? ? // 因此總的意思是每次訓(xùn)練樣本的一行渔工,而這一行是哪一類是由labelsMat決定的
? ? svm->train(trainingDataMat, ROW_SAMPLE, labelsMat);
? ? //! [train]
? ? // Show the decision regions given by the SVM
? ? //! [show]
? ? Vec3b green(0, 255, 0), blue(255, 0, 0);
? ? for (int i = 0; i < image.rows; ++i)
? ? ? ? for (int j = 0; j < image.cols; ++j)
? ? ? ? {
? ? ? ? ? ? Mat sampleMat = (Mat_<float>(1, 2) << j, i);
? ? ? ? ? ? float response = svm->predict(sampleMat);
? ? ? ? ? ? if (response == 1)
? ? ? ? ? ? ? ? image.at<Vec3b>(i, j) = green;
? ? ? ? ? ? else if (response == -1)
? ? ? ? ? ? ? ? image.at<Vec3b>(i, j) = blue;
? ? ? ? }
? ? //! [show]
? ? // Show the training data
? ? //! [show_data]
? ? int thickness = -1;? ? // 實心圓
? ? int lineType = 8;
? ? circle(image, Point(501, 10), 5, Scalar(0, 0, 0), thickness, lineType);
? ? circle(image, Point(255, 10), 5, Scalar(255, 255, 255), thickness, lineType);
? ? circle(image, Point(501, 255), 5, Scalar(255, 255, 255), thickness, lineType);
? ? circle(image, Point(10, 501), 5, Scalar(255, 255, 255), thickness, lineType);
? ? //! [show_data]
? ? // Show support vectors
? ? //! [show_vectors]
? ? thickness = 2;? ? // 線寬為2的圓
? ? lineType = 8;
? ? // 輸出所有的支持向量
? ? //int c = svm->getVarCount();? ? // 獲得支持向量的維數(shù)
? ? //cout << c << endl;
? ? Mat sv = svm->getSupportVectors();
? ? //cout << sv.cols << "-" << sv.rows << endl;
? ? // 訓(xùn)練出來的SVM classifier的support vector是以Mat類型進(jìn)行存儲,
? ? //其rows是根據(jù)svm的參數(shù)而變化的桥温,如果是二分類分類器引矩,應(yīng)該是1*n的大小。
? ? // 這里一行存的坐標(biāo)。
? ? for (int i = 0; i < sv.rows ; ++i)
? ? {
? ? ? ? const float* v = sv.ptr<float>(i);
? ? ? ? // 6是圓的半徑脓魏,(128,128,128)是灰色
? ? ? ? circle(image, Point((int)v[0], (int)v[1]), 10, Scalar(128, 128, 128), thickness, lineType);
? ? }
? ? //! [show_vectors]
? ? imwrite("result.png", image);? ? ? ? // save the image
? ? imshow("SVM Simple Example", image); // show it to the user
? ? waitKey(0);
}
3.用SVM做簡單的圖像分割
直接看代碼兰吟,同樣做了注釋:
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include "opencv2/imgcodecs.hpp"
#include <opencv2/highgui.hpp>
#include <opencv2/ml.hpp>
#include <iostream>
using namespace std;
using namespace cv;
using namespace cv::ml;
int main()
{
? ? Mat srcImg = imread("test.jpg");
? ? Mat desImg = srcImg.clone();
? ? imshow("原圖", srcImg);
? ? // 選取目標(biāo)區(qū)域和背景區(qū)域
? ? Mat BackImg = srcImg(Rect(199, 0, 30, 30));
? ? Mat ForeImg = srcImg(Rect(38, 95, 30, 30));
? ? // 初始化訓(xùn)練數(shù)據(jù)
? ? Mat trainingDataMat = ForeImg.clone().reshape(1, ForeImg.cols*ForeImg.rows);
? ? //在這里直接存入背景像素點,或者像下邊一個一個點存入也可以
? ? trainingDataMat.push_back(BackImg.clone().reshape(1,BackImg.cols*BackImg.rows));
? ? trainingDataMat.convertTo(trainingDataMat, CV_32FC1);
? ? // 初始化標(biāo)簽茂翔,分別給兩種標(biāo)簽輔助混蔼,雖然這里memset已經(jīng)全部初始化為1了,可是這里的1是浮點數(shù)
? ? int *labels = new int[ForeImg.cols*ForeImg.rows + BackImg.cols*BackImg.rows];
? ? memset(labels, 1, sizeof(int)*(ForeImg.cols*ForeImg.rows + BackImg.cols*BackImg.rows));
? ? for (int i = 0; i < ForeImg.rows; ++i)
? ? ? ? for (int j = 0; j < ForeImg.cols; ++j){
? ? ? ? ? ? labels[i*ForeImg.cols + j] = 1;
? ? ? ? }
? ? for (int h = 0; h<BackImg.rows; h++)
? ? {
? ? ? ? for (int w = 0; w<BackImg.cols; w++)
? ? ? ? {
? ? ? ? ? ? labels[ForeImg.cols*ForeImg.rows + h*BackImg.cols + w] = -1;
? ? ? ? }
? ? }
? ? Mat labelsMat = Mat(ForeImg.cols*ForeImg.rows + BackImg.cols*BackImg.rows, 1, CV_32SC1, labels);
? ? // 可以將數(shù)據(jù)寫入文件來檢查是否正確
? ? //FileStorage fs("data.xml", FileStorage::WRITE);
? ? //fs << "traindata" << trainingDataMat << "labels" << labelsMat;
? ? // Train the SVM
? ? Ptr<SVM> svm = SVM::create();
? ? svm->setType(SVM::C_SVC);
? ? svm->setKernel(SVM::RBF);
? ? svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, (int)1e5, 1e-6));
? ? svm->train(trainingDataMat, ROW_SAMPLE, labelsMat);
? ? // 開始分類
? ? Vec3b black(0, 0, 0), white(255, 255, 255);
? ? for (int i = 0; i < desImg.rows; ++i)
? ? {
? ? ? ? uchar* p_sample = desImg.ptr<uchar>(i);
? ? ? ? for (int j = 0; j < desImg.cols; ++j)
? ? ? ? {
? ? ? ? ? ? Mat sampleMat(1, 3, CV_32FC1);
? ? ? ? ? ? sampleMat.at<float>(0, 0) = p_sample[3 * j + 0];
? ? ? ? ? ? sampleMat.at<float>(0, 1) = p_sample[3 * j + 1];
? ? ? ? ? ? sampleMat.at<float>(0, 2) = p_sample[3 * j + 2];
? ? ? ? ? ? float response = svm->predict(sampleMat);
? ? ? ? ? ? if (response == 1)
? ? ? ? ? ? ? ? desImg.at<Vec3b>(i, j) = white;
? ? ? ? ? ? else if (response == -1)
? ? ? ? ? ? ? ? desImg.at<Vec3b>(i, j) = black;
? ? ? ? }
? ? }
? ? imwrite("result.jpg", desImg);
? ? imshow("resImg", desImg);
? ? waitKey(0);
? ? return 0;
}
這里的白塊就是我們選得目標(biāo)區(qū)域珊燎。不知道是不是我參數(shù)選擇不好惭嚣,這里的分割效果步理想。
參考博客:利用SVM支持向量機(jī)對彩色圖像進(jìn)行分割并使用OpenCV進(jìn)行實現(xiàn)
支持向量機(jī)通俗導(dǎo)論(理解SVM的三層境界)
---------------------
作者:影子要造反
來源:CSDN
原文:https://blog.csdn.net/shi923281339/article/details/77094757
版權(quán)聲明:本文為博主原創(chuàng)文章悔政,轉(zhuǎn)載請附上博文鏈接晚吞!