日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

OpenCV3.0或OpenCV3.1的SVM操作

發布時間:2024/4/15 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OpenCV3.0或OpenCV3.1的SVM操作 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

OpenCV2.0 SVM代碼及其分析

OpenCV 在很久以前就集成了SVM的功能,現在OpenCV升級到了3.0和3.1了,很多人都不習慣了怎么調用OpenCV中的SVM功能了。在之前OpenCV的SVM調用一直有個案例:首先,給定幾組訓練數據,并且給了label所對應的值。然后經過訓練之后,對圖像的各個位置進行預測是1還是-1。如果是1的話,用綠色來表示,如果是-1呢,用藍色表示。并且還畫出幾個支持向量。?
下面給了OpenCV2.0 的SVM代碼(勿噴,直接從OpenCV官方網址復制下來的)

#include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/ml/ml.hpp>using namespace cv;int main() {// Data for visual representationint width = 512, height = 512;Mat image = Mat::zeros(height, width, CV_8UC3);// Set up training datafloat labels[4] = {1.0, -1.0, -1.0, -1.0};Mat labelsMat(3, 1, CV_32FC1, labels);float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} };Mat trainingDataMat(3, 2, CV_32FC1, trainingData);// Set up SVM's parametersCvSVMParams params;params.svm_type = CvSVM::C_SVC;params.kernel_type = CvSVM::LINEAR;params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 1e-6);// Train the SVMCvSVM SVM;SVM.train(trainingDataMat, labelsMat, Mat(), Mat(), params);Vec3b green(0,255,0), blue (255,0,0);// Show the decision regions given by the SVMfor (int i = 0; i < image.rows; ++i)for (int j = 0; j < image.cols; ++j){Mat sampleMat = (Mat_<float>(1,2) << i,j);float response = SVM.predict(sampleMat);if (response == 1)image.at<Vec3b>(j, i) = green;else if (response == -1) image.at<Vec3b>(j, i) = blue;}// Show the training dataint 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 support vectorsthickness = 2;lineType = 8;int c = SVM.get_support_vector_count();for (int i = 0; i < c; ++i){const float* v = SVM.get_support_vector(i);circle( image, Point( (int) v[0], (int) v[1]), 6, Scalar(128, 128, 128), thickness, lineType);}imwrite("result.png", image); // save the image imshow("SVM Simple Example", image); // show it to the userwaitKey(0);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68

OpenCV 3.0、OpenCV3.1 的SVM訓練代碼

下面給出了正確的,記住是正確的代碼:

例子1:

#include "stdafx.h" #include "opencv2/opencv.hpp" using namespace cv; using namespace cv::ml;int main(int, char**) {int width = 512, height = 512;Mat image = Mat::zeros(height, width, CV_8UC3); //創建窗口可視化// 設置訓練數據int labels[10] = { 1, -1, 1, 1,-1,1,-1,1,-1,-1 };Mat labelsMat(10, 1, CV_32SC1, labels);float trainingData[10][2] = { { 501, 150 },{ 255, 10 },{ 501, 255 },{ 10, 501 },{ 25, 80 },{ 150, 300 },{ 77, 200 } ,{ 300, 300 } ,{ 45, 250 } ,{ 200, 200 } };Mat trainingDataMat(10, 2, CV_32FC1, trainingData);// 創建分類器并設置參數Ptr<SVM> model = SVM::create();model->setType(SVM::C_SVC);model->setKernel(SVM::LINEAR); //核函數//設置訓練數據 Ptr<TrainData> tData = TrainData::create(trainingDataMat, ROW_SAMPLE, labelsMat);// 訓練分類器model->train(tData);Vec3b green(0, 255, 0), blue(255, 0, 0);// Show the decision regions given by the SVMfor (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 = model->predict(sampleMat); //進行預測,返回1或-1if (response == 1)image.at<Vec3b>(i, j) = green;else if (response == -1)image.at<Vec3b>(i, j) = blue;}// 顯示訓練數據int thickness = -1;int lineType = 8;Scalar c1 = Scalar::all(0); //標記為1的顯示成黑點Scalar c2 = Scalar::all(255); //標記成-1的顯示成白點//繪圖時,先寬后高,對應先列后行for (int i = 0; i < labelsMat.rows; i++){const float* v = trainingDataMat.ptr<float>(i); //取出每行的頭指針Point pt = Point((int)v[0], (int)v[1]);if (labels[i] == 1)circle(image, pt, 5, c1, thickness, lineType);elsecircle(image, pt, 5, c2, thickness, lineType);}imshow("SVM Simple Example", image);waitKey(0);}

例子2:

#include "opencv2/opencv.hpp" #include "opencv2/imgproc.hpp" #include "opencv2/highgui.hpp" #include "opencv2/ml.hpp"//using namespace cv; //using namespace cv::ml;int main(int argc, char** argv) {// visual representationint width = 512;int height = 512;cv::Mat image = cv::Mat::zeros(height, width, CV_8UC3);// training dataint labels[4] = { 1, -1, -1, -1 };float trainingData[4][2] = { { 501, 10 }, { 255, 10 }, { 501, 255 }, { 10, 501 } };cv::Mat trainingDataMat(4, 2, CV_32FC1, trainingData);cv::Mat labelsMat(4, 1, CV_32SC1, labels);// initial SVMcv::Ptr<cv::ml::SVM> svm = cv::ml::SVM::create();svm->setType(cv::ml::SVM::Types::C_SVC);svm->setKernel(cv::ml::SVM::KernelTypes::LINEAR);svm->setTermCriteria(cv::TermCriteria(cv::TermCriteria::MAX_ITER, 100, 1e-6));// train operationsvm->train(trainingDataMat, cv::ml::SampleTypes::ROW_SAMPLE, labelsMat);// predictioncv::Vec3b green(0, 255, 0);cv::Vec3b blue(255, 0, 0);for (int i = 0; i < image.rows; i++){for (int j = 0; j < image.cols; j++){cv::Mat sampleMat = (cv::Mat_<float>(1, 2) << j, i);float respose = svm->predict(sampleMat);if (respose == 1)image.at<cv::Vec3b>(i, j) = green;else if (respose == -1)image.at<cv::Vec3b>(i, j) = blue;}}int thickness = -1;int lineType = cv::LineTypes::LINE_8;cv::circle(image, cv::Point(501, 10), 5, cv::Scalar(0, 0, 0), thickness, lineType);cv::circle(image, cv::Point(255, 10), 5, cv::Scalar(255, 255, 255), thickness, lineType);cv::circle(image, cv::Point(501, 255), 5, cv::Scalar(255, 255, 255), thickness, lineType);cv::circle(image, cv::Point(10, 501), 5, cv::Scalar(255, 255, 255), thickness, lineType);thickness = 2;lineType = cv::LineTypes::LINE_8;cv::Mat sv = svm->getSupportVectors();for (int i = 0; i < sv.rows; i++){const float* v = sv.ptr<float>(i);cv::circle(image, cv::Point((int)v[0], (int)v[1]), 6, cv::Scalar(128, 128, 128), thickness, lineType);}cv::imshow("SVM Simple Example", image);cv::waitKey(0);return 0; }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

運行的效果如下:?

為了保證代碼可讀性,代碼沒有用using namespace cv或using namespace cv::ml;之類的代碼,全部都寫完整的名稱,命名空間+類名。比如設置SVM的核類型為線性,寫成svm->setKernel(cv::ml::SVM::KernelTypes::LINEAR);。當然,這個只是一處地方,其他的請自己閱讀。

代碼的注意事項

雖然,大家的目標很明確:導入訓練數據+label –> Mat, 訓練,預測,顯示這些目標。但是仍然避免不了代碼錯誤。下面就是我遇到的代碼的問題。

標簽以及變成Mat的數據類型

其實,在本代碼中出現了一種情況就是數據類型,下面均以標簽為例:?
這個是OpenCV3.0、OpenCV3.1正確的代碼

int labels[4] = { 1, -1, -1, -1 }; cv::Mat labelsMat(4, 1, CV_32SC1, labels);
  • 1
  • 2

下面是OpenCV 2.X 正確代碼

float labels[4] = {1.0, -1.0, -1.0, -1.0}; Mat labelsMat(3, 1, CV_32FC1, labels);
  • 1
  • 2

如果將OpenCV 2.X的代碼換到OpenCV 3.1、OpenCV3.0代碼會有什么樣子的結果呢??
?
這個很熟悉吧所以,如果傻乎乎的換,這個是行不通的。?
下面對于label和labelMat按照不同的情況進行分析。?
首先,這個labelMat和trainingMat到底能取哪幾種類型?

下面,請看OpenCV3.1 源碼中的一個部分:

void setData(InputArray _samples, int _layout, InputArray _responses,InputArray _varIdx, InputArray _sampleIdx, InputArray _sampleWeights,InputArray _varType, InputArray _missing){samples = _samples.getMat(); responses = _responses.getMat();CV_Assert( samples.type() == CV_32F || samples.type() == CV_32S );if( !responses.empty() ){CV_Assert( responses.type() == CV_32F || responses.type() == CV_32S );}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

為了方便起見,將這個函數的代碼的其他部分刪除了。首先解釋一下:samples就是訓練的數據。response就是標簽。通過上面,我們知道再來用Mat的時候,只能用CV_32F和CV_32S。所以說,如果這些矩陣不能寫什么CV_8UC1之類的了,這個是錯誤的。

假設我們寫其他的情況,比如

label為int,labelsMat為CV_32SC1

這個是正確的。

label為float,labelsMat為CV_32FC1

這個會出現錯誤,這個我還沒有分析出來是什么原因。錯誤的截圖如下:。?
下面的錯誤均表示為截圖所示的錯誤。

label為int,labelsMat為CV_32FC1

同樣的,這個是錯誤。當我們用Imagewatch插件去觀察labelsMat的值的時候發現這個labelsMat的值為。好吧,這個很明顯了。

label為float,labelsMat為CV_32SC1

這個是可以運行的,但是結果肯定是錯誤的。同樣的,值不對。

總結

以上是生活随笔為你收集整理的OpenCV3.0或OpenCV3.1的SVM操作的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。