c - 优化循环遍历像素的代码

标签 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 传输内存和向 GPU 传输内存非常昂贵。

由于我对任何类型的优化技术(例如 openCV 中使用的优化技术)都是全新的,所以我想知道是否有任何方法可以使我的代码段更快。

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

最佳答案

一些微优化:

  • 重新组织行上的循环以仅访问完全位于图像内部的像素对,这样您就无需测试列索引和行索引;

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

  • 如果您检测到边界点(它们只是图像区域的一小部分),则仅测试白色;

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

或者更好的是,一次加载整个像素作为整数值,计算适当的偏移量,对它们进行异或并屏蔽掉额外的字节:(*(unsigned int*)pixels ^ *(unsigned int*) (像素 + 3)) >> 8.

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

关于c - 优化循环遍历像素的代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47562303/

相关文章:

optimization - Haskell 基准测试/优化非严格归约的 nf/whnf

ruby - 我如何重构这段 Ruby 代码以消除重复?

c++ - 作为 OpenMP pragma 的结果的中间代码

c - Toom-Cook乘法算法实现

java - 使用 JavaCV 在图像中进行模式检测

python - 将文件转换为灰度图像

c++ - 我如何优化/改进这个哈希函数

c - 微 Controller 编程 - 程序不退出循环

c - 使用 cygwin gcc 时出现 typedef 定义错误

c++ - 在 ROI 中使用 findContours,轮廓坐标错误