我有一个任务,要为膨胀和腐 eclipse 函数编写一个内联的x86汇编代码。我的问题是,我们没有得到一个单独的数组,并且不能触及程序的非asm部分。所以我需要找到一种方法来修改原始图像,而不用将其复制到其他地方。但如果我这样做了,该过程受到损害,因为后面的像素考虑它们相邻像素的改变值而不是它们的原始值,并且整个图像变为黑色或白色。
下面是其中的一个函数,我把它放在这里是为了让我提到的限制很清楚,而不是因为我希望有人为我写它。我不能在asm块中初始化一个单独的数组,其余的代码也没有给我一个数组。
void dilation(int image_size, int filter_size, short* image_org) {
__asm {
MOV EBX, image_org
//I can only write code in here
}
}
编辑:我想我应该把每个像素的新值推到堆栈中,只有在遍历完整个图像后才能把它们放回数组中。
2条答案
按热度按时间wnvonmuf1#
通过保留要修改的几个像素,您可以轻松地对3x1膨胀执行此操作。
假设三个连续的像素值A、B、C。假设您已经修改了A,并且正忙碌对B进行扩张(即,您将用max(A,B,C)替换B)。您可以使用以下操作序列
在一个循环中从左到右。(我把行中第一个和最后一个像素的处理作为exrecise留给您。)
你可以将其推广到1x3膨胀,以及通过连续应用3x1和1x3进行3x3膨胀。侵 eclipse 也是如此。
对于(2n+1)x1,重复n次。
这也适用于灰度图像。你也可以适应压缩的二进制格式。
kpbpu0082#
如果输入图像是单色的,则可以使用额外的几个值来标记具有额外含义的像素,然后处理这些像素,然后在退出之前清除标记。
如果像素数据是16位,如果你只使用1位单色,其余的15位可以很容易地保存所有的值,如“要删除”,“要绘制”。这将只是对像素位和值2或4的或运算。
否则,您必须在相邻像素需要之前更改像素值,这会给算法增加偏差。
如果允许AVX矢量(在32位环境中,只有一半数量的寄存器可用(参见Peter Cordes的以下注解)),并且像素是全色的,则可以存储16个像素(每个16位)作为单个AVX寄存器上4x 4大小的瓦片。如果AVX指令集允许使用16个寄存器,然后,它允许在单个CPU内核中计算16 x16切片。要计算整个512 x512图像而不使用RAM上的任何阵列,您至少需要1024个内核(或线程)。如果线程不算为该问题的数组,则它应该工作。但技巧是计算不应写入结果,直到所有计算完成。一旦所有内核写入自己的瓦片,它应该被同步为完整的。但是提取/改变AVX寄存器的通道会消耗额外的性能。
如果AVX 512允许(32位模式=总寄存器数的1/4),则每个内核将有32 x32大小的瓦片,或者仅需要256个内核/线程。
我不知道你是否也被允许将值推到FPU中以获得额外的空间(可能不多,但仍然可以在2个瓦片或其他东西之间保存一些边界像素)。
如果图像又是单色的,你可以应用一个RLE来压缩它。一旦压缩,它应该花费更少的区域在输入数组中。然后你可以使用剩下的作为输出RLE。在最后一步,从那里做解压缩到整个输入再次。游程编码是快的,但解压缩每个像素读取将是慢的,或至少必须是太多的簿记。尽管如此,性能并不是这里的优先考虑因素,对吗?也许通过每行一个新的RLE可以降低复杂性。没有尝试。