使用 arm neon 进行 Rgb 到灰度转换
Posted
技术标签:
【中文标题】使用 arm neon 进行 Rgb 到灰度转换【英文标题】:Rgb to grayscale conversion with arm neon 【发布时间】:2011-12-14 09:18:33 【问题描述】:我正在尝试有效地从 rgb 转换为灰度,因此我从 here 获得了一个函数,它解释了如何从 rgba 转换为灰度。现在我正在尝试做同样的事情,但只使用 rgb。我改变了一些东西,但似乎效果不佳。我不知道为什么,有人看到我的错误吗?
void neon_asm_convert(uint8_t * __restrict dest, uint8_t * __restrict src, int numPixels)
__asm__ volatile(
"lsr %2, %2, #3 \n"
"# build the three constants: \n"
"mov r4, #28 \n" // Blue channel multiplier
"mov r5, #151 \n" // Green channel multiplier
"mov r6, #77 \n" // Red channel multiplier
"vdup.8 d4, r4 \n"
"vdup.8 d5, r5 \n"
"vdup.8 d6, r6 \n"
"0: \n"
"# load 8 pixels: \n" //RGBR
"vld4.8 d0-d3, [%1]! \n"
"# do the weight average: \n"
"vmull.u8 q7, d0, d4 \n"
"vmlal.u8 q7, d1, d5 \n"
"vmlal.u8 q7, d2, d6 \n"
"# shift and store: \n"
"vshrn.u16 d7, q7, #8 \n" // Divide q3 by 256 and store in the d7
"vst1.8 d7, [%0]! \n"
"subs %2, %2, #1 \n" // Decrement iteration count
"# load 8 pixels: \n"
"vld4.8 d8-d11, [%1]! \n" //Other GBRG
"# do the weight average: \n"
"vmull.u8 q7, d3, d4 \n"
"vmlal.u8 q7, d8, d5 \n"
"vmlal.u8 q7, d9, d6 \n"
"# shift and store: \n"
"vshrn.u16 d7, q7, #8 \n" // Divide q3 by 256 and store in the d7
"vst1.8 d7, [%0]! \n"
"subs %2, %2, #1 \n" // Decrement iteration count
"# load 8 pixels: \n"
"vld4.8 d0-d3, [%1]! \n"
"# do the weight average: \n"
"vmull.u8 q7, d10, d4 \n"
"vmlal.u8 q7, d11, d5 \n"
"vmlal.u8 q7, d0, d6 \n"
"# shift and store: \n"
"vshrn.u16 d7, q7, #8 \n" // Divide q3 by 256 and store in the d7
"vst1.8 d7, [%0]! \n"
"subs %2, %2, #1 \n" // Decrement iteration count
"# do the weight average: \n"
"vmull.u8 q7, d1, d4 \n"
"vmlal.u8 q7, d2, d5 \n"
"vmlal.u8 q7, d3, d6 \n"
"# shift and store: \n"
"vshrn.u16 d7, q7, #8 \n" // Divide q3 by 256 and store in the d7
"vst1.8 d7, [%0]! \n"
"subs %2, %2, #1 \n" // Decrement iteration count
"bne 0b \n" // Repeat unil iteration count is not zero
:
: "r"(dest), "r"(src), "r"(numPixels)
: "r4", "r5", "r6"
);
【问题讨论】:
图片转换不好。 截图什么的? 【参考方案1】:你应该使用"vld3.8 d0-d2, [%1]! \n"
另见http://hilbert-space.de/?p=22
【讨论】:
欢迎来到 Stack Overflow!虽然这在理论上可以回答问题,it would be preferable 在此处包含答案的基本部分,并提供链接以供参考。【参考方案2】:您加载四个值 (RGBA) 而不是 3 个 (RGB)。
你的图片中有RGB RGB RGB
,但你在连续的步骤中加载了RGBR GBRG B...
等。
"vld4.8 d0-d3, [%1]! \n"
你应该这样做
"vld3.8 d0-d2, [%1]! \n"
请注意,我不知道我的asm
是否正确,但这是错误的。
将像素移回内存时也要检查相同的错误
【讨论】:
我已经考虑到,我从源中得到了四倍的向量,所以我可以转换成倍数。我每次都会得到 RGBR / GBRG /BRGB 的转换 你正在做的是加载RGBR,将RGB转换为灰度并忽略第二个R,然后加载GBRB,将GBR处理为RGB(错误!),忽略最后一个B,然后再次......所以,您忽略了一些像素,并且每一步都加载了错误的通道。【参考方案3】:瓦西尔是对的。使用 VLD3 加载 24bit 像素。
4 VSTx 也有 3 个 VLDx 其实你的代码很奇怪...
您不必复制代码。这解释起来很复杂,但你对 NEON 没有兴趣重复你的代码 4 次
void neon_asm_convert(uint8_t * __restrict dest, uint8_t * __restrict src, int numPixels)
__asm__ volatile(
"# build the three constants: \n"
"mov r4, #28 \n" // Blue channel multiplier
"mov r5, #151 \n" // Green channel multiplier
"mov r6, #77 \n" // Red channel multiplier
"vdup.8 d4, r4 \n"
"vdup.8 d5, r5 \n"
"vdup.8 d6, r6 \n"
"0: \n"
"# load 8 pixels: \n" //RGBR
"vld3.8 d0-d2, [%1]! \n"
"# do the weight average: \n"
"vmull.u8 q7, d0, d4 \n"
"vmlal.u8 q7, d1, d5 \n"
"vmlal.u8 q7, d2, d6 \n"
"# shift and store: \n"
"vshrn.u16 d7, q7, #8 \n" // Divide q3 by 256 and store in the d7
"vst1.8 d7, [%0]! \n"
"subs %2, %2, #1 \n" // Decrement iteration count
"bne 0b \n" // Repeat unil iteration count is not zero
:
: "r"(dest), "r"(src), "r"(numPixels)
: "r4", "r5", "r6"
);
应该可以。
【讨论】:
看起来不错,但它给了我一个内存访问错误,而且我认为你忘记了函数开头的这一行:“lsr %2, %2, #3 \n” 是的,这是正确的,或者将 subs %2, %2, #1 替换为 subs %2, %2, #8以上是关于使用 arm neon 进行 Rgb 到灰度转换的主要内容,如果未能解决你的问题,请参考以下文章