OpenCV利用K-means實(shí)現(xiàn)根據(jù)顏色進(jìn)行圖像分割
K-means算法分割
K-means是一種經(jīng)典的無監(jiān)督聚類算法---不需要人工干預(yù)。
算法原理:
(1)隨機(jī)選擇兩個(gè)中心點(diǎn);
(2)計(jì)算每個(gè)點(diǎn)到這兩個(gè)中心點(diǎn)的距離,最近的分成一類(連接起來);
(3)重新計(jì)算中心點(diǎn)(平均值計(jì)算),計(jì)算新的中心點(diǎn)到舊的中心點(diǎn)的差值如果小于輸入的值,就說明中心的位置發(fā)生了變化,,那么到(2)步重新計(jì)算中心點(diǎn)到每個(gè)點(diǎn)的距離,開始下一次循環(huán);
(4)執(zhí)行多個(gè)迭代之后,滿足收斂時(shí),得到最終的分類
應(yīng)用:分類
根據(jù)顏色分類
#include<opencv2/opencv.hpp> #include<iostream> int main(int argc, char** argv) { cv::Mat img(500, 500, CV_8UC3); cv::RNG rng(12345); cv::Scalar colorTab[] = { cv::Scalar(0, 0, 255), cv::Scalar(0, 255, 0), cv::Scalar(255, 0, 0), cv::Scalar(0, 255, 255), cv::Scalar(255, 0, 255) }; int numCluster = rng.uniform(2, 5); printf("種類數(shù)量 : %d\n", numCluster); //4 int sampleCount = rng.uniform(2, 1000);//隨機(jī)樣本 printf("樣本數(shù)量 : %d\n", sampleCount); //591 cv::Mat points(sampleCount, 1, CV_32FC2); cv::Mat labels; cv::Mat centers; for (int k = 0; k < numCluster; k++) { cv::Point center; center.x = rng.uniform(0, img.cols);//隨機(jī)坐標(biāo) center.y = rng.uniform(0, img.rows); cv::Mat pointChunk = points.rowRange(k * sampleCount / numCluster, k == numCluster - 1 ? sampleCount : (k + 1) * sampleCount / numCluster); //每一類占1/numCluster 行 //rng.fill(pointChunk, cv::RNG::NORMAL, cv::Scalar(center.x, center.y), cv::Scalar(img.cols * 0.05, img.rows * 0.05));//用隨機(jī)數(shù)填充矩陣 rng.fill(pointChunk, cv::RNG::UNIFORM, 0, 255);//用隨機(jī)數(shù)填充矩陣 } randShuffle(points, 1, &rng);//算法打亂元素排列順序 kmeans(points, numCluster, labels, cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::COUNT, 10, 0.1), 3, cv::KMEANS_PP_CENTERS, centers); /*【根據(jù)參數(shù)1的坐標(biāo)進(jìn)行分類】 參數(shù)1:為cv::Mat類型,每行代表一個(gè)樣本,即特征,即mat.cols=特征長度,mat.rows=樣本數(shù),數(shù)據(jù)類型僅支持float 參數(shù)2:K 指定聚類時(shí)劃分為幾類 參數(shù)3:為cv::Mat類型,是一個(gè)長度為(樣本數(shù),1)的矩陣,即mat.cols=1,mat.rows=樣本數(shù);為K-Means算法的結(jié)果輸出,指定每一個(gè)樣本聚類到哪一個(gè)label中【指定每一個(gè)樣本聚類到哪一類中】 參數(shù)4:TermCriteria類,算法進(jìn)行迭代時(shí)終止的條件,可以指定最大迭代次數(shù),也可以指定預(yù)期的精度,也可以這兩種同時(shí)指定; 參數(shù)1:int type type=TermCriteria::MAX_ITER/TermCriteria::COUNT 迭代到最大或迭代次數(shù)終止 type= TermCriteria::EPS 迭代到閾值終止 type= TermCriteria::MAX_ITER+ TermCriteria::EPS 上述兩者都作為迭代終止條件 參數(shù)2:int maxCount 迭代的最大次數(shù) 參數(shù)3:double epsilon 閾值(中心位移值) 參數(shù)5:指定K-Means算法執(zhí)行的次數(shù),每次算法執(zhí)行的結(jié)果是不一樣的,選擇最好的那次結(jié)果輸出 參數(shù)6:初始化均值點(diǎn)的方法,目前支持三種:KMEANS_RANDOM_CENTERS、KMEANS_PP_CENTERS、KMEANS_USE_INITIAL_LABELS 參數(shù)7:為cv::Mat類型,輸出最終的均值點(diǎn),mat.cols=特征長度,mat.rols=K 【每個(gè)類的中心點(diǎn)】 */ // 用不同顏色顯示分類 //初始化圖片顏色。 img = cv::Scalar::all(255); for (int i = 0; i < sampleCount; i++) { int index = labels.at<int>(i); //獲取ponint點(diǎn) cv::Point p = points.at<cv::Point2f>(i); //填充 circle(img, p, 2, colorTab[index], -1, 8); } // 每個(gè)聚類的中心來繪制圓 for (int i = 0; i < centers.rows; i++) { int x = centers.at<float>(i, 0); int y = centers.at<float>(i, 1); printf("c.x= %d, c.y=%d", x, y); circle(img, cv::Point(x, y), 40, colorTab[i], 1, cv::LINE_AA); } imshow("KMeans-Data-Demo", img); cv::waitKey(0); return 0; }
實(shí)例
2.png
#include<opencv2/opencv.hpp> #include<iostream> int main(int argc, char** argv) { cv::Scalar colorTab[] = { cv::Scalar(0, 0, 255), cv::Scalar(0, 255, 0), cv::Scalar(255, 0, 0), cv::Scalar(0, 255, 255), }; cv::Mat src = cv::imread("D:/bb/tu1/2.png"); if (!src.data) { printf("圖像讀取失敗...\n"); return -1; } cv::imshow("src", src); int width = src.cols; int height = src.rows; int dims = src.channels(); int sampleCount = width * height; //總像素 int clusterCount = 4; //分類數(shù)量 cv::Mat points(sampleCount, dims,CV_32F,cv::Scalar(10)); //一個(gè)像素為一行 cv::Mat labels; cv::Mat centers(clusterCount,1, points.type()); //保存中心坐標(biāo) //把RGB數(shù)據(jù)轉(zhuǎn)換成樣本數(shù)據(jù) int index = 0;//像素序號 for (int row = 0; row < height;row++) { for (int col = 0; col < width;col++) { index = row * width + col; cv::Vec3b bgr = src.at<cv::Vec3b>(row, col); points.at<float>(index, 0) = static_cast<int>(bgr[0]); points.at<float>(index, 1) = static_cast<int>(bgr[1]); points.at<float>(index, 2) = static_cast<int>(bgr[2]); } } cv::TermCriteria criteria = cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS,10,0.1); //kmeans的終止的條件 kmeans(points, clusterCount, labels, criteria, 3, cv::KMEANS_PP_CENTERS, centers);//運(yùn)行kmeans //顯示圖像分割結(jié)果 cv::Mat result = cv::Mat::zeros(src.size(),src.type()); for (int row = 0; row < height;row++) { for (int col = 0; col < width;col++) { index = row * width + col; int label = labels.at<int>(index, 0); //獲取類序號 result.at<cv::Vec3b>(row, col)[0] = colorTab[label][0]; result.at<cv::Vec3b>(row, col)[1] = colorTab[label][1]; result.at<cv::Vec3b>(row, col)[2] = colorTab[label][2]; } } cv::imshow("result", result); cv::waitKey(0); return 0; }
以上就是OpenCV利用K-means實(shí)現(xiàn)根據(jù)顏色進(jìn)行圖像分割的詳細(xì)內(nèi)容,更多關(guān)于OpenCV K-means圖像分割的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語言實(shí)現(xiàn)猜數(shù)字游戲的兩種方法
猜數(shù)字小游戲是我們大多數(shù)人學(xué)習(xí)C語言時(shí)都會(huì)了解到的一個(gè)有趣的C語言小游戲,本文就詳細(xì)的介紹一下,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-01-01剖析C++中的常量表達(dá)式與省略號的相關(guān)作用
這篇文章主要介紹了C++中的常量表達(dá)式與省略號的相關(guān)作用,以及表達(dá)式中的可變參數(shù)模板示例,需要的朋友可以參考下2016-01-01Qt+OpenCV實(shí)現(xiàn)目標(biāo)檢測詳解
這篇文章主要介紹了如何利用Qt和OpenCV中自帶xml文件實(shí)現(xiàn)目標(biāo)檢測,文中的實(shí)現(xiàn)過程講解詳細(xì),感興趣的小伙伴可以動(dòng)手試一試2022-03-03Qt串口通信開發(fā)之Qt串口通信模塊QSerialPort開發(fā)完整實(shí)例(串口助手開發(fā))
這篇文章主要介紹了Qt串口通信開發(fā)之Qt串口通信模塊QSerialPort開發(fā)完整實(shí)例(串口助手開發(fā)),需要的朋友可以參考下2020-03-03C語言 volatile與const同時(shí)使用應(yīng)注意的問題
“volatile”的含義是“請不要做沒譜的優(yōu)化,這個(gè)值可能變掉的”,而并非“你可以修改這個(gè)值”。因此,它們本來就不是矛盾的2013-09-09