1

我正在尝试实现此图像缩小算法的逐行版本:http: //intel.ly/1avllXm,应用于 RGBA 8 位图像。

为了简化,考虑调整单行的大小,w_src -> w_dst。然后每个像素可以将其值贡献给权重为 1.0 的单个输出累加器,或者贡献给权重为 alpha 和 (1.0f - alpha) 的两个连续输出像素。在 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)。谢谢!

4

2 回答 2

1

我的第二个想法是,垂直缩小尺寸非常适合 SIMDable,因为相同的算法可以应用于水平相邻的像素。

所以这是我的建议:

  • 使用 q15 无符号 fp 算法使用 NEON 垂直调整大小。临时结果存储在 32 位/元素中。
  • 使用 ARM 使用 q15 unsigned fp 算法水平调整大小,除以 area/typecast/pack 并将最终结果存储在 RGBA 中。

请注意,按面积除应在q17中与 (1/area) 进行 LONG 乘法运算。

为什么是 q17?如果执行 q15*q17,则结果在 q32 中,其中两个 32 位寄存器包含数据。而且您不需要执行任何“按位操作进行类型转换”,因为高位寄存器已经具有目标 8 位 int 值。这就是 fp 算术的美妙之处。

也许我会在不久的将来编写完全优化的版本,完全在汇编中。

于 2013-06-21T03:13:00.487 回答
0

不幸的是,NEON 不太适合这种工作。如果它是使用固定源和目标分辨率调整图像大小,则可以使用动态向量进行 NEONize,但对可变数量的相邻像素求和并不是简单的 SIMDable。

我建议用定点一替换浮点算术。仅此一项就会有很大帮助。

此外,除法需要非常长的时间。它确实会损害性能,尤其是在循环内完成时。您应该用以下乘法替换它:

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);
于 2013-06-20T09:14:18.820 回答