OpenCV3.3中K-Means聚类接口简介及使用
????OpenCV3.3中給出了K-均值聚類(K-Means)的實現,即接口cv::kmeans,接口的聲明在include/opencv2/core.hpp文件中,實現在modules/core/src/kmeans.cpp文件中,其中:
????下面對此接口中的參數作個簡單說明:
????(1)、data:為cv::Mat類型,每行代表一個樣本,即特征,即mat.cols=特征長度,mat.rows=樣本數,數據類型僅支持float;
????(2)、K:指定聚類時劃分為幾類;
????(3)、bestLabels:為cv::Mat類型,是一個長度為(樣本數,1)的矩陣,即mat.cols=1,mat.rows=樣本數;為K-Means算法的結果輸出,指定每一個樣本聚類到哪一個label中;
????(4)、criteria:TermCriteria類,算法進行迭代時終止的條件,可以指定最大迭代次數,也可以指定預期的精度,也可以這兩種同時指定;
????(5)、attempts:指定K-Means算法執行的次數,每次算法執行的結果是不一樣的,選擇最好的那次結果輸出;
????(6)、flags:初始化均值點的方法,目前支持三種:KMEANS_RANDOM_CENTERS、KMEANS_PP_CENTERS、KMEANS_USE_INITIAL_LABELS;
????(7)、centers:為cv::Mat類型,輸出最終的均值點,mat.cols=特征長度,mat.rols=K.
????一般當attempts和TermCriteria中迭代次數值越大時,聚類效果越好。
? ? 關于K-Means聚類的簡介可以參考:?http://blog.csdn.net/fengbingchun/article/details/79276668?
????以下是從數據集MNIST中提取的40幅圖像,0,1,2,3四類各20張,如下圖:
????關于MNIST的介紹可以參考:http://blog.csdn.net/fengbingchun/article/details/49611549?
? ? 測試代碼如下:
#include "opencv.hpp"
#include <string>
#include <vector>
#include <memory>
#include <algorithm>
#include <opencv2/opencv.hpp>
#include <opencv2/ml.hpp>
#include "common.hpp"/ K-Means ///
int test_opencv_kmeans()
{const std::string image_path{ "E:/GitCode/NN_Test/data/images/digit/handwriting_0_and_1/" };cv::Mat tmp = cv::imread(image_path + "0_1.jpg", 0);CHECK(tmp.data != nullptr && tmp.channels() == 1);const int samples_number{ 80 }, every_class_number{ 20 }, categories_number{ samples_number / every_class_number};cv::Mat samples_data(samples_number, tmp.rows * tmp.cols, CV_32FC1);cv::Mat labels(samples_number, 1, CV_32FC1);float* p1 = reinterpret_cast<float*>(labels.data);for (int i = 1; i <= every_class_number; ++i) {static const std::vector<std::string> digit{ "0_", "1_", "2_", "3_" };CHECK(digit.size() == categories_number);static const std::string suffix{ ".jpg" };for (int j = 0; j < categories_number; ++j) {std::string image_name = image_path + digit[j] + std::to_string(i) + suffix;cv::Mat image = cv::imread(image_name, 0);CHECK(!image.empty() && image.channels() == 1);image.convertTo(image, CV_32FC1);image = image.reshape(0, 1);tmp = samples_data.rowRange((i - 1) * categories_number + j, (i - 1) * categories_number + j + 1);image.copyTo(tmp);p1[(i - 1) * categories_number + j] = j;}}const int K{ 4 }, attemps{ 100 };const cv::TermCriteria term_criteria = cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 100, 0.01);cv::Mat labels_, centers_;double value = cv::kmeans(samples_data, K, labels_, term_criteria, attemps, cv::KMEANS_RANDOM_CENTERS, centers_);fprintf(stdout, "K = %d, attemps = %d, iter count = %d, compactness measure = %f\n",K, attemps, term_criteria.maxCount, value);CHECK(labels_.rows == samples_number);int* p2 = reinterpret_cast<int*>(labels_.data);for (int i = 1; i <= every_class_number; ++i) {for (int j = 0; j < categories_number; ++j) {fprintf(stdout, " %d ", *p2++);}fprintf(stdout, "\n");}return 0;
}
? ? 執行結果如下:下圖中每一列表示期望是同一個label。
? ? GitHub:?https://github.com/fengbingchun/NN_Test?
總結
以上是生活随笔為你收集整理的OpenCV3.3中K-Means聚类接口简介及使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 吴恩达老师深度学习视频课笔记:单隐含层神
- 下一篇: 吴恩达老师深度学习视频课笔记:多隐含层神