zoukankan      html  css  js  c++  java
  • 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的控制可以参阅下图

     

  • 相关阅读:
    Oracle数据库ORA-12154: TNS: 无法解析指定的连接标识符详解
    Oracle Client客户端+PLSQL配置
    函数和存过的创建调用
    MVC学习二:基础语法
    前台和后台的相互传值
    MVC学习一:EF
    博客转发小工具2
    博客转发小工具1
    博客园页面设置
    js问题杂记
  • 原文地址:https://www.cnblogs.com/easymind223/p/2574887.html
Copyright © 2011-2022 走看看