菜单

betway体育导向滤波算法的落实。导向滤波算法的实现。

2018年9月24日 - 中甲报道

由上篇导向滤波算法分析,根据(5)~(8)式就可测算输出图像Q

由上篇导向滤波算法分析,根据(5)~(8)式就得测算输出图像Q

betway体育 1  (5)

betway体育 2  (5)

betway体育 3  (6)

betway体育 4  (6)

betway体育 5  (7)

betway体育 6  (7)

betway体育 7  (8)

betway体育 8  (8)

其中betway体育 9betway体育 10,/ai和/bi的结果如算有所覆盖了例如素i的窗口Wk的ak和bk的平均值。除了用平均值,在事实上采用被,我还看了其它的计算/ai和/bi的艺术。比如根据像素i在窗口Wk的职务,给予不同的权重。如果i距离窗口Wk的主干位置更远,则给予ak和bk越低的权重。如果i位于窗口中心,则ak和bk发最高的权重。最常用之虽是因此高斯分布来给不同之权重。这样考虑到了紧邻像从距离远近对i影响的高低,最后的结果碰头又规范一些。

其中betway体育 11betway体育 12,/ai和/bi的结果一旦算有所覆盖了例如素i的窗口Wk的ak和bk的平均值。除了用平均值,在骨子里运用被,我还见到了任何的计算/ai和/bi的计。比如根据像素i在窗口Wk的岗位,给予不同之权重。如果i距离窗口Wk的核心岗位更远,则给予ak和bk越低的权重。如果i位于窗口中心,则ak和bk发生高的权重。最常用之便是因此高斯分布来予以不同之权重。这样考虑到了邻近像从距离远近对i影响的分寸,最后之结果碰头重新精确一些。

此间我或者用极简易的平均值的办法来计算/ai和/bi。我们眼前早已使了以窗口Wk内,ak和bk是常数,因此ak和bk只和Wk的位置有关。取Wk否半径为r的方形窗口,使窗口的中心像从位置遍历整个图像,那么就算设Wk赢得到了不同之兼具位置,在每个位置计算产生相应的ak和bk。所有的ak和bk构成了同输入图像P相同长宽维度的多寡集合,记为A和B。对于自由像素i,/ai和/bi纵使分别吗缘i为主导半径r的窗口Wk内A和B的多寡都值,这不正是我们熟悉的图像均值模糊的算法也?而图像均值模糊有几栽于成熟的飞速算法,比如积分图算法和冲直方图的敏捷算法。只要出矣A和B,就得方便之以均值模糊得出/ai和/bi,从而使(8)计算出输出图像Q。

此间我还是用最好简便易行的平均值的方式来计算/ai和/bi。我们前面早已使了当窗口Wk内,ak和bk是常数,因此ak和bk只和Wk的岗位有关。取Wk也半径为r的方形窗口,使窗口的基本像从位置遍历整个图像,那么就算假设Wk抱到了不同之兼具位置,在每个位置计算产生相应的ak和bk。所有的ak和bk做了跟输入图像P相同长宽维度的数量集合,记为A同B。对于自由像素i,/ai和/bi不怕分别吗坐i为主导半径r的窗口Wk内A和B的数量都值,这不正是我们熟悉的图像均值模糊的算法也?而图像均值模糊有几乎栽于成熟之敏捷算法,比如积分图算法和依据直方图的飞快算法。只要发生矣A和B,就好好的用均值模糊得出/ai和/bi,从而以(8)计算起输出图像Q。

以计算A和B,从(6)式看到,需要各自计输入图像P和导向图G的均值模糊结果。而(5)式需要计算导向图G的方差,还有P和G的协方差。方差和协方差且关涉到乘积的恳求与测算,可以由下的公式,通过积分图来计算。这简单只公式很爱推导出来,就未赘述了。

为了计算A和B,从(6)式看到,需要各自计输入图像P和导向图G的均值模糊结果。而(5)式需要算导向图G的方差,还有P和G的协方差。方差和协方差且干到乘积的求与计算,可以由下的公式,通过积分图来测算。这有限单公式很易推导出来,就无赘述了。

betway体育 13

betway体育 14

betway体育 15

betway体育 16

一个平方和,一个积及还可以为此积分图来算。只是要留意当图像足够大的时节,要用当的数据类型。假设像从的数码范围是0~255的整型,如果平方积分图用32各之整型数据,那么只能支持不过要命256×256轻重的图像。超过此分寸,就非得使用64各类的整型了。下面给起下模板函数的乘积积分图函数,可以依据需要利用不同的数据类型。p1和p2是图像数据指针,当它对准相同之多少时,这个函数就成了平方积分图。注意积分图的长宽比原始数据的增长宽都设大1。

一个平方和,一个积及还得以据此积分图来算。只是要留心当图像足够好的时刻,要因此合适的数据类型。假设像从的数目范围是0~255的整型,如果平方积分图用32号之整型数据,那么只能支持不过酷256×256大大小小的图像。超过这分寸,就务须使用64员的整型了。下面给有下模板函数的乘积积分图函数,可以根据需要采用不同的数据类型。p1和p2是图像数据指针,当它对准相同之多少常常,这个函数就改为了平方积分图。注意积分图的丰富宽比原始数据的长宽都设大1。

betway体育 17betway体育 18

betway体育 19betway体育 20

/* Cumulative image of the multiplication of p1.*p2.
 p1 and p2 can be the same pointer and it becomes square cumulative image.
 The returned cumulative image MUST be freed by the caller! */
template <class T1, class T2, class T3>
BOOL MultiplyCumImage(T1 *p1, T2 *p2, T3 **ppCum)
{
    long i, j;
    long Width = GetWidth();
    long Height = GetHeight();
    long integral_len = (Width + 1)*(Height + 1);

    // Only allocate cumulative image memory when *ppCum is NULL
    if (*ppCum == NULL)
    {
        try { *ppCum = new T3[integral_len]; }
        catch (CException *pe)
        {
            pe->Delete();
            return FALSE;
        }
    }
    memset(*ppCum, 0, sizeof(T3)*integral_len);
    // The cumulative values of the leftmost and the topmost pixels are always 0.
    for (i = 1; i <= Height; i++)
    {
        T3 *prow, *puprow;
        prow = *ppCum + i*(Width + 1);
        puprow = *ppCum + (i - 1)*(Width + 1);
        T3 sum = 0;
        long up_row_idx = (i - 1)*Width;
        for (j = 1; j <= Width; j++)
        {
            long idx = up_row_idx + j - 1;
            sum += p1[idx] * p2[idx];
            prow[j] = puprow[j] + sum;
        }
    }
    return TRUE;
}
/* Cumulative image of the multiplication of p1.*p2.
 p1 and p2 can be the same pointer and it becomes square cumulative image.
 The returned cumulative image MUST be freed by the caller! */
template <class T1, class T2, class T3>
BOOL MultiplyCumImage(T1 *p1, T2 *p2, T3 **ppCum)
{
    long i, j;
    long Width = GetWidth();
    long Height = GetHeight();
    long integral_len = (Width + 1)*(Height + 1);

    // Only allocate cumulative image memory when *ppCum is NULL
    if (*ppCum == NULL)
    {
        try { *ppCum = new T3[integral_len]; }
        catch (CException *pe)
        {
            pe->Delete();
            return FALSE;
        }
    }
    memset(*ppCum, 0, sizeof(T3)*integral_len);
    // The cumulative values of the leftmost and the topmost pixels are always 0.
    for (i = 1; i <= Height; i++)
    {
        T3 *prow, *puprow;
        prow = *ppCum + i*(Width + 1);
        puprow = *ppCum + (i - 1)*(Width + 1);
        T3 sum = 0;
        long up_row_idx = (i - 1)*Width;
        for (j = 1; j <= Width; j++)
        {
            long idx = up_row_idx + j - 1;
            sum += p1[idx] * p2[idx];
            prow[j] = puprow[j] + sum;
        }
    }
    return TRUE;
}

View
Code

View
Code

 这样导向滤波实现的重大问题还解决了,算法步骤如下:

 这样导向滤波实现的根本问题都解决了,算法步骤如下:

  1. 算引导图G的积分图和平方积分图
  2. 算算输入图像P的积分图, P和G的乘积积分图
  3. 故此上少步得起的积分图计算P和G的均值,G的方差,P和G的协方差,窗口半径为r
  4. 接下来据此(5)(6)式计算系数图A和B
  5. 计算A和B的积分图
  6. 计算A和B的窗口半径r的均值,并为此(8)式计算输出图Q
  1. 算引导图G的积分图和平方积分图
  2. 算算输入图像P的积分图, P和G的乘积积分图
  3. 据此上点滴步得发的积分图计算P和G的均值,G的方差,P和G的协方差,窗口半径为r
  4. 接下来据此(5)(6)式计算系数图A和B
  5. 计算A和B的积分图
  6. 计算A和B的窗口半径r的均值,并因此(8)式计算输出图Q

 下面的参阅代码中,pData存储输入和出口图像,pGuidedData引导图,radius领域半径

 下面的参考代码中,pData存储输入和输出图像,pGuidedData引导图,radius领域半径

betway体育 21betway体育 22

betway体育 23betway体育 24

    long len = Width*Height;

    // Cululative image and square cululative for guided image G
    UINT64 *pCum = NULL, *pSquareCum = NULL;
    CumImage(pGuidedData, &pCum);
    MultiplyCumImage(pGuidedData, pGuidedData, &pSquareCum);

    // Allocate memory for a and b
    float *pa, *pb;
    pa = new float[len];
    pb = new float[len];
    memset(pa, 0, sizeof(float)*len);
    memset(pb, 0, sizeof(float)*len);

    UINT64 *pInputCum = NULL, *pGPCum = NULL;
    CumImage(pData, &pInputCum);
    MultiplyCumImage(pGuidedData, pData, &pGPCum);

    int field_size;
    UINT64 cum, square_cum;
    long uprow, downrow, upidx, downidx;        // In cumulative image
    long leftcol, rightcol;
    float g_mean, g_var;        // mean and variance of guided image
    long row_idx = 0;
    UINT64 p_cum, gp_cum;
    float p_mean;
    // Calculate a and b
    // Since we're going to calculate cumulative image of a and b, we have to calculate the whole image of a and b.
    for (i = 0; i < Height; i++)
    {
        // Check the boundary for radius
        if (i < radius) uprow = 0;
        else uprow = i - radius;
        upidx = uprow*(Width + 1);
        if (i + radius >= Height) downrow = Height;
        else downrow = i + radius + 1;
        downidx = downrow*(Width + 1);
        for (j = 0; j < Width; j++)
        {
            // Check the boundary for radius
            if (j < radius) leftcol = 0;
            else leftcol = j - radius;
            if (j + radius >= Width) rightcol = Width;
            else rightcol = j + radius + 1;
            field_size = (downrow - uprow)*(rightcol - leftcol);
            long p1, p2, p3, p4;
            p1 = downidx + rightcol;
            p2 = downidx + leftcol;
            p3 = upidx + rightcol;
            p4 = upidx + leftcol;
            // Guided image summary in the field
            cum = pCum[p1] - pCum[p2] - pCum[p3] + pCum[p4];
            // Guided image square summary in the field
            square_cum = pSquareCum[p1] - pSquareCum[p2] - pSquareCum[p3] + pSquareCum[p4];
            // Field mean
            g_mean = (float)(cum) / field_size;
            // Field variance
            g_var = float(square_cum) / field_size - g_mean * g_mean;
            // Summary of input image in the field
            p_cum = pInputCum[p1] - pInputCum[p2] - pInputCum[p3] + pInputCum[p4];
            // Input image field mean
            p_mean = float(p_cum) / field_size;
            // Multiply summary in the field
            gp_cum = pGPCum[p1] - pGPCum[p2] - pGPCum[p3] + pGPCum[p4];
            long idx = row_idx + j;
            pa[idx] = (float(gp_cum) / field_size - g_mean*p_mean) / (g_var + epsilon);
            pb[idx] = p_mean - g_mean*pa[idx];
        }
        row_idx += Width;
    }
    // not needed after this
    delete[] pCum;
    delete[] pSquareCum;
    delete[] pInputCum;
    delete[] pGPCum;

    // Cumulative image of a and b
    float *pCuma = NULL, *pCumb = NULL;
    CumImage(pa, &pCuma);
    CumImage(pb, &pCumb);

    // Finally calculate the output image q=ag+b
    float mean_a, mean_b;
    row_idx = Hstart*Width;
    for (i = Hstart; i < Hend; i++)
    {
        // Check the boundary for radius
        if (i < radius) uprow = 0;
        else uprow = i - radius;
        upidx = uprow*(Width + 1);
        if (i + radius >= Height) downrow = Height;
        else downrow = i + radius + 1;
        downidx = downrow*(Width + 1);
        for (j = Wstart; j < Wend; j++)
        {
            // Check the boundary for radius
            if (j < radius) leftcol = 0;
            else leftcol = j - radius;
            if (j + radius >= Width) rightcol = Width;
            else rightcol = j + radius + 1;
            field_size = (downrow - uprow)*(rightcol - leftcol);
            long p1, p2, p3, p4;
            p1 = downidx + rightcol;
            p2 = downidx + leftcol;
            p3 = upidx + rightcol;
            p4 = upidx + leftcol;
            // Field mean
            mean_a = (pCuma[p1] - pCuma[p2] - pCuma[p3] + pCuma[p4]) / field_size;
            // Field mean
            mean_b = (pCumb[p1] - pCumb[p2] - pCumb[p3] + pCumb[p4]) / field_size;
            // New pixel value
            long idx = row_idx + j;
            int value = int(mean_a*pGuidedData[idx] + mean_b);
            CLAMP0255(value);
            pData[idx] = value;
        }
        row_idx += Width;
    }

    delete[] pa;
    delete[] pb;
    delete[] pCuma;
    delete[] pCumb;
    long len = Width*Height;

    // Cululative image and square cululative for guided image G
    UINT64 *pCum = NULL, *pSquareCum = NULL;
    CumImage(pGuidedData, &pCum);
    MultiplyCumImage(pGuidedData, pGuidedData, &pSquareCum);

    // Allocate memory for a and b
    float *pa, *pb;
    pa = new float[len];
    pb = new float[len];
    memset(pa, 0, sizeof(float)*len);
    memset(pb, 0, sizeof(float)*len);

    UINT64 *pInputCum = NULL, *pGPCum = NULL;
    CumImage(pData, &pInputCum);
    MultiplyCumImage(pGuidedData, pData, &pGPCum);

    int field_size;
    UINT64 cum, square_cum;
    long uprow, downrow, upidx, downidx;        // In cumulative image
    long leftcol, rightcol;
    float g_mean, g_var;        // mean and variance of guided image
    long row_idx = 0;
    UINT64 p_cum, gp_cum;
    float p_mean;
    // Calculate a and b
    // Since we're going to calculate cumulative image of a and b, we have to calculate the whole image of a and b.
    for (i = 0; i < Height; i++)
    {
        // Check the boundary for radius
        if (i < radius) uprow = 0;
        else uprow = i - radius;
        upidx = uprow*(Width + 1);
        if (i + radius >= Height) downrow = Height;
        else downrow = i + radius + 1;
        downidx = downrow*(Width + 1);
        for (j = 0; j < Width; j++)
        {
            // Check the boundary for radius
            if (j < radius) leftcol = 0;
            else leftcol = j - radius;
            if (j + radius >= Width) rightcol = Width;
            else rightcol = j + radius + 1;
            field_size = (downrow - uprow)*(rightcol - leftcol);
            long p1, p2, p3, p4;
            p1 = downidx + rightcol;
            p2 = downidx + leftcol;
            p3 = upidx + rightcol;
            p4 = upidx + leftcol;
            // Guided image summary in the field
            cum = pCum[p1] - pCum[p2] - pCum[p3] + pCum[p4];
            // Guided image square summary in the field
            square_cum = pSquareCum[p1] - pSquareCum[p2] - pSquareCum[p3] + pSquareCum[p4];
            // Field mean
            g_mean = (float)(cum) / field_size;
            // Field variance
            g_var = float(square_cum) / field_size - g_mean * g_mean;
            // Summary of input image in the field
            p_cum = pInputCum[p1] - pInputCum[p2] - pInputCum[p3] + pInputCum[p4];
            // Input image field mean
            p_mean = float(p_cum) / field_size;
            // Multiply summary in the field
            gp_cum = pGPCum[p1] - pGPCum[p2] - pGPCum[p3] + pGPCum[p4];
            long idx = row_idx + j;
            pa[idx] = (float(gp_cum) / field_size - g_mean*p_mean) / (g_var + epsilon);
            pb[idx] = p_mean - g_mean*pa[idx];
        }
        row_idx += Width;
    }
    // not needed after this
    delete[] pCum;
    delete[] pSquareCum;
    delete[] pInputCum;
    delete[] pGPCum;

    // Cumulative image of a and b
    float *pCuma = NULL, *pCumb = NULL;
    CumImage(pa, &pCuma);
    CumImage(pb, &pCumb);

    // Finally calculate the output image q=ag+b
    float mean_a, mean_b;
    row_idx = Hstart*Width;
    for (i = Hstart; i < Hend; i++)
    {
        // Check the boundary for radius
        if (i < radius) uprow = 0;
        else uprow = i - radius;
        upidx = uprow*(Width + 1);
        if (i + radius >= Height) downrow = Height;
        else downrow = i + radius + 1;
        downidx = downrow*(Width + 1);
        for (j = Wstart; j < Wend; j++)
        {
            // Check the boundary for radius
            if (j < radius) leftcol = 0;
            else leftcol = j - radius;
            if (j + radius >= Width) rightcol = Width;
            else rightcol = j + radius + 1;
            field_size = (downrow - uprow)*(rightcol - leftcol);
            long p1, p2, p3, p4;
            p1 = downidx + rightcol;
            p2 = downidx + leftcol;
            p3 = upidx + rightcol;
            p4 = upidx + leftcol;
            // Field mean
            mean_a = (pCuma[p1] - pCuma[p2] - pCuma[p3] + pCuma[p4]) / field_size;
            // Field mean
            mean_b = (pCumb[p1] - pCumb[p2] - pCumb[p3] + pCumb[p4]) / field_size;
            // New pixel value
            long idx = row_idx + j;
            int value = int(mean_a*pGuidedData[idx] + mean_b);
            CLAMP0255(value);
            pData[idx] = value;
        }
        row_idx += Width;
    }

    delete[] pa;
    delete[] pb;
    delete[] pCuma;
    delete[] pCumb;

View
Code

View
Code

 导向滤波还有平等种植高效算法,基本思想是经下采样输入图P和导图G,得到比较小之图像P’和G’。用它来计量系数A’和B’。然后经过线性插值的法恢复老大小得到近似的A和B,用来与初大小的指引图来测算输出Q。这样,ak和bk的盘算不是当全尺寸图像上,能节约成千上万运算量,而最终的结果莫给异常充分影响。

 导向滤波还有一样栽高效算法,基本思维是通过下采样输入图P和指引图G,得到比较小的图像P’和G’。用它们来计算系数A’和B’。然后通过线性插值的法子恢复原有大小得到近似之A和B,用来与原来大小的带图来算输出Q。这样,ak和bk的计算不是于全尺寸图像上,能省去成千上万运算量,而最后之结果莫吃大要命影响。

 下面坐富含保边平滑特性的导向滤波为例,来看望效果。如达到同一首所说,当输入图P和带图G相同时,导向滤波呈现保边平滑特性。

 下面为带有保边平滑特性的导向滤波为例,来探效果。如齐一样篇所说,当输入图P和导图G相同时,导向滤波呈现保边平滑特性。

betway体育 25  
betway体育 26

betway体育 27  
betway体育 28

                              
原图                                                                                                
半径3,ε=52

                              
原图                                                                                                
半径3,ε=52

betway体育 29  
betway体育 30

betway体育 31  
betway体育 32

                   
半径3,ε=102                                                
                                          
半径3,ε=202

                   
半径3,ε=102                                                
                                          
半径3,ε=202

betway体育 33
  betway体育 34

betway体育 35
  betway体育 36

                         原图            
                                         
 半径5,ε=202

                         原图            
                                         
 半径5,ε=202

 总体来说,P=G时,导向滤波的保边平滑特性和包含保边功能领域平滑滤波有像样之作用。

 总体来说,P=G时,导向滤波的保边平滑特性和富含保边功能领域平滑滤波有像样的功力。

 

 

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图