【问题标题】:Resize 8-bit image by 4 with ARM NEON使用 ARM NEON 将 8 位图像大小调整为 4
【发布时间】:2014-10-03 18:06:58
【问题描述】:

我想使用 ARM Neon 将 8 位灰度图像的大小从 1280x960 调整为 4 倍至 320x240。

例如,我已经将 2 倍的大小从 640x480 调整为 320x240:

void divideimageby2(uint8_t * src, uint8_t * dest) {
    //src is 640 x 480
    //dst is 320 x 240
    int h;
    for (h = 0; h < 240; h++)
        resizeline2(src + 640 * (h * 2 + 0), src + 640 * (h * 2 + 1), dt + 320 * h);
}

void resizeline2(uint8_t * __restrict src1, uint8_t * __restrict src2, uint8_t * __restrict dest) {
    int w;
    for (w = 0; w < 640; w += 16) {
        uint16x8_t a = vpaddlq_u8(vld1q_u8(src1));
        uint16x8_t b = vpaddlq_u8(vld1q_u8(src2));
        uint16x8_t ab = vaddq_u16(a, b);
        vst1_u8(dest, vshrn_n_u16(ab, 2));
        src1 += 16;
        src2 += 16;
        dest += 8;
    }
}   

如果我想做类似的事情,我可以在 resizeline4 中使用什么样的 Neon 指令来聚合 4 行?

void divideimageby4(uint8_t * src, uint8_t * dest) {
    //src is 1280 x 960
    //dst is 320 x 240
    int h;
    for (h = 0; h < 240; h++)
        resize_line2(src + 640 * (h * 4 + 0), src + 640 * (h * 4 + 1), src + 640 * (h * 4 + 2), src + 640 * (h * 4 + 3), dt + 320 * h);
}

void resizeline4(uint8_t * __restrict src1, uint8_t * __restrict src2, uint8_t * __restrict src3, uint8_t * __restrict src4, uint8_t * __restrict dest) {
    int w;
    for (w = 0; w < 1280; w += 16) {
        //What to put here?
        src1 += 16;
        src2 += 16;
        src3 += 16;
        src4 += 16;
        dest += 4;
    }
}   

【问题讨论】:

  • 你想怎么做?你正在减少信息。见:What is the best image reduction algorithm;真正的答案是没有,因为reducing information 时有各种标准。你可以把它们结合起来。例如,第一次通过整数平均值,然后是第二次通过双三次将提供几乎与完整双三次一样好的质量,但会快得多。
  • 这里的关键目标是速度。我希望它几乎和 Neon memcpy 一样快。
  • 然后只消屏幕,这很快 :) 在花时间手动调整 NEON 之前,您至少应该评估不同的缩放算法。我的观点是,通过使用两个滤镜,您可以获得接近同等速度的很多更好的图像质量。跳过像素/行会更快并提供类似的质量;您在主图像上受到带宽限制。 NEON 将使 CPU 时间不占优势。无论如何,我祝你好运。

标签: image image-processing arm simd neon


【解决方案1】:

您应该将 vpaddl 与 vpadal 结合使用。

在 q 个寄存器 line1a, line1b ..... line4b 中加载 32*4 矩阵

vpaddl.u8 line1a, line1a

vpaddl.u8 line1b, line1b

vpadal.u8 line1a, line2a

vpadal.u8 line1b, line2b

.

.

vpadal.u8 line1b, line4b

vpadd.u16 d0, line1alow, line1ahigh

vpadd.u16 d1, line1blow, line1bhigh

vrshrn.u16 d0, q0, #4

vst1.8 {d0},[pDst]!

【讨论】:

  • 这看起来是正确的,如果减少是像他的示例代码那样使用整数平均值。但大多数人最终会发现它有点缺乏。
  • 感谢您的回答。我对你的建议有点困惑。你能编辑答案并写一些更接近一些工作代码的东西吗?
猜你喜欢
  • 2013-07-22
  • 1970-01-01
  • 2013-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-06
  • 1970-01-01
相关资源
最近更新 更多