使用 ARM NEON 将 8 位图像大小调整为 6x6
Posted
技术标签:
【中文标题】使用 ARM NEON 将 8 位图像大小调整为 6x6【英文标题】:Resize 8-bit image by 6x6 with ARM NEON 【发布时间】:2016-02-24 08:54:39 【问题描述】:我正在尝试将灰色 8 位图像的大小调整(缩小)36=6x6 倍。我想使用 ARM NEON 指令。我的代码如下所示:
//I deinterlace 3 8-pixel on the first line (named line0) and
//I add them. So I have resized horizontally by a factor 3
//Line 0
vld3.u8 d0, d1, d2, [line0]!
vaddl.u8 q3, d0, d1
vaddw.u8 q3, q3, d2
vld3.u8 d3, d4, d5, [line0]!
vaddl.u8 q4, d3, d4
vaddw.u8 q4, q4, d5
//I do this for six successive lines
//So virtually, I have reduced by a factor 3x6=18
//Line 1
vld3.u8 d0, d1, d2, [line1]!
vaddw.u8 q3, q3, d0
vaddw.u8 q3, q3, d1
vaddw.u8 q3, q3, d2
vld3.u8 d3, d4, d5, [line1]!
vaddw.u8 q4, q4, d3
vaddw.u8 q4, q4, d4
vaddw.u8 q4, q4, d5
.....
//Line 5
vld3.u8 d0, d1, d2, [line5]!
vaddw.u8 q3, q3, d0
vaddw.u8 q3, q3, d1
vaddw.u8 q3, q3, d2
vld3.u8 d3, d4, d5, [line5]!
vaddw.u8 q4, q4, d3
vaddw.u8 q4, q4, d4
vaddw.u8 q4, q4, d5
//At this point, I want to add two adjacent pixels
//to give my last factor by 2.
//I also want to merge two successive q registers
//In other words, I want to do the following:
/*
q5[0] = q3[0] + q3[1]
q5[1] = q3[2] + q3[3]
q5[2] = q3[4] + q3[5]
q5[3] = q3[6] + q3[7]
q5[4] = q4[0] + q4[1]
q5[5] = q4[2] + q4[3]
q5[6] = q4[4] + q3[5]
q5[7] = q4[6] + q3[7]
*/
//This code doesn't seem to work as expected...
vpaddl.u16 q3, q3
vpaddl.u16 q4, q4
vext.u16 q5, q4, q3, #4
//Now, I want to divide by 36.
//In other words, I want to do the following:
/*
d0 = q5 / 36
*/
//The best I can do is to divide by 32
vshrn.i16 d0, q3, #5
看来我有两个问题:如何将q个寄存器的相邻值相加?如何除以 36?
【问题讨论】:
【参考方案1】:水平加法通常像(q0 中的 8 个 uint16 值)
vadd.u16 d2, d0, d1 ; normally add high 4 lanes to low 4 lanes
vpadd.u16 d0, d2, d2 ; d0[0] = d2[0] + d2[1], d0[1] = d2[2] + d2[3], ...
vpadd.u16 d1, d0, d0 ; d1[0] = d0[0] + d0[1] = sum of the 8 values
针对具体情况
/*
q5[0] = q3[0] + q3[1]
q5[1] = q3[2] + q3[3]
q5[2] = q3[4] + q3[5]
q5[3] = q3[6] + q3[7]
q5[4] = q4[0] + q4[1]
q5[5] = q4[2] + q4[3]
q5[6] = q4[4] + q4[5]
q5[7] = q4[6] + q4[7]
*/
解决办法是
vpadd.u16 d10, d6, d7
vpadd.u16 d11, d8, d9
对于除法,发现类似 1/36 ~= 7/256 (0.0278 ~= 0.273)
【讨论】:
【参考方案2】:解决方案是使用 vuzp(非常酷!),实际上是 7/256:
vuzp.16 q3, q4
vadd.u16 q5, q3, q4
mov tmp, #7
vdup.u16 q6, tmp
vmulq.i16 q5, q5, q6
vshrn.i16 d0, q5, #8
【讨论】:
以上是关于使用 ARM NEON 将 8 位图像大小调整为 6x6的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 ARM NEON 内在函数将 u8 掩码转换为 u32 掩码?