2010-02-17 27 views
2

我写这个网址如何加快算法(二值化,积分图像)

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; 
+1

你需要解释一下这个算法为了让人们来帮助你。 –

+0

谢谢,我附上网址描述算法 – Kowalikus

回答

2

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

  • 预先计算(100 - TrackBar1.Position)为变量
  • 相反师:/ 100使用* 100的另一面。您可能不需要任何浮点值。以下
  • 使用查找表(注意BTW解释identation?):

代码:

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,乘法递减istead:指数:= jj * iWidth + ii;
+0

感谢您的回复它的帮助。但你认为我应该使用指针而不是动态数组,并做一些指针增量? – Kowalikus

+1

绝对是的。 –

+0

指针肯定是更快,所以你可以使用这些。如果你禁用范围检查,它已经削减了一些CPU周期到基于索引的访问,但它仍然会变慢。 –

2

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

诀窍是避免在第二循环中重新计算一切所有的时间

若S是恒定的(相对于环我的意思是,不是绝对的)

  • iy1,IY2唯一的变化与主(jj)循环,所以做iy1 *宽度(和iy2 *宽度)。 对它们进行预先计算,或者像对待行一样对它们进行优化。 (每行预先计算一次,递增其间)
  • 变化的二回路成三个循环:
    • 第一比特,其中IX1 = 0
    • 第二其中IX1 = II-S IX2 = II + S;
    • 第三其中IX1 = II-S和IX2 = iwidth-1

这消除了很多检查出来的循环,仅被进行一次。

  • 作出的状态的专用回路,如果(aGrays [索引] * ICOUNT)<(ISUM *(100 - TrackBar1.Position)/ 100),则行^:=黑色;所以不对每个像素进行评估,因为您可以预先计算出发生这种情况的区域?

  • 在灰色计算循环中引入指针,以便您不必重新计算每个像素的索引(但例如,仅针对行循环,递增每像素ptr)

如果您很难,也可以预先计算行间跳转。请记住,abs(scanline [j] -scanline [i]) - width是每行对齐字节数的度量。

更高级的是在算法级别优化缓存效果。请参阅 rotating bitmaps. In code 了解其工作原理。一些指针技巧也在那里演示(但仅限于8位元素)

1

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

0

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