最快的方法来计算每个像素的8邻接中的最大像素灰度值

时间:2017-05-31 18:51:02

标签: c algorithm performance loops image-processing

我想计算给定图像中每个像素的8邻接的最大像素灰度值。

我使用以下代码在C中实现它。

signInWithCredential()

上面的代码按预期工作。然而,这看起来像迭代一样缓慢。

是否有提高速度的改进范围?

3 个答案:

答案 0 :(得分:4)

是的,使用大语句,而不是几个语句。这样,您就不必评估所有语句,更不用说分支预测了。

这应该是开始优化代码的好方法。除此之外,您可以在Code Review中发帖以获取更多信息。祝你好运!

答案 1 :(得分:2)

在任意两个相邻像素之间有六个共享表达式,表明有可能提高约66%的速度。

在实践中,可以在垂直和水平方向分别计算最大值:

 for (i=0;i<h-2;i++) {
     for (j=0;j<w;j++)
        M[j] = max3(img[i][j], img[i+1][j], img[i+2]);
     for (j=0;j<w-2;j++)
         Out[i][j] = max4(M[j], img[i][j+1], img[i+2][j+1], M[j+2];
}

这完全避免了超出范围的测试并略微减少了比较。结果图像在每个方向上当然缩短了2个像素。

答案 2 :(得分:0)

您有八个特殊情况或多或少发生,有时这些情况可能会重合,如果您只有一行或只有一列或两者:

[]====+=====================================+====[]
|| UL | Upper row                           | UR ||
++----+-------------------------------------+----++
|| Le | Main block                          | Ri ||
|| ft |                                     | gh ||
||  c |                                     | t  ||
|| ol |                                     | co ||
||    |                                     | l  ||
||    |                                     |    ||
++----+-------------------------------------+----++
|| LL | Lower row                           | LR ||
[]====+=====================================+====[]

我应该为每个使用不同的循环,因此您知道一个小修道院可以访问哪些单元格而不必进行任何测试。如果数组只有一行或一列,你必须考虑特殊情况,但这就是全部。

我假设您有一个数组指针数组,正如您所说,但它简化了使用[]运算符对矩阵单元格的访问。

inline int max2(int a, int b) 
{ 
    return a > b ? a : b; 
}
inline int max3(int a, int b, int c) 
{ 
    return max2(max2(a, b), c); 
}
inline int max4(int a, int b, int c, int d) 
{ 
    return max2(max2(a, b), max2(c, d)); 
}
inline int max6(
        int a, int b, int c, 
        int d, int e, int f)
{
    return max2(max3(a, b, c), max3(d, e, f));
}
inline int max9(
        int a, int b, int c, 
        int d, int e, int f, 
        int g, int h, int i)
{
    return max3(max3(a, b, c), max3(d, e, f), max3(g, h, i));
}

void max_value(int **in, int **out, int rows, int cols)
{
    if (rows > 1) {
        /* to avoid many calculations */
        int rows_1 = rows - 1, rows_2 = rows - 2;

        if (cols > 1) { /* cols > 1 && rows > 1 */
            int cols_1 = cols - 1, cols_2 = cols - 2;

            /* first consider the four corners */
            /* UL */
            out[0][0] = max4(
                 in[0][0],          in[0][1], 
                 in[1][0],          in[1][1]);

            /* LR */
            out[rows_1][cols_1] = max4(
                 in[rows_2][cols_2],in[rows_2][cols_1],
                 in[rows_1][cols_2],in[rows_1][cols_1]);

            /* LL */
            out[rows_1][0] = max4(
                 in[rows_2][0],     in[rows_2][1],
                 in[rows_1][0],     in[rows_1][1]);

            /* UR */
            out[0][cols_1] = max4(
                 in[0][cols_2],     in[1][cols_2],
                 in[0][cols_1],     in[1][cols_1]);

            /* next the two side columns */
            for(row = 1; row < rows_1; row++) {
                /* left */
                out[row][0] = max6(
                 in[row-1][0],      in[row-1][1],
                 in[row][0],        in[row][1],
                 in[row+1][0],      in[row+1][1]); 

                /* right */
                out[row][cols_1] = max6(
                 in[row-1][cols_2], in[row-1][cols_1],
                 in[row][cols_2],   in[row][cols_1],
                 in[row+1][cols_2], in[row+1][cols_1]);
            } /* for */

            /* ... and the top/bottom rows */
            for(col = 1; col < cols_1; col++) {
                /* top */
                out[0][col] = max6(
                 in[0][col-1], in[0][col], in[0][col+1],
                 in[1][col-1], in[0][col], in[0][col+1]);
                /* bottom */
                out[row_1][col] = max6(
                 in[row_2][col-1], in[row_2][col], in[row_2][col+1],
                 in[row_1][col-1], in[row_1][col], in[row_1][col+1]);
            } /* for */

            /* and finally, the main block */
            for(row=1; row < row_1; row++) {
                for(col=1; col < col_1; col++) {
                    out[row][col] = max9(
                     in[row-1][col-1],in[row-1][col],in[row-1][col+1],
                     in[row][col-1],in[row][col],in[row][col+1],
                     in[row+1][col-1],in[row+1][col],in[row+1][col+1]);
                } /* for */
            } /* for */
        } else { /* rows > 1 && cols == 1 */
            /* we collapsed to three zones in one column */  
            /* UL == UR */
            out[0][0] = max2(
                    in[0][0],
                    in[1][0]);

            /* LL == LR */
            out[row_1][0] = max2(
                    in[row_2][0],
                    in[row_1][0]);

            /* main block */
            for(row = 1; row < rows_1; row++) {
                out[row][0] = max3(
                    in[row-1][0],
                    in[row][0],
                    in[row+1][0]);
            } /* for */
        } /* if */
    } else { /* rows == 1 */
        /* the nine zones collapse to three */
        if (cols > 1) {
            /* UL == LL */
            out[0][0] = max2(in[0][0], in[0][1]);
            /* UR == LR */
            out[0][col_1] = max2(in[0][col_2], in[0][col_1]);
            /* the main part */
            for(col=1; col < cols_1; col++)
                out[0][col] = max3(in[0][col-1],in[0][col],in[0][col+1]);
            } /* for */
        } else { /* rows == 1 && cols == 1 */
            /* ... or one */
            out[0][0] = in[0][0];
        }
    } /* if */
} /* max_value */