在2年前,我写过SSE图像算法优化系列十八:三次卷积插值的进一步SSE优化 一文,在那里使用了SSE对三次卷积插值进行了SSE优化,原本以为那个速度已经比较极限了,最新遇到一个项目需要更高速的效果,自己又对这个算法进行了下构思,发现原来根本不是那回事,速度极限离天花板还早着呢。
早期的优化中,仅仅是在每个像素的放大内部使用SIMD指令进行处理,而没有考虑每个相邻像素或者相邻行像素之间的联系和关系,因此呢计算量依旧是很大。 再来仔细看看三次立方插值,他需要涉及到像素是4*4的领域,共有16个权重,但是16个权重可以看成是水平和垂直分离的,因此可以先计算行方向的累计值,然后再计算列方向的累加和,我们发现,在放大和缩小时,这4行的取样点一般来说总会有部分是重叠的,甚至是完全重叠的,如果是完全重叠,那么水平方向的累加和是根本无需进行计算的,部分重叠时,也可以只计算重叠的部分,这个时候,整体的计算量将大大的减少。这也是行和列分离计算所带来的好处。4*4的取样这个特性,决定他在某方面非常合适使用SIMD指令进行优化。对于灰度图,由于其一个采样点水平方向只涉及到4个像素(4个字节),不适合在取样时就计算其水平方向的累加值(是指不适合用SIMD指令,如果纯C实现反而就要在取样时计算了),我们先收集取样数据,然后再整体计算累加值时使用SIMD指令优化,而对于24位或者是32位图,由于取样4个像素占用了12个字节和16个字节,此时就可以直接在取样时进行计算,避免了收集取样数据的耗时,使得彩色模式图像比灰度也仅仅多了一倍时间,而不是3倍或4倍。
就是这么一个简单的思路,能极大的提高算法的速度,而对于另外一个经典的Lanczos4插值算法,他涉及到的领域范围是8*8,同样可以使用上述的方式进行优化。
测试一幅720P的彩色图放大到1080P,三次立方插值单次的执行时间越月8.5ms, Lanczos4的耗时17.7ms左右,如果是灰度图像,则三次立方耗时约6ms,Lanczos4用时7.5ms,差异很小。
如果4K彩色图缩小到1080P图,三次立方插值单次的执行时间越15ms, Lanczos4的耗时31ms左右,如果是灰度图像,则三次立方耗时约10ms,Lanczos4用时也是10ms左右,也差异很小。
和Opencv比较发现,CV你如果调用100次某个图的放大,他是多线程的执行的,CPU使用率到了100%,而且这个时候他的速度也就是和我的差不多。
另外,三次立方插值其实有个参数可以调节,他控制了结果是锐化还是模糊一些,如下图所示:
联系客服