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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

opencv画虚线_(四十四)OpenCV中的机器学习-SVM

發布時間:2025/3/20 编程问答 15 豆豆
生活随笔 收集整理的這篇文章主要介紹了 opencv画虚线_(四十四)OpenCV中的机器学习-SVM 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

時間為友,記錄點滴。

本來還想在特征點檢測的道路上再走一走,學習一下Harr級聯或者HOG什么的,但總有些概念感覺繞不過去。擇日不如撞日,撞日不如今日。我們先揭開機器學習中的一個小角,看看大熱的機器學習到底是什么東西。


啥是機器學習?

如今機器學習在中國的大熱,還是要感謝2016年Alpha Go和李世石的那場人機圍棋對決。外行人人談AI,內行深度神經網絡大紅大紫。

人工智能,機器學習,深度學習的關系

從關系上看,機器學習僅僅是實現人工智能的其中一種方式。所謂機器學習,我更愿意把機器擬人化,跟人類學習一樣,可以從經驗(數據)中去成長(學習),然后可以解決實際的問題。這個過程就是學習。人的過程就是人的學習,計算機的過程就是機器學習。

我們可以用這么定義:

機器學習=數據+算法+硬件

機器學習的分類

硬件:

我們結合上面的公式,先來看看硬件:

CPU GPU 專用芯片
  • 最開始的機器學習當然是寫成程序運行在CPU通用處理器上了;
  • 但是隨著深度學習的發展,人們發現GPU的架構更適合做深度神經網絡這種大量的簡單運算(要么NVIDIA的股票biubiu地飛);
  • 后來,人們發現可以為某個算法單獨設計一款ASIC,這樣的運算能效比比GPU更高(要么Bitcoin能挖這么快);

數據和算法:

為什么把數據和算法放一塊呢?因為他們總是相輔相成,特定的數據就需要有更優的算法來匹配。

在機器學習的算法世界里,如OpenCV的傳統算法一樣,浩如煙海,如果真的有人想要搞懂大部分的算法,一定是驚為天人了。聽說下面這個哥們用numpy手寫了好多。

ddbourgin/numpy-ml?github.com

OpenCV中的機器學習

OpenCV的ml模塊實現了很多算法,包括樸素貝葉斯、K近鄰、SVM、決策樹、Boosting、GBT、隨機森林、神經網絡等。其大多繼承自同一基類,訓練和預測的接口都是train(),predict(),使用較為方便。

我們進入到代碼里面瞅一瞅:

在源碼的opencv-4.1.1opencv-4.1.1modulesmlincludeopencv2ml.hpp文件中有提到:

ml.hpp里面包含的內容

SVM(Support Vector Machines)

如果之前沒接觸過機器學習,那么越說多越迷糊;如果之前就聽過NG大神的課,那多說就是廢話。我們既然不是以機器學習算法研究推導為主題,那么就讓我們在OpenCV中感受一個比較簡單的算法,這樣可以對機器學習的認識再向前前進一小步。

拿誰開刀呢?SVM!

SVM(Support Vector Machines)中文翻譯是支持向量機,SVM算法在在1995年正式發表,在針對中小型數據規模的分類任務上有著卓越的效果,同時有著完整的理論證明,在20世紀末的幾年和21世紀初的10年完勝神經網絡,直到深度學習的興起。但即便這樣,現在SVM算法依舊被廣泛的使用。

1、SVM要解決什么問題?

如果要搞清楚SVM是什么東西,還是要從我們為什么要引入SVM說起。

SVM主要用于解決模式識別領域中的數據分類問題,屬于有監督學習算法的一種。SVM要解決的問題可以用一個經典的二分類問題加以描述。

我們把需求簡化一下,兩個數據在笛卡爾直角平面坐標系中分別被標定成紅色點和藍色點,那么我顯然可以通過一條直線把兩個數據區分開(在數字圖像中,可以把兩個點理解成特征點和背景,所以區分數據就是提取特征點的過程)

那么問題來了,這條線該怎么畫?SVM就是來解決如何劃線的問題。

監督:人為規定此球(數據)為紅色,彼球(數據)為藍色的過程。
分類:就是把紅球和籃球分開;

2、SVM中如何畫線?

如何判斷上圖中的三條線,哪條比較好?直覺是紅色的那條,為什么呢?因為當數據變多時,紅色的線是最大可能分區數據的那條。

可以畫一條虛線連接兩個圓的圓心作為輔助線,紅線距離兩個圓的圓心都比較遠

嗯,感覺好有道理,這和SVM有什么關系呢?

我們知道,在計算機的世界里,所有的點都是離散的,比如下圖:

如何區分上圖的眾多紅球和籃球的過程中,你可以畫一條A這樣的線,也可以畫一條B這樣的線,他們都可以把紅球和籃球區分開,但是哪個是最優的呢?

可不可以借鑒兩個圓連接圓心求最大距離的思路呢?當然可以!

我們取(b)圖放大,此時A就是此時的分界線,專業稱為“決策線”。

  • 我們沿著決策線做向兩邊的平行線,直到碰到兩邊的第一個有效數據,畫兩條虛線。
  • 定義兩條虛線之間的距離為W為“分類間隔”,兩邊被虛線劃中的點叫做“支持向量”
  • 那么最佳的決策線應該是所有的支持向量到決策線的垂直距離d都相等,且最大。
  • 所以,找線的問題就轉變成求解支持向量到決策線的垂直距離d最大的問題。

    在SVM支持向量中,所有的這些數據在空間中的表達式就是一個向量,而用于直接支持確定決策線的這些點,就叫做支持向量。因此,這個算法被叫做支持向量機。

    • 數據即向量;
    • 支持確立決策線的數據即支持向量;
    • 通過支持向量求決策線的算法即支持向量機;

    好了,我們今天了解了支持向量機能做什么以及為什么叫他支持向量機。至于公式推導SVM如何做到這一切的就留給明天吧,我們今天先來看看OpenCV中官方的SVM怎么使用的。

    官方文件目錄:opencv-4.1.1samplescpptutorial_codemlintroduction_to_svmintroduction_to_svm.cpp

    C++

    這里面的三個關鍵點:

    1、數據和標簽

    int labels[4] = {1, 1, -1, -1};float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} };
    • trainingData為四個數據點(可以認為是球的圓心坐標)。
    • labels為對應數據的標簽(監督,可以認為1為紅球,-1為籃球)

    2、訓練

    svm->train(trainingDataMat, ROW_SAMPLE, labelsMat);

    如下是OpenCV中train的函數原型:

    /** @brief Trains the statistical model@param samples training samples@param layout See ml::SampleTypes.@param responses vector of responses associated with the training samples.*/CV_WRAP virtual bool train( InputArray samples, int layout, InputArray responses );

    其中:

    • Sample表示訓練樣本數據
    • Layout 有兩種組織方式ROW_SAMPLE與COL_SAMPLE
    • Responses 每個輸入樣本的標簽

    這里其實就是尋找決策線的過程。

    3、分類

    float response = svm->predict(sampleMat);

    如下是OpenCV的predict原型

    @param samples The input samples, floating-point matrix@param results The optional output matrix of results.@param flags The optional flags, model-dependent. See cv::ml::StatModel::Flags.*/CV_WRAP virtual float predict( InputArray samples, OutputArray results=noArray(), int flags=0 ) const = 0;

    其中:

    • samples:表示輸入樣本,供SVM判定。
    • OutputArray :表示輸出矩陣
    • flag:表示支持模式

    返回值為設定的標簽值(這里是1或者-1),由此可以判定當前輸入應該被分到哪一類中(也可以理解成是分在決策線的哪一邊。)

    #include <opencv2/core.hpp> #include <opencv2/imgproc.hpp> #include <opencv2/imgcodecs.hpp> #include <opencv2/highgui.hpp> #include <opencv2/ml.hpp>using namespace cv; using namespace cv::ml;int main(int, char**) {// Set up training data//! [setup1]int labels[4] = {1, 1, -1, -1};float trainingData[4][2] = { {501, 10}, {255, 10}, {501, 255}, {10, 501} };//! [setup1]//! [setup2]Mat trainingDataMat(4, 2, CV_32F, trainingData);Mat labelsMat(4, 1, CV_32SC1, labels);//! [setup2]// Train the SVM//! [init]Ptr<SVM> svm = SVM::create();svm->setType(SVM::C_SVC);svm->setKernel(SVM::LINEAR);svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));//! [init]//! [train]svm->train(trainingDataMat, ROW_SAMPLE, labelsMat);//! [train]// Data for visual representationint width = 512, height = 512;Mat image = Mat::zeros(height, width, CV_8UC3);// 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;circle( image, Point(501, 10), 5, Scalar( 0, 0, 0), thickness );circle(image, Point(255, 10), 5, Scalar(0, 0, 0), thickness);circle( image, Point(501, 255), 5, Scalar(255, 255, 255), thickness );circle( image, Point( 10, 501), 5, Scalar(255, 255, 255), thickness );//! [show_data]// Show support vectors//! [show_vectors]thickness = 2;Mat sv = svm->getUncompressedSupportVectors();for (int i = 0; i < sv.rows; i++){const float* v = sv.ptr<float>(i);circle(image, Point( (int) v[0], (int) v[1]), 6, Scalar(0, 0, 255), thickness);}//! [show_vectors]imwrite("result.png", image); // save the imageimshow("SVM Simple Example", image); // show it to the userwaitKey();return 0; }

    有了上面的監督數據+訓練+預測,代碼就好理解多了。直接看結果吧:

    代碼我稍作了修改,主要是修改了標簽值。

    讀者也可以自己改一下標簽紙,感受一下支持向量和決策邊界的移動。

    總結

    以上是生活随笔為你收集整理的opencv画虚线_(四十四)OpenCV中的机器学习-SVM的全部內容,希望文章能夠幫你解決所遇到的問題。

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