Meanshift圖像平滑之opencv實現


一句話一幅圖理解meanshift算法:

對於集合中的每一個元素,對它執行下面的操作:把該元素移動到它鄰域中所有元素的特征值的均值的位置,不斷重復直到收斂。

准確的說,不是真正移動元素,而是把該元素與它的收斂位置的元素標記為同一類。對於圖像來說,所有元素程矩陣排列,特征值便是像素的灰度值。

 

Meanshift的這種思想可以應用於目標跟蹤、圖像平滑、邊緣檢測、聚類等,是一種適應性很好的算法,缺點是速度非常慢。

本文以圖像平滑為例對其說明

  從網上找代碼不如自己動手寫。說明一下兩個參數的含義,hs和hr是核函數的窗口大小,hs是距離核函數,控制子窗口的大小,同時也影響計算速度。hr是顏色核函數,是顏色差值的閾值,maxiter是最大迭代次數。轉載請注明出處,謝謝。本文算法只是用作實驗之用,沒有進行優化,計算時會有重復計算的地方,速度非常慢,且只支持3通道圖像。

 1 void MyTreasureBox::MeanShiftSmooth(const IplImage* src, IplImage* dst, int hs, int hr, int maxIter)
 2 {
 3     if(!src)return ;
 4 
 5     IplImage* srcLUV = cvCreateImage( cvGetSize( src ), src->depth, src->nChannels );
 6     IplImage* dstLUV = cvCreateImage( cvGetSize( src ), src->depth, src->nChannels );
 7 
 8     cvCvtColor( src, srcLUV, CV_RGB2Luv);
 9     cvCopy( srcLUV, dstLUV );
10 
11     int widthstep = srcLUV->widthStep;
12     int channel = srcLUV->nChannels;
13 
14     for( int y = 0; y<src->height; y++ )
15     {
16         for( int x = 0; x<src->width; x++ )
17         {
18             uchar L = (uchar)srcLUV->imageData[y *widthstep + x *channel];
19             uchar U = (uchar)srcLUV->imageData[y *widthstep + x *channel + 1];
20             uchar V = (uchar)srcLUV->imageData[y *widthstep + x *channel + 2];
21             int xx = x;
22             int yy = y;
23 
24             int nIter = 0;
25             int count, sumL, sumu, sumv, sumx, sumy;
26 
27             while(nIter < maxIter)
28             {
29                 count = 0;
30                 sumL = sumu = sumv = 0;
31                 sumx = sumy = 0;
32 
33                 for( int m = yy - hs; m <= yy + hs; m++ )
34                 {
35                     for( int n = xx - hs; n <= xx + hs; n++ )
36                     {
37                         if(m >= 0 && m < src->height && n >= 0 && n < src->width)
38                         {
39                             uchar l = (uchar)srcLUV->imageData[m *widthstep + n *channel];
40                             uchar u = (uchar)srcLUV->imageData[m *widthstep + n *channel + 1];
41                             uchar v = (uchar)srcLUV->imageData[m *widthstep + n *channel + 2];
42 
43                             double dist = sqrt( (double)((L - l)^2 + (U - u)^2 + (V - v)^2) );
44                             if( dist < hr )
45                             {
46                                 count++;
47                                 sumL += l;
48                                 sumu += u;
49                                 sumv += v;
50                                 sumx += n;
51                                 sumy += m;
52                             }
53                         }
54                     }                    
55                 }
56                 if(count == 0)break;
57                 L = sumL / count;
58                 U = sumu / count;
59                 V = sumv / count;
60                 xx = sumx / count;
61                 yy = sumy / count;
62 
63                 nIter++;
64             }
65             dstLUV->imageData[y *widthstep + x *channel] = L;
66             dstLUV->imageData[y *widthstep + x *channel + 1] = U;
67             dstLUV->imageData[y *widthstep + x *channel + 2] = V;
68         }
69     }
70 
71     cvCvtColor( dstLUV, dst, CV_Luv2RGB );
72     cvReleaseImage(&srcLUV);
73     cvReleaseImage(&dstLUV);
74 }

hs和hr的控制可以參閱下圖

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM