SSE图像算法优化系列十四:局部均方差及局部平方差算法的优化。
2018-01-21 09:28
756 查看
关于局部均方差有着较为广泛的应用,在我博客的基于局部均方差相关信息的图像去噪及其在实时磨皮美容算法中的应用及使用局部标准差实现图像的局部对比度增强算法中都有谈及,即可以用于去噪也可以用来增强图像,但是直接计算其计算量较大,一般都是通过某种方式进行优化,典型的即通过积分图来处理:
展开:
上式中两个累积一个是平方积分图,一个是累加积分图,累加积分图在SSE图像算法优化系列六:OpenCv关于灰度积分图的SSE代码学习和改进中曾经谈及,而平方积分图由于数据范围的问题,用int类型的数据来处理的话,只能处理很小很小的图,因此需要使用浮点类型,经过测试,如果使用SSE指令,由于SSE的浮点计算精度实在是低,比FPU的还要低,积分图这种累加性质的算法计算出来的结果会存在很大的误差,特别是在图像比较宽而半径比较小时,会看到明显的错误结果,半径稍微大点时,也会有明显竖条纹出现(小图像好像不会出现什么大问题),如下图所示:
小半径 大半径 合理的结果
因此,如果使用积分图,考虑各种类型的图像,最好是使用double类型保存中间的积分图数据,这是个很可观的内存消耗,也会导致时间的增加。
在SSE图像算法优化系列十三:超高速BoxBlur算法的实现和优化(Opencv的速度的五倍)一文中,我们描述了Boxblur的优化,优化后的速度即比传统的快,也占用很少的内存,我们观察下BoxBlur的累加式:
以及像素平方的累加式
,他们除理数据不一样外,其他并无本质的区别的,因此
也是可以使用类似于Boxblur的方式进行优化和处理的,这样上述算法就变为了2个这种累积算法的同步进行算法,并且同步进行能够减少很多重复数据的加载和处理,比单独进行两个过程其实是要更节省时间的。
那么需要注意的时,由于
是对像素的平方进行累加,还考虑使用int类型来保存列累加值以及水平方向的累加值,那么理论上讲最大的安全半径可以达到90(不会产生溢出),计算如下:
Sqrt(Int.MaxValue / (Byte.MaxValue * Byte.MaxValue)) / 2 - 1 = Sqrt(2147483647 / 65025) / 2 - 1 = 90
对于局部均方差相关的算法来说,90的半径已经完全满足了实际的需求。
使用SSE优化,实际测试表面,对于3000*2000的灰度图求取均方差大约需要13ms(包括了最后的求sqrt过程的时间,是相当快的)。
另外,局部均方差是像素领域的值减去该领域的平均值的平方累积和,这样的结果在强边缘处均方差会特别强烈,用于某法会出现边缘效应,如果我们对这个稍微改造下,使用像素领域的值减去领域的模糊值,在求累加值,会不会有什么结果呢,此时假如平均值用y表示,则需要计算
这个值,同样的y就是上述的Boxblur的值,计算这个的
优化方式和Boxblur又是相同的,一环套一环,当然这个时候的速度会比上面的慢一点,因此公共的计算不能重复利用了,大概需要17ms。
更广泛的讲,还可以用上述方式计算任意两幅图像的局部平方差,速度和效率同样很高。比如计算原图和高斯模糊后的图的局部平法差,会得到什么结果呢?
使用这种方式优化后,我以前提的磨皮算法针对1080P的图可以做到约20ms每帧,而且效果非常好,完全可以使用到视频处理中。
参考效果下载:https://files.cnblogs.com/files/Imageshop/SSE_Optimization_Demo.rar,见其中的Boxblur - >LeeAddtiveNoiseFilter 以及Enhance ->MakeUp和ImageInfo->Stdfilter等。
展开:
上式中两个累积一个是平方积分图,一个是累加积分图,累加积分图在SSE图像算法优化系列六:OpenCv关于灰度积分图的SSE代码学习和改进中曾经谈及,而平方积分图由于数据范围的问题,用int类型的数据来处理的话,只能处理很小很小的图,因此需要使用浮点类型,经过测试,如果使用SSE指令,由于SSE的浮点计算精度实在是低,比FPU的还要低,积分图这种累加性质的算法计算出来的结果会存在很大的误差,特别是在图像比较宽而半径比较小时,会看到明显的错误结果,半径稍微大点时,也会有明显竖条纹出现(小图像好像不会出现什么大问题),如下图所示:
小半径 大半径 合理的结果
因此,如果使用积分图,考虑各种类型的图像,最好是使用double类型保存中间的积分图数据,这是个很可观的内存消耗,也会导致时间的增加。
在SSE图像算法优化系列十三:超高速BoxBlur算法的实现和优化(Opencv的速度的五倍)一文中,我们描述了Boxblur的优化,优化后的速度即比传统的快,也占用很少的内存,我们观察下BoxBlur的累加式:
以及像素平方的累加式
,他们除理数据不一样外,其他并无本质的区别的,因此
也是可以使用类似于Boxblur的方式进行优化和处理的,这样上述算法就变为了2个这种累积算法的同步进行算法,并且同步进行能够减少很多重复数据的加载和处理,比单独进行两个过程其实是要更节省时间的。
那么需要注意的时,由于
是对像素的平方进行累加,还考虑使用int类型来保存列累加值以及水平方向的累加值,那么理论上讲最大的安全半径可以达到90(不会产生溢出),计算如下:
Sqrt(Int.MaxValue / (Byte.MaxValue * Byte.MaxValue)) / 2 - 1 = Sqrt(2147483647 / 65025) / 2 - 1 = 90
对于局部均方差相关的算法来说,90的半径已经完全满足了实际的需求。
使用SSE优化,实际测试表面,对于3000*2000的灰度图求取均方差大约需要13ms(包括了最后的求sqrt过程的时间,是相当快的)。
另外,局部均方差是像素领域的值减去该领域的平均值的平方累积和,这样的结果在强边缘处均方差会特别强烈,用于某法会出现边缘效应,如果我们对这个稍微改造下,使用像素领域的值减去领域的模糊值,在求累加值,会不会有什么结果呢,此时假如平均值用y表示,则需要计算
这个值,同样的y就是上述的Boxblur的值,计算这个的
优化方式和Boxblur又是相同的,一环套一环,当然这个时候的速度会比上面的慢一点,因此公共的计算不能重复利用了,大概需要17ms。
更广泛的讲,还可以用上述方式计算任意两幅图像的局部平方差,速度和效率同样很高。比如计算原图和高斯模糊后的图的局部平法差,会得到什么结果呢?
使用这种方式优化后,我以前提的磨皮算法针对1080P的图可以做到约20ms每帧,而且效果非常好,完全可以使用到视频处理中。
参考效果下载:https://files.cnblogs.com/files/Imageshop/SSE_Optimization_Demo.rar,见其中的Boxblur - >LeeAddtiveNoiseFilter 以及Enhance ->MakeUp和ImageInfo->Stdfilter等。
相关文章推荐
- SSE图像算法优化系列十九:一种局部Gamma校正对比度增强算法及其SSE优化。
- SSE图像算法优化系列十:简单的一个肤色检测算法的SSE优化。
- SSE图像算法优化系列一:一段BGR2Y的SIMD代码解析。
- SSE图像算法优化系列四:图像转置的SSE优化(支持8位、24位、32位),提速4-6倍
- SSE图像算法优化系列二:高斯模糊算法的全面优化过程分享(二)。
- SSE图像算法优化系列五:超高速指数模糊算法的实现和优化(10000*10000在100ms左右实现)。
- SSE图像算法优化系列十二:多尺度的图像细节提升。
- SSE图像算法优化系列十三:超高速BoxBlur算法的实现和优化(Opencv的速度的五倍)
- SSE图像算法优化系列六:OpenCv关于灰度积分图的SSE代码学习和改进。
- SSE图像算法优化系列二十四: 基于形态学的图像后期抗锯齿算法--MLAA优化研究。
- SSE图像算法优化系列八:自然饱和度(Vibrance)算法的模拟实现及其SSE优化(附源码,可作为SSE图像入门,Vibrance算法也可用于简单的肤色调整)。
- SSE图像算法优化系列二:高斯模糊算法的全面优化过程分享(一)。
- SSE图像算法优化系列二十一:基于DCT变换图像去噪算法的进一步优化(100W像素30ms)。
- SSE图像算法优化系列十一:使用FFT变换实现图像卷积。
- SSE图像算法优化系列十六:经典USM锐化中的分支判断语句SSE实现的几种方法尝试。
- SSE图像算法优化系列九:灵活运用SIMD指令16倍提升Sobel边缘检测的速度(4000*3000的24位图像时间由480ms降低到30ms)。
- SSE图像算法优化系列十一:使用FFT变换实现图像卷积。
- SSE图像算法优化系列十:简单的一个肤色检测算法的SSE优化。
- SSE图像算法优化系列二十三: 基于value-and-criterion structure 系列滤波器(如Kuwahara,MLV,MCV滤波器)的优化。
- SSE图像算法优化系列三:超高速导向滤波实现过程纪要(欢迎挑战)