EM演算法及OpenCV原始碼分析

2021-07-16 08:51:40 字數 2039 閱讀 7042

關於em原理,見:

演算法執行的開始步驟有三種指定方式。如果使用了cvem::start_auto_step,則會呼叫k-means演算法估計最初的引數,k-means會隨機地初始化類中心,kmeans_pp_centers,這會導致em演算法得到不同的結果,如果資料量越大,則這種差異性會變小。

如果指定cvem::start_e_step或cvem::start_m_step引數,則不會出現同樣的輸入資料,得到不同結果的現象。如果指定cvem::start_m_step引數,則以m步開始,

m步固定

如果指定cvem::start_e_step,則以e步開始,cvemparams::means必須給出,cvemparams::weights和cvemparams::covs引數可給出可不給出,weights代表初始的各個成分的概率。

演算法執行的終止條件。em演算法是迭代演算法,自然終止條件可以是迭代次數達到了,或者兩次迭代之間的差異小於epsilon就結束。

關於引數的解析,請參照機器學習中文參考手冊。

trainloglikelihooddelta 表示兩次相鄰迭代過程中對數似然概率的增量。

e-step 原始碼:

注意上面的公式,轉換到log後,相乘除的變為相加減

vec2d em::computeprobabilities(const mat& sample, mat* probs) const

cv_dbgassert(!logweightdivdet.empty());

l.at(clusterindex) = logweightdivdet.at(clusterindex) - 0.5 * lval;

// note: logweightdivdet = log(weight_k) - 0.5 * log(|det(cov_k)|)

// note: l.at(clusterindex) = log(weight_k) - 0.5 * log(|det(cov_k)|)-0.5 * lval

if(l.at(clusterindex) > l.at(label))

label = clusterindex; //求似然最大的label值

}double maxlval = l.at(label); //

mat expl_lmax = l; // exp(l_ij - l_iq) //l 1*nclusters

for(int i = 0; i < l.cols; i++)

expl_lmax.at(i) = std::exp(l.at(i) - maxlval);

double expdiffsum = sum(expl_lmax)[0]; // sum_j(exp(l_ij - l_iq))

if(probs) //probs

vec2d res;

res[0] = std::log(expdiffsum) + maxlval - 0.5 * dim * cv_log2pi; //dim樣本維數 cv_log2pi (1.8378770664093454835606594728112)

opencv原始碼檢視

1 針對opencv自帶的函式 cv.h中宣告的函式 可直接選擇函式,右鍵轉到宣告 h檔案 或轉到定義 cpp檔案 2 source modules下的函式不能直接跳轉到定義,需要先編譯,此處用cmake編譯原始碼 a 安裝,官網中包括源 sources 需自己編譯 和二進位制檔案 已編譯好 此處選...

OpenCV原始碼閱讀 1

開始從讀取檔案的函式說起,這裡主要有兩個函式用於讀取影象的 實際上,當我們在做數字影象處理系統的時候,主要要考慮的也是怎麼讀乙個進來。第乙個函式 cvloadimage主要是用於返回乙個iplimage 的資料結構。第二個函式 cvloadimagem主要是用於返回乙個cvmat 的資料結構。實際上...

Opencv原始碼閱讀 HogDescriptor

opencv中hog特徵提取寫在類hogdescriptor中 預設的建構函式如下 cv wraphogdescriptor winsize 64,128 blocksize 16,16 blockstride 8,8 cellsize 8,8 nbins 9 derivaperture 1 win...