我正在尝试实施此图像缩小算法的逐行版本:http://intel.ly/1avllXm,应用于RGBA 8位图像。
为简化起见,请考虑调整单行的大小,w_src - > w_dst。然后,每个像素可以将其值贡献给具有权重1.0的单个输出累加器,或者贡献给具有权重α和(1.0f-α)的两个连续输出像素。在C /伪代码中:
float acc[w_dst] = malloc(w_dst * 4);
x_dst = 0
for x = 0 .. w_src:
if x is a pivot column:
acc[x_dst] += (w_src[x] * alpha);
x_dst++;
acc[x_dst] += (w_src[x] * (1.0f - alpha);
else
acc[x_dst] += w_src[x];
最后,将每个累加器通道除以对其有贡献的源像素数(浮点值):
uint8_t dst = malloc(w_dst);
for x_dst = 0 .. w_dst
dst[x_dst] = (uint8_t)round(acc[x_dst] / area);
我的参考纯C实现正常工作。但是,我想知道是否有办法加速使用NEON操作(请记住每个像素是8位RGBA)。谢谢!
答案 0 :(得分:1)
在我的第二个想法中,垂直缩小尺寸非常SIMDable,因为相同的算法可以应用于水平相邻的像素。
所以这就是我的建议:
请注意,按区域划分应在 q17 中以(1 /区域)的LONG乘法进行。
为什么选择q17?如果你执行q15 * q17,结果是在q32中,其中两个32位寄存器包含数据。并且您不需要通过位操作进行任何“类型转换”,因为上层寄存器已经具有目标8位int值。这就是fp算术的美妙。
也许我会在不久的将来编写完全优化的版本,完全在装配中。
答案 1 :(得分:0)
不幸的是,NEON不太适合这种工作。 如果使用固定的源和目标分辨率进行图像大小调整,则可以使用动态矢量进行NEONize,但是相邻像素的可变数量的求和不仅仅是SIMDable。
我建议用固定点1替换浮点运算。仅这一点将有很大帮助。
此外,分工花费的时间非常长。它确实会损害性能,尤其是在循环内部完成时。你应该用乘法替换它:
uint8_t dst = malloc(w_dst);
float area_ret = 1.0f/area;
for x_dst = 0 .. w_dst
dst[x_dst] = (uint8_t)round(acc[x_dst] * area_ret);