我根据此网址描述的积分图像算法编写了此程序
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;
答案 0 :(得分:2)
你至少可以做一些简单的事情:
代码:
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;
答案 1 :(得分:2)
我的猜测是第二个循环是慢位。
诀窍是避免一直重新计算第二个循环中的所有内容
如果S是常数(相对于我的意思是环,不是绝对的)
这会从循环中删除大量检查,只需执行一次。
为条件if(aGrays [index] * iCount)&lt; (iSum *(100 - TrackBar1.Position)/ 100)然后行^:=黑色;所以不对每个像素进行评估,因为你可以预先计算出发生这种情况的区域吗?
将指针引入灰色计算循环,这样您就不必重新计算每个像素的索引(但仅限于行循环,每个像素递增一个ptr)
如果你很耐心,你也可以预先计算线之间的跳跃。请记住,abs(scanline [j] -scanline [i]) - width是每行对齐字节数的度量标准。
更高级的是在算法级别上优化缓存效果。看到 rotating bitmaps. In code 了解这是如何工作的。这里也演示了一些指针技巧(但仅适用于8位元素)
答案 2 :(得分:1)
我首先使用分析器来查找CPU使用率重新分区,以找出最有利于优化的代码的最小部分。 然后我会根据结果调整工作量。如果某些代码代表90%的CPU负载并执行数十亿次,即使是极端措施(使用内联汇编语言重新编码一些序列)也可能有意义。
答案 3 :(得分:0)
使用优秀且免费的SamplingProfiler来找出代码中的瓶颈。然后再次优化并运行探查器以找到下一个瓶颈。这种方法比猜测需要优化什么要好得多,因为即使是专家也常常对此不以为然。