【问题标题】:Fastest way to calculate maximum pixel gray value in the 8-adjacency of every pixel计算每个像素8邻接中最大像素灰度值的最快方法
【发布时间】:2017-11-01 17:17:27
【问题描述】:

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

我正在使用下面的代码在 C 中实现它。

        for(x = 0;x<row;x++){
            for(y = 0;y<col;y++){
                maxpixel = INT_MIN;
                if((x-1)>=0 && (y-1)>=0){
                    maxpixel = max(maxpixel,img[x-1][y-1]);
                }
                if((x-1)>=0){
                    maxpixel = max(maxpixel,img[x-1][y]);
                }
                if((x-1)>=0 && (y+1)<col){
                    maxpixel = max(maxpixel,img[x-1][y+1]);
                }
                if((y+1)<m){
                    maxpixel = max(maxpixel,img[x][y+1]);
                }
                if((x+1)<row && (y+1) <col){
                    maxpixel = max(maxpixel,img[x+1][y+1]);
                }
                if((x+1)<row){
                    maxpixel = max(maxpixel,img[x+1][y]);
                }
                if((x+1)<row && (y-1)>=0){
                    maxpixel = max(maxpixel,img[x+1][y-1]);
                }
                if((y-1)>=0){
                    maxpixel = max(maxpixel,img[x][y-1]);
                }
                // do some other constant time operation.
            }
        }

上面的代码按预期工作。但是,这似乎非常缓慢地迭代。

有没有提高速度的改进范围?

【问题讨论】:

  • 提高速度的一种方法是使第一行和最后一行、第一列和最后一列成为特殊情况。然后,您无需测试具有 8 个邻居的典型像素的边界。 max 是函数还是宏?确保它是内联的。
  • 当您计算连续三个像素的最大值(例如 1/3、2/3、3/3)时,您可以使用该值计算 2/2 和2/4,这样可以节省一些计算。也许这可以作为进一步优化的开始
  • 这是一次性通过img[] 还是会发生多次?
  • @beaker 是的,这是一个错字。已编辑。谢谢。

标签: c algorithm performance loops image-processing


【解决方案1】:

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

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

【讨论】:

    【解决方案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 个像素。

    【讨论】:

      【解决方案3】:

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

      []====+=====================================+====[]
      || 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 */
      

      【讨论】:

        猜你喜欢
        • 2013-09-06
        • 2016-03-22
        • 2018-01-01
        • 2019-07-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多