首页 > 编程语言 >基于局部直方图相关算法的近似优化和提速。

基于局部直方图相关算法的近似优化和提速。

时间:2022-12-30 15:57:38浏览次数:59  
标签:++ 模糊 算法 提速 直方图 64 Radius

  基于局部直方图的算法有很多很多,我们已经研究这类算法有以下一些:

   1、中值滤波

  2、表面模糊

  3、选择性模糊

  4、中值锐化

  5、图像局部熵

       这类算法有个通病,就是即使选择使用SIMD指令加速,因为其内在的特性,速度还是不能很快,但是又找不到其他合适的构架来优化他,还必须使用直方图技术,比如我们的中值滤波, 我尝试过各种商业软件,其速度都和我博客里提到的那个优化速度差不多,说明大家基本上都是那个套路。你们当确实某个场景需要更快的速度时,我们是否能有其他方法来加速呢,或者使用某个近似的方法来替代呢,经过个人的实践,我觉得还是可以有的。

   一个简单的方法就是减少直方图的数量,常规状态下我们直方图有256个元素,因为基于局部直方图的算法基本都是一些统计类算法,是大面积像素的统计信息,所以最终的结果其实也是个统计结果。那么我们压缩直方图的量级,只要压缩量合理,最后的结果可能差异不是很大。

   我们可以把直方图压缩为128等级、64等级、32等级,更小的等级可能信息损失量过大,当压缩时,对应的直方图统计工作不会减少,可能计算量还会稍微有点增加,如下面的代码所示:

for (int Y = 0; Y < Height; Y++)
{
    if (Y == 0)                                            //    第一行的列直方图,要重头计算
    {
        for (int K = -Radius; K <= Radius; K++)
        {
            unsigned char *LinePS = Src + ColOffset[K + Radius] * Stride;
            for (int X = -Radius; X < Width + Radius; X++)
            {
                ColHist[(X + Radius) * HistAmount + (LinePS[RowOffset[X + Radius]] >> Shift)]++;
            }
        }
    }
    else                                                //    其他行的列直方图,更新就可以了
    {
        unsigned char *LinePS = Src + ColOffset[Y - 1] * Stride;
        for (int X = -Radius; X < Width + Radius; X++)        // 删除移出范围内的那一行的直方图数据
        {
            ColHist[(X + Radius) * HistAmount + (LinePS[RowOffset[X + Radius]] >> Shift)]--;
        }

        LinePS = Src + ColOffset[Y + Radius + Radius] * Stride;
        for (int X = -Radius; X < Width + Radius; X++)        // 增加进入范围内的那一行的直方图数据
        {
            ColHist[(X + Radius) * HistAmount + (LinePS[RowOffset[X + Radius]] >> Shift)]++;
        }
    }
  .........
}

  很明显,每个像素点都有右移Shift的计算,这个计算是凭空增加的,幸好,移位的计算量很小。 

       这个直方图更新的耗时的轻微增加,换来的是后续,累计直方图统计的数据量的集聚变小,以及计算过程的集聚下降,如下代码所示:

for (int X = 0; X < Width; X++)
{
    if (X == 0)
    {
        for (int K = -Radius; K <= Radius; K++)            //    行第一个像素,需要重新计算    
            HistgramAddShort_PureC(ColHist + (K + Radius) * HistAmount, Hist, Shift);
    }
    else
    {
        HistgramSubAddShort_PureC(ColHist + (RowOffset[X - 1] + Radius) * HistAmount, ColHist + (RowOffset[X + Radius + Radius] + Radius) * HistAmount, Hist, Shift);  //    行内其他像素,依次删除和增加就可以了
    }
    IM_Calc_SB_PureC(Hist, Intensity + HistAmount - 1 - (LinePS[X] >> Shift), LinePD + X, Shift);
}

  HistgramAddShort_PureC和HistgramSubAddShort_PureC里的计算量随着移位量的增加而变少,IM_Calc_SB_PureC里的计算量也同步变少。

    我们用一副1920*1080的灰度图做测试,以表明模糊为例,当不压缩实现时,平均耗时276ms,压缩到128等级时,用时160ms,64等级时,用时95ms,32等级时,用时51ms。

      

                      原始图像                           256级表面模糊                              128级表面模糊

      

          64级表面模糊                        32级表面模糊                      16级表面模糊

  可见,对于表面模糊,甚至16级的效果都是可以接受的。 

  对于选择性模糊、局部熵等算法,也是同样的道理。

       上面的几个算法,其结果值都是某个权重累加值除以权重,其中间结果其实是个浮点数,因此,等级量化后对结果不是影响很大。

        对于中值模糊,情况又有所不同,因为中值是将直方图分为细分直方图和粗分直方图,而最终得到的结果是一个整形值,这个时候如果我们降低直方图的色阶精度,得到的结果可能会存在一定的瑕疵,特别是用在比较平滑的区域内,像素信息比较少,这个时候可以看到有较为明显的过渡色阶。比如我们把色阶调整为64阶,那么细分则有64个元素,粗分有8个元素,这个时候算法的速度大概能提高一倍,不过效果会有一定差异,实际使用时这个差异是否在容许的范围,就要看具体的应用了。

  比如1920*1080的灰度图,正常C语言满色阶中值模糊大概要200ms,如果调整为64色阶,大概在100ms实现。对于普通信息比较丰满的图,他们的效果差异也不大,如下图所示:

       

            原图                          256色阶中值                        64色阶中值

 如果图像含有大面的看似纯色的部分,则两者就有一定的区别了。

       

          原图                          256色阶中值                        64色阶中值

  明显看到64色阶的中值里有很多halo现象。

  所以具体的如何优化以及是否值得优化还要看具体的算法需求和应用场景。 

     有兴趣的朋友可以从:https://files.cnblogs.com/files/Imageshop/SSE_Optimization_Demo.rar?t=1660121429 下载。

       如果想时刻关注本人的最新文章,也可关注公众号:

                              

标签:++,模糊,算法,提速,直方图,64,Radius
From: https://www.cnblogs.com/Imageshop/p/17014961.html

相关文章

  • 《程序与算法》课程设计(论文)指导书[2022-12-30]
    《程序与算法》课程设计(论文)指导书[2022-12-30]《程序与算法》课程设计(论文)指导书一、设计目的使学生具备理论联系实际的程序设计思想,掌握数据与结构中线性表和二叉树和......
  • 云上提速哪家强?华为云CDN加速成首选!​
    伴随着信息化时代的到来,企业为了满足日益增长的数据流量需求,开始将大量数据存储在云端进行处理和分析以提高数据处理能力和效率,这就要求数据中心能够提供更快速度,更高稳定性......
  • VTK_Learning_图像统计_灰度直方图计算_彩色直方图计算
    1.灰度图像直方图直方图统计是图像处理中的一个非常重要的操作。VTK中实现直方图统计功能的filter是vtkImageAccumulate。其将每个组分的数值范围划分为离散的间隔,然后统计......
  • 每日算法之和为S的连续正数序列
    JZ74和为S的连续正数序列题目小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续......
  • 手撕fft算法--fft原理和源码解析
    一前言 在音频信号处理中,fft变换是一个无法绕过过去的存在。借着一次算法出来的机会,把fft熟悉一下不为过啊。 二问题 这里,其实是由一个问题驱动的,那......
  • AI算法玩转象棋
    大家好我是毕加锁(锁!)今天教大家python象棋AI算法一,棋子的着法com.bylaw={}(1)车:com.bylaw.c=function(x,y,map,my){vard=[];//左侧检索若存在棋子且颜色不同则......
  • 泛型算法
    1、迭代器令算法不依赖于容器,但算法依赖于元素类型的操作。2、算法可能改变容器中保存元素的值,也可能在容器内移动元素,但永远不会直接添加或删除元素。3、那些只接受一个......
  • VBA 47 程序优化与提速的方法
    一、减少对象的调用二、减少计算次数三、禁止闪屏四、增加变量的声明类型五、减少工作表函数的使用六、减少VBA函数的使用七、用静态数组替换动态八、填充前先清空......
  • 代码随想录算法训练营Day2|977.有序数组的平方,209.长度最小的子数组,59.螺旋数组
    977.有序数组的平方题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/文章链接:https://programmercarl.com/0209.长度最小的子数组.html视频链接:https......
  • 代码随想录算法训练营第二天LeetCode977, 209, 59
    代码随想录算法训练营第二天|LeetCode977,209,59LeetCode977有序数组的平方题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array///使用stl的排序,毫无算......