【问题标题】:How to speed up algorithm (Binarization, integral image)如何加速算法(二值化、积分图像)
【发布时间】:2010-02-17 12:38:20
【问题描述】:

我根据这个网址描述的积分图像算法编写了这个程序

http://people.scs.carleton.ca/~roth/iit-publications-iti/docs/gerh-50002.pdf

有什么方法可以更快地完成这段代码?

指针比动态数组快得多?

procedure TForm1.bBinarizationClick(Sender: TObject);
var
  iX1, iY1,
  iX2, iY2,
  ii, jj,
  s, s2,
  iSum, iCount,  index,
  iHeight, iWidth : Integer;
  iSize: Integer;

  row : ^TRGBTriple;
  black : TRGBTriple;
  aIntegralIm: array  of Integer;
  aGrays : array of Byte;

  startTime : Cardinal;

begin
  iWidth := bBitmap.Width;
  iHeight := bBitmap.Height;
  iSize := iWidth * iHeight;

  SetLength(aGrays, iSize);
  SetLength(aIntegralIm, iSize);

  black.rgbtRed  := (clBlack and $0000FF);
  black.rgbtGreen := (clBlack and $00FF00) shr 8;
  black.rgbtBlue := (clBlack and $FF0000) shr 16;

  bBitmap2.Canvas.Brush.Color := clWhite;
  bBitmap2.Canvas.FillRect(Rect(0, 0, bBitmap2.Width, bBitmap2.Height));

  s := Round(iWidth / TrackBar2.Position);
    s2 := Round(s / 2);

  startTime := GetTickCount();

  index := 0;

  for ii := 0 to iHeight - 1 do begin
     row := bBitmap.ScanLine[ii];
     for jj := 0 to iWidth - 1 do begin
       aGrays[index] := ((row.rgbtRed * 77 + row.rgbtGreen * 150 + row.rgbtBlue * 29) shr 8);
       inc(index);
       inc(row);
     end;
  end;


  for ii := 0 to iWidth - 1 do begin
     iSum := 0;
     for jj := 0 to iHeight - 1 do begin
       index := jj*iWidth+ii;
       iSum := iSum + aGrays[index];
       if ii = 0 then aIntegralIm[index] := iSum
       else aIntegralIm[index] := aIntegralIm[index - 1] + iSum;
     end;
  end;


  for jj := 0 to iHeight - 1 do begin
     row := bBitmap2.ScanLine[jj];
     for ii := 0 to iWidth - 1 do begin

       index := jj*iWidth+ii;

       iX1 := ii-s2;
       iX2 := ii+s2;
       iY1 := jj-s2;
       iY2 := jj+s2;

       if (iX1 < 0) then iX1 := 0;
         if (iX2 >= iWidth) then  iX2 := iWidth-1;
           if (iY1 < 0) then  iY1 := 0;
             if (iY2 >= iHeight) then  iY2 := iHeight-1;

       iCount := (iX2 - iX1) * (iY2 - iY1);

       iSum := aIntegralIm[iY2*iWidth+iX2]
              - aIntegralIm[iY1*iWidth+iX2]
              - aIntegralIm[iY2*iWidth+iX1]
              + aIntegralIm[iY1*iWidth+iX1];

       if (aGrays[index] * iCount) < (iSum * (100 - TrackBar1.Position) / 100) then  row^ :=  black;

       inc(row);

     end;
  end;

  ePath.Text :=  'Time: ' + inttostr(GetTickCount() - startTime) + ' ms';

  imgOryginal.Picture.Bitmap.Assign(bBitmap2);

end;

【问题讨论】:

  • 你需要解释这个算法的作用,以便人们帮助你。
  • 谢谢,我把 url 附加到算法描述中

标签: delphi


【解决方案1】:

你至少可以做一些简单的事情:

  • 预先计算 (100 - TrackBar1.Position) 到一个变量中
  • 而不是除法:/ 100 使用 * 100 在另一边。您可能不需要任何浮点值。
  • 使用以下查找表(顺便解释一下标识?):

代码:

if (iX1 < 0) then iX1 := 0;
if (iX2 >= iWidth) then  iX2 := iWidth-1;
if (iY1 < 0) then  iY1 := 0;
if (iY2 >= iHeight) then  iY2 := iHeight-1;
  • 尽量保持索引和icremnet,减而不是乘:index := jj*iWidth+ii;

【讨论】:

  • 感谢您的帮助。但是你认为我应该使用指针而不是动态数组,并做一些指针增量?
  • 指针肯定更快,所以你可以使用它们。如果禁用范围检查,它已经为基于索引的访问减少了一些 CPU 周期,但它仍然会更慢。
【解决方案2】:

我的猜测是第二个循环有点慢。

诀窍是避免一直在第二个循环中重新计算所有内容

如果 S 是常数(我的意思是相对于循环,不是绝对的)

  • iy1,iy2 仅随 main(jj) 循环而变化,iy1*width(和 iy2*width)也是如此。 预先计算它们,或者以与行相同的方式优化它们。 (每行预计算一次,中间递增)
  • 将ii循环改为三个循环:
    • ix1=0 的第一位
    • 第二个 ix1=ii-s ix2=ii+s;
    • ix1=ii-s 和 ix2=iwidth-1 的第三个

这消除了循环中的大量检查,只需执行一次。

  • 为条件创建一个专用循环 if (aGrays[index] * iCount)

  • 在灰度计算循环中引入指针,这样您就不必重新计算每个像素的索引(但例如仅用于行循环,每个像素递增一个 ptr)

如果你有耐心,你还可以预先计算行间的跳跃。请记住,abs(scanline[j]-scanline[i])-width 是衡量每行对齐字节数的指标。

更高级的是优化算法级别的缓存效果。看 rotating bitmaps. In code 了解这是如何工作的。那里也演示了一些指针技巧(但仅适用于 8 位元素)

【讨论】:

    【解决方案3】:

    我会首先使用分析器来找出 CPU 使用重新分区,以找出最能从优化中受益的代码的最小部分。 然后我会根据结果调整努力。如果某些代码代表了 90% 的 CPU 负载并且被执行了无数次,那么即使是极端的措施(使用内联汇编语言重新编码一些序列)也可能是有意义的。

    【讨论】:

      【解决方案4】:

      使用优秀且免费的SamplingProfiler 找出代码中的瓶颈。然后再次优化并运行分析器以找到下一个瓶颈。这种方法比猜测需要优化的内容要好得多,因为即使是专家也经常对此有误。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-08-10
        • 1970-01-01
        • 2012-10-18
        • 1970-01-01
        • 1970-01-01
        • 2017-07-19
        • 1970-01-01
        相关资源
        最近更新 更多