优化循环像素的代码

时间:2017-11-29 21:40:14

标签: c image-processing optimization

我得到一个200x200的图像,作为像素的字节数组(每个像素3个字节,表示RGB值)。我想选择所有边界点,定义为非白色的点,并且位于图像的边界或具有不同颜色的相邻像素。

为此编写了简单的C代码:

int i = 0, row = 0, column = 0, width3 = width*3;
char r,g,b;
while (i < length) {

    r = pixels[i], g = pixels[i+1], b = pixels[i+2];

    if (r != -1 || g != -1 || b != -1) { // Not white
        // Check for border point
        if (column == 0 || column == width-1 || row == 0 || row == height-1
            || r != pixels[i-3] || r != pixels[i+3] || r != pixels[i-width3] || r != pixels[i+width3]
            || g != pixels[i-2] || g != pixels[i+4] || g != pixels[i-width3+1] || g != pixels[i+width3+1]
            || b != pixels[i-1] || b != pixels[i+5] || b != pixels[i-width3+2] || b != pixels[i+width3+2]) {
            // Border point
        }
    }

    i += 3;

    if (++column == width) {
        column = 0;
        row++;
        // printf("new row");
    }

}

现在我想知道如何尽可能加快速度。 要么我可以使用GPU,但是GPU的内存传输成本非常高。

由于我对openCV中使用的任何优化技术都很陌生,我想知道是否有办法让我的代码段更快。

(更多上下文;我想将图像上每个非白色物体的边界点解释为可见物体的“轮廓”,然后使用Douglas-Peucker将轮廓近似为多边形)

1 个答案:

答案 0 :(得分:3)

一些微观优化:

  • 重新组织行上的循环,只访问整个图像内的像素对,这样就不需要测试列和行索引了;

  • 不要左右测试:如果两个像素不同,单个比较就足够了;

  • 仅在检测到边界点时测试白色(它们只是图像区域的一小部分);

您的12次比较测试(减少到6次)可能是有效的,因为它使用快捷逻辑(因此所有测试仅在统一区域中执行)。您可以尝试将其换成无分支表达式,它将始终完整执行,但避免使用昂贵的条件分支:使用r0 - r1 | g0 - g1 | b0 - b1,对于相同的颜色只有零。

甚至更好,一次将整个像素作为整数值加载,计算适当的偏移量,xor它们并屏蔽额外的字节:(*(unsigned int*)pixels ^ *(unsigned int*)(pixels + 3)) >> 8

如果这还不够,你可以考虑使用矢量指令集(SSE / AVX),但这是另一个故事。