首先妳要知道這是PAMI 2003的壹篇文章,非常經典的哦,Mean Shift: A Robust Approach Toward Feature Space Analysis。當然原文有17頁,都是壹些復雜的公式。。。。。
Mean shift主要用在圖像平滑和圖像分割(那個跟蹤我現在還不清楚),先介紹壹下平滑的原理:
輸入是壹個5維的空間,2維的(x,y)地理坐標,3維的(L,u,v)的顏色空間坐標,當然妳原理也可以改寫成rgb色彩空間或者是紋理特征空間。
先介紹壹下核函數,有uniform的,也有高斯的核函數,不管是哪個的,其基本思想如下:簡單的平滑算法用壹個模板平均壹下,對所有的像素,利用周圍的像素平均壹下就完事了,
這個mean shift的是基於概率密度分布來的,而且是壹種無參的取樣。有參的取樣就是假設所有的樣本服從壹個有參數的概率分布函數,比如說泊松分布,正態分布等等,高中生都知道概率公式裏面是有參數的,在說壹下特征空間是壹個5維的空間,距離用歐幾裏德空間就可以了,至少代碼裏就是這樣實現的,而本文的無參取樣是這樣的:在特征空間裏有3維的窗口(想象壹下2維空間的窗口),對於壹個特征空間的點,對應壹個5維的向量,可以計算該點的壹個密度函數,如果是有參的直接帶入該點的坐標就可以求出概率密度了,基於窗函數的思想就是考慮它鄰近窗口裏的點對它的貢獻, 它假設密度會往密集壹點的地方轉移,算出移動之後的壹個5維坐標,該坐標並會穩定,叠代了幾次之後,穩定的地方是modes。這樣每壹個像素點都對應壹個這麽壹個modes,用該點的後3維的值就是平滑的結果了,當然在算每個點的時候,有些地方可能重復計算了,有興趣的化妳可以參考壹下源代碼,確實是可以優化的。總結壹下mean shift的平滑原理就是在特征空間中向密度更高的地方shift(轉移)。
其次是怎麽利用mean shift分割圖像
先對圖像進行平滑,
第2步利用平滑結果建立區域鄰接矩陣或者區域鄰接鏈表,就是在特征空間比較近的二間在2維的圖像平面也比較接近的像素算成壹個區域,這樣就對應壹個區域的鄰接鏈表,記錄每個像素點的label值。當然代碼中有壹個傳遞凸胞的計算,合並2個表面張力很接近的相鄰區域,這個我還沒想怎麽明白,希望比較清楚的朋友講壹講。最後還有壹個合並面積較小的區域的操作,壹個區域不是對應壹個modes值嘛,在待合並的較小的那個區域中,尋找所有的鄰接區域,找到距離最小的那個區域,合並到那個區域就ok了。
void msImageProcessor::Filter(int sigmaS, float sigmaR, SpeedUpLevel speedUpLevel)這個是平滑操作,sigmaS是2維的平面窗口的窗函數,sigmaR是顏色空間的窗函數,最後壹個參數表示是否加速算法。
void msImageProcessor::FuseRegions(float sigmaS, int minRegion)這個就是合並較小區域的壹個函數。
void msImageProcessor::Segment(int sigmaS, float sigmaR, int minRegion, SpeedUpLevel speedUpLevel)這個是分割函數,裏面包括了平滑功能。再詳細的我也不說了。。。。。
最後是怎麽調用問題:void CImageProcessing::mydebug()
{
int x,y;
int width_ = imageWidth;
int height_ = imageHeight;
unsigned char *tmp = new unsigned char[width_ * height_ * 3];
unsigned char *dst = tmp;
for (x = 0;x < imageHeight; x ++)
for(y = 0;y < imageWidth; y++)
{
//Color tmp = (*imageData_RGB)(y, x);
//uchar * data = &CV_IMAGE_ELEM(ip,uchar,x,y*3) ;
// *(dst++) = data[2] ;
// *(dst++) = data[1] ;
// *(dst++) = data[0] ;
*(dst++) = (*imageData_RGB)(y, x).channel[0];
*(dst++) = (*imageData_RGB)(y, x).channel[1];
*(dst++) = (*imageData_RGB)(y, x).channel[2];
}
cbgImage_->SetImageFromRGB( tmp, width_, height_, true);
delete []tmp;
msImageProcessor *iProc = new msImageProcessor();
iProc->DefineImage(cbgImage_->im_, COLOR, height_, width_);
iProc->SetSpeedThreshold(0.1);
iProc->Segment(5,8,10,NO_SPEEDUP);
// iProc->Filter(5,8,NO_SPEEDUP);
// iProc->FuseRegions(mWinSize,mAreaSize);//°??×?Сò
} 至於怎麽調試編譯我看我是說不清楚了。。。。。。。。。。。。。。。。。。。。。。
推薦參考:/zzf378139208/blog/item/33a47c35b7ed95b9d1a2d304.html
/zzf378139208/blog/item/ee395c115019e80f203f2e85.html