Meanshift图像平滑之opencv实现

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 = y - hs; m <= y + hs; m++ )
34                 {
35                     for( int n = x - hs; n <= x + 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的控制可以参阅下图

 

 from: http://www.cnblogs.com/easymind223/archive/2012/07/03/2574887.html


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Meanshift算法是一种基于概率密度函数的追踪算法,常用于目标跟踪。在OpenCV中,可以使用cv2.meanShift()方法实现Meanshift算法。 下面是一个简单的示例代码: ```python import cv2 # 读取视频 cap = cv2.VideoCapture('test.mp4') # 获取第一帧 ret, frame = cap.read() # 定义初始窗口位置 x, y, w, h = 300, 200, 100, 50 track_window = (x, y, w, h) # 提取ROI直方图 roi = frame[y:y+h, x:x+w] hsv_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2HSV) mask = cv2.inRange(hsv_roi, (0, 60, 32), (180, 255, 255)) roi_hist = cv2.calcHist([hsv_roi], [0], mask, [180], [0, 180]) cv2.normalize(roi_hist, roi_hist, 0, 255, cv2.NORM_MINMAX) # 设置Meanshift迭代终止条件 term_crit = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 1) while True: ret, frame = cap.read() if not ret: break # 应用Meanshift算法进行目标跟踪 hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV) dst = cv2.calcBackProject([hsv], [0], roi_hist, [0, 180], 1) ret, track_window = cv2.meanShift(dst, track_window, term_crit) # 在视频中绘制跟踪框 x, y, w, h = track_window img2 = cv2.rectangle(frame, (x, y), (x+w, y+h), 255, 2) cv2.imshow('img2', img2) k = cv2.waitKey(30) & 0xff if k == 27: break cap.release() cv2.destroyAllWindows() ``` 在这个示例中,我们首先读取了一个视频,并定义了初始窗口位置。然后,我们从第一帧中提取ROI区域的直方图,并将其用于计算反向投影。最后,我们使用cv2.meanShift()方法进行目标跟踪,并在视频中绘制跟踪框。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值