zoukankan      html  css  js  c++  java
  • opencv源码学习: getGaussianKernel( 高斯核);

    参考: https://blog.csdn.net/u012633319/article/details/80921023

    二维高斯核, 可以根据下面的公式推到为两个一维高斯核的乘积:

    原型:

    /** @brief Returns Gaussian filter coefficients.
    
    The function computes and returns the f$	exttt{ksize} 	imes 1f$ matrix of Gaussian filter
    coefficients:
    
    f[G_i= alpha *e^{-(i-( 	exttt{ksize} -1)/2)^2/(2* 	exttt{sigma}^2)},f]
    
    where f$i=0..	exttt{ksize}-1f$ and f$alphaf$ is the scale factor chosen so that f$sum_i G_i=1f$.
    
    Two of such generated kernels can be passed to sepFilter2D. Those functions automatically recognize
    smoothing kernels (a symmetrical kernel with sum of weights equal to 1) and handle them accordingly.
    You may also use the higher-level GaussianBlur.
    @param ksize Aperture size. It should be odd ( f$	exttt{ksize} mod 2 = 1f$ ) and positive.
    @param sigma Gaussian standard deviation. If it is non-positive, it is computed from ksize as
    `sigma = 0.3*((ksize-1)*0.5 - 1) + 0.8`.
    @param ktype Type of filter coefficients. It can be CV_32F or CV_64F .
    @sa  sepFilter2D, getDerivKernels, getStructuringElement, GaussianBlur
     */
    CV_EXPORTS_W Mat getGaussianKernel( int ksize, double sigma, int ktype = CV_64F );

    源码分析:

    cv::Mat cv::getGaussianKernel( int n, double sigma, int ktype )
    {
        const int SMALL_GAUSSIAN_SIZE = 7;
        static const float small_gaussian_tab[][SMALL_GAUSSIAN_SIZE] =
        {
            {1.f},
            {0.25f, 0.5f, 0.25f},
            {0.0625f, 0.25f, 0.375f, 0.25f, 0.0625f},
            {0.03125f, 0.109375f, 0.21875f, 0.28125f, 0.21875f, 0.109375f, 0.03125f}
        };
    
        //判断是否满足预置的高斯模板;
        const float* fixed_kernel = n % 2 == 1 && n <= SMALL_GAUSSIAN_SIZE && sigma <= 0 ?
            small_gaussian_tab[n>>1] : 0;
    
        CV_Assert( ktype == CV_32F || ktype == CV_64F );          //仅支持两种格式,  32, 64位;
        Mat kernel(n, 1, ktype);                  //创建核模板, ktype为指定的类型;
        float* cf = kernel.ptr<float>();
        double* cd = kernel.ptr<double>();
        //如果sigma < 0, 那么更具模板尺寸计算sigma;
        double sigmaX = sigma > 0 ? sigma : ((n-1)*0.5 - 1)*0.3 + 0.8;
        double scale2X = -0.5/(sigmaX*sigmaX);
        double sum = 0;
    
        int i;
        for( i = 0; i < n; i++ )
        {
            double x = i - (n-1)*0.5;
            double t = fixed_kernel ? (double)fixed_kernel[i] : std::exp(scale2X*x*x);                //使用预置模板或者根据高斯函数计算高斯模板;
            if( ktype == CV_32F )          //把计算得到的核填到模板中;
            {
                cf[i] = (float)t;
                sum += cf[i];
            }
            else
            {
                cd[i] = t;
                sum += cd[i];
            }
        }
    
        sum = 1./sum;
        for( i = 0; i < n; i++ )            //归一化;
        {
            if( ktype == CV_32F )
                cf[i] = (float)(cf[i]*sum);
            else
                cd[i] *= sum;
        }
    
        return kernel;
    }
  • 相关阅读:
    项目经理-要材料
    java stream 处理
    listGiftBagShowInfo 这个方法 我搞了一晚上
    BigDecimal.ROUND_UP 如果 从 double 到 Decimal 有异常, 必须从double到String然后 Decimal 就可以了
    json串 转 list<class> 方法 List转JSONArray和JSONArray转List
    昨晚加班到3点多-身体都虚脱了
    MVN 点击compile总是失败
    IDEA使用笔记(八)——自动生成 serialVersionUID 的设置
    Maven 版本号规范
    java多线程学习
  • 原文地址:https://www.cnblogs.com/yinwei-space/p/9833440.html
Copyright © 2011-2022 走看看