OpenCv Kmeans演算法及實現

2021-07-02 00:22:15 字數 3713 閱讀 1588

kmeans演算法:基於劃分的聚類方法,適用於資料預處理,但影象分割的消耗的時間太長並且效果不怎麼好。

基本思想:以空間中k個點為中心進行聚類,對最靠近他們的物件歸類。通過迭代,逐次更新各聚類中心的值,直到得到最好的聚類結果。

演算法描述:

1、適當選擇c個類的初始中心;

2、在第k次迭代中,對任意乙個樣本,求其到c個中心的距離,將該樣本歸到距離最短的中心所在的類;

3、利用均值等方法更新該類的中心值;

4、對於所有的c個類的聚類中心,如果利用2、3的迭代更新後,值保持不變,則迭代結束,否則,繼續。

該演算法的最大優勢在於簡潔、快速。

關鍵在於:初始中心的選擇和距離公式。

演算法流程:

1、從n個資料中任意選擇k個物件作為初始聚類中心;

2、對於剩下的,根據他們與這些聚類中心的相似度(距離),分別將其分配給與之最相似的聚類;

3、再計算每個所獲新聚類的聚類中心(該聚類內所有物件的均值);

4、重複上述,直到標準測度函式開始收斂為止。

一般採用均方差作為標準測度函式。

k個聚類各聚類本身盡可能緊湊,但是各聚類之間盡可能的分散。

演算法缺陷:

1、必須人為指定所聚的類的個數k,但實際情況中,往往很難確定中的類別數。;

2、如果使用歐式距離來衡量相似度的話,可能會得到錯誤的結果,因為沒有考慮到屬性的重要性和相關性。

為了減少這種錯誤,在使用kmeans距離時,一定要使樣本的每一維資料歸一化,不然的話由於樣本的屬性範圍不同會導致錯誤的結果。

3、使用空間資訊後,影象的分割後受空間的影響大(同一類的資料如果分布較遠,不是高斯型的,就會錯分),因為影象分割本身要求資料是呈超球體(高斯類)分布。k-means得到的是線性判決面,因為演算法使用的準則函式是最小均方誤差,相當於不同類別間求最小二乘直線擬合。

4、在opencv裡判斷聚類誤差是由類別中心點的兩次迭代結果的差決定的,即當類別中心點都變化不大時或者說不變時,聚類結束。多次執行程式會發現不同的結果,因為程式可能會陷入不同的區域性極值,所以如果要找到全域性最優,可以多次執行找出誤差最小值。

涉及到的函式簡介:

1、void rng::fill(inputoutputarray mat, int disttype, inputarray a, inputarray b, bool saturaterange=false )

功能:對矩陣mat填充隨機數,隨機數的產生方式有引數「int disttype

」來決定,如果其型別為rng::uniform,則表示產生均一分布的隨機數,如果為rng::normal則表示產生高斯分布的隨機數。

對應的「inputarray a, inputarray b,

」為上面兩種隨機數產生模型的引數。如果隨機數產生模型為均勻分布,則引數a表示均勻分布的下限,引數b表示上限。如果隨機數產生模型為高斯模型,則引數a表示均值,引數b表示方程。

bool saturaterange=false

」只有當隨機數產生方式為均勻分布時才有效,表示是否產生的資料要布滿整個範圍。

用來儲存隨機數的矩陣mat可以是多維的,也可以是多通道的,目前最多只能支援4個通道。

2、void randshuffle(inputoutputarray dst, double ite***ctor=1., rng* rng=0 )

功能:隨機打亂1d陣列dst裡面的資料,隨機打亂的方式由隨機數發生器rng決定。ite***ctor為隨機打亂資料對數的因子,總共打亂的資料對數為:dst.rows*dst.cols*ite***ctor,如果為0,表示沒有打亂資料。

3、class termcriteria

功能:類termcriteria 一般表示迭代終止的條件,如果為cv_termcrit_iter,則用最大迭代次數作為終止條件,如果為cv_termcrit_eps 則用精度作為迭代條件,如果為cv_termcrit_iter+cv_termcrit_eps則用最大迭代次數或者精度作為迭代條件,看哪個條件先滿足。

4、double kmeans(inputarray data, int k, inputoutputarray bestlabels, termcriteria criteria, int attempts, int flags, outputarray centers=noarray() )

功能:該函式為kmeans聚類演算法實現函式。

引數data表示需要被聚類的原始資料集合,一行表示乙個資料樣本,每乙個樣本的每一列都是乙個屬性;

引數k表示需要被聚類的個數;

引數bestlabels表示每乙個樣本的類的標籤,是乙個整數,從0開始的索引整數;

引數criteria表示的是演算法迭代終止條件;

引數attempts表示執行kmeans的次數,取結果最好的那次聚類為最終的聚類,要配合下乙個引數flages來使用;

引數flags表示的是聚類初始化的條件。

其取值有3種情況,如果為kmeans_random_centers,則表示為隨機選取初始化中心點,如果為kmeans_pp_centers則表示使用某一種演算法來確定初始聚類的點;如果為kmeans_use_initial_labels,則表示使用使用者自定義的初始點,但是如果此時的attempts大於1,則後面的聚類初始點依舊使用隨機的方式;

引數centers表示的是聚類後的中心點存放矩陣。

該函式返回的是聚類結果的緊湊性,其計算公式為:

在使用k-means函式時,注意輸入和輸出矩陣的資料型別,是32fc1

。輸入矩陣的每一行是乙個輸入向量。opencv矩陣的特點是,矩陣的元素本身可以是個向量,即元素的資料通道,這樣方便影象處理。所以乙個樣本向量可以用矩陣的一行表示即單通道多資料,也可以用乙個多資料通道的矩陣元素表示。

**實現:

#include

#include

#include

using namespace cv;

using namespace std;

int main( )

;mat img(500, 500, cv_8uc3);

rng rng(123456); //隨機數產生器

while(1)

randshuffle(points, 1, &rng);

//因為要聚類,所以先隨機打亂points裡面的點,注意points和pointchunk是共用資料的。

kmeans(points, clustercount, labels,

termcriteria( cv_termcrit_eps+cv_termcrit_iter, 10, 1.0),

3, kmeans_pp_centers, centers);

//聚類3次,取結果最好的那次,聚類的初始化採用pp特定的隨機演算法。

img = scalar::all(0);

for( i = 0; i < samplecount; i++ )

imshow("clusters", img);

char key = (char)

waitkey();     //等待

if( key == 27  ) // 'esc'

break;

}return 0;

}

Opencv Kmeans聚類演算法

k means 演算法接受輸入量 k 然後將n個資料物件劃分為 k個聚類以便使得所獲得的聚類滿足 同一聚類中的物件相似度較高 而不同聚類中的物件相似度較小 1.演算法基本步驟 1 從 n個資料物件任意選擇 k 個物件作為初始聚類中心 2 根據每個聚類物件的均值 中心物件 計算每個物件與這些中心物件的...

Opencv Kmeans聚類演算法

k means 演算法接受輸入量 k 然後將n個資料物件劃分為 k個聚類以便使得所獲得的聚類滿足 同一聚類中的物件相似度較高 而不同聚類中的物件相似度較小 1.演算法基本步驟 1 從 n個資料物件任意選擇 k 個物件作為初始聚類中心 2 根據每個聚類物件的均值 中心物件 計算每個物件與這些中心物件的...

演算法及演算法效率

一 演算法的定義 演算法是解決特定問題求解步驟的描述,在計算機中表現為指令的有限序列,並且每條指令表示乙個或多個操作。二 演算法的特性 輸入輸出 演算法就有零個或多個輸入,演算法至少要有乙個或多個輸出 有窮性 在演算法執行有限的步驟後,自動結束而不是出現無限迴圈,並且每乙個步驟在可接受範圍內完成。確...