|
{ 作者:刘留 参考文献为: Jean-Yves Bouguet "Pyramidal Implementation of the Lucas Kanade Feature Tracker Description of the algorithm" http://www.aivisoft.net/ Geo.Cra[at]gmail[dot]com } unit OpticalFlowLK; interface uses Math, Windows, SysUtils, Variants, Classes, Graphics, unitypes, ColorConv; type TOpticalFlowLK = class private ImageOld, ImageNew: TTripleLongintArray; ImageGray, dx, dy, dxy: TDoubleLongintArray; Eigenvalues: TDoubleExtendedArray; WBPoint: TDoubleBooleanArray; Height, Width, L, RadioX, RadioY: longint; procedure CornerDetect(sWidth, sHeight: longint; Quality: extended); procedure MakePyramid(var Images: TTripleLongintArray; sWidth, sHeight, sL: longint); public Frame: TBitmap; Features: TSinglePointInfoArray; FeatureCount, SupportCount: longint; Speed, Radio: extended; procedure Init(sWidth, sHeight, sL: longint); procedure InitFeatures(Frames: TBitmap); procedure CalOpticalFlowLK(Frames: TBitmap); destructor Destroy; override; end; implementation procedure TOpticalFlowLK.CornerDetect(sWidth, sHeight: longint; Quality: extended); var i, j, fi, fj: longint; a, b, c, sum, MinAccept, MaxEigenvalue: extended; begin FeatureCount := 0; { 下面采用Good Feature To Track介绍的方法 J. Shi and C. Tomasi "Good Features to Track", CVPR 94 } for i := 1 to sWidth - 2 do for j := 1 to sHeight - 2 do begin dx[i, j] := ImageGray[i - 1, j - 1] + 2 * ImageGray[i - 1, j] + ImageGray[i - 1, j + 1] - (ImageGray[i + 1, j - 1] + 2 * ImageGray[i + 1, j] + ImageGray[i + 1, j + 1]); dy[i, j] := ImageGray[i - 1, j + 1] + 2 * ImageGray[i, j + 1] + ImageGray[i + 1, j + 1] - (ImageGray[i - 1, j - 1] + 2 * ImageGray[i, j - 1] + ImageGray[i + 1, j - 1]); dxy[i, j] := ImageGray[i + 1, j - 1] + ImageGray[i - 1, j + 1] - (ImageGray[i - 1, j - 1] + ImageGray[i + 1, j + 1]); end; {求取Sobel算子的Dx, Dy, Dxy Dx: |1 0 -1| |2 0 -2| |1 0 -1| Dy: |-1 -2 -1| | 0 0 0| | 1 2 1| Dxy |-1 0 1| | 0 0 0| | 1 0 -1|} MaxEigenvalue := 0; for i := 2 to sWidth - 3 do for j := 2 to sHeight - 3 do begin a := 0; b := 0; c := 0; for fi := i - 1 to i + 1 do for fj := j - 1 to j + 1 do begin a := a + sqr(dx[fi, fj]); b := b + dxy[fi, fj]; c := c + sqr(dy[fi, fj]); end; a := a / 2; c := c / 2; Eigenvalues[i, j] := (a + c - sqrt((a - c) * (a - c) + b * b)); if Eigenvalues[i, j] > MaxEigenvalue then MaxEigenvalue := Eigenvalues[i, j]; end; {求取矩阵 |∑Dx*Dx ∑Dxy| M=| | |∑Dxy ∑Dy*Dy| 的特征值 λ= ∑Dx*Dx + ∑Dy*Dy - ((∑Dx*Dx+∑Dy*Dy)^2-4*(∑Dx*Dx * ∑Dy*Dy - ∑Dxy * ∑Dxy))^1/2} MinAccept := MaxEigenvalue * Quality; {设置最小允许阀值} for i := 8 to sWidth - 9 do for j := 8 to sHeight - 9 do if Eigenvalues[i, j] > MinAccept then begin WBPoint[i, j] := true; Inc(FeatureCount); end else WBPoint[i, j] := false; for i := 8 to sWidth - 9 do for j := 8 to sHeight - 9 do if WBPoint[i, j] then begin sum := Eigenvalues[i, j]; for fi := i - 8 to i + 8 do begin for fj := j - 8 to j + 8 do if sqr(fi - i) + sqr(fj - j) <= 64 then if (Eigenvalues[fi, fj] >= sum) and ((fi <> i) or (fj <> j)) and (WBPoint[fi, fj]) then begin WBPoint[i, j] := false; Dec(FeatureCount); break; end; if not WBPoint[i, j] then break; end; end; {用非最大化抑制来抑制假角点} setlength(Features, FeatureCount); fi := 0; for i := 8 to sWidth - 9 do for j := 8 to sHeight - 9 do if WBPoint[i, j] then begin Features[fi].Info.X := i; Features[fi].Info.Y := j; Features[fi].Index := 0; Inc(fi); end; {输出最终的点序列} end; procedure TOpticalFlowLK.Init(sWidth, sHeight, sL: longint); begin Width := sWidth; Height := sHeight; L := sL; setlength(ImageOld, Width, Height, L); setlength(ImageNew, Width, Height, L); Frame := TBitmap.Create; Frame.Width := Width; Frame.Height := Height; Frame.PixelFormat := pf24bit; setlength(ImageGray, Width, Height); setlength(Eigenvalues, Width, Height); setlength(dx, Width, Height); setlength(dy, Width, Height); setlength(dxy, Width, Height); setlength(WBPoint, Width, Height); FeatureCount := 0; end; procedure TOpticalFlowLK.MakePyramid(var Images: TTripleLongintArray; sWidth, sHeight, sL: longint); var i, j, k, ii, jj, nWidth, nHeight, oWidth, oHeight: longint; begin {生成金字塔图像} oWidth := sWidth; oHeight := sHeight; for k := 1 to sL - 1 do begin nWidth := (oWidth + 1) shr 1; nHeight := (oHeight + 1) shr 1; for i := 1 to nWidth - 2 do begin ii := i shl 1; for j := 1 to nHeight - 2 do begin jj := j shl 1; Images[i, j, k] := (Images[ii, jj, k - 1] shl 2 + Images[ii - 1, jj, k - 1] shl 1 + Images[ii + 1, jj, k - 1] shl 1 + Images[ii, jj - 1, k - 1] shl 1 + Images[ii, jj + 1, k - 1] shl 1 + Images[ii - 1, jj - 1, k - 1] + Images[ii + 1, jj - 1, k - 1] + Images[ii - 1, jj + 1, k - 1] + Images[ii + 1, jj + 1, k - 1]) shr 4; {高斯原则,shl右移位,shr左移位} end; end; for i := 1 to nWidth - 2 do begin ii := i shl 1; Images[i, 0, k] := (Images[ii, 0, k - 1] shl 2 + Images[ii - 1, 0, k - 1] shl 1 + Images[ii + 1, 0, k - 1] shl 1 + Images[ii, 0, k - 1] shl 1 + Images[ii, 1, k - 1] shl 1 + Images[ii - 1, 0, k - 1] + Images[ii + 1, 0, k - 1] + Images[ii - 1, 1, k - 1] + Images[ii + 1, 1, k - 1]) shr 4; Images[i, nHeight - 1, k] := (Images[ii, oHeight - 1, k - 1] shl 2 + Images[ii - 1, oHeight - 1, k - 1] shl 1 + Images[ii + 1, oHeight - 1, k - 1] shl 1 + Images[ii, oHeight - 2, k - 1] shl 1 + Images[ii, oHeight - 1, k - 1] shl 1 + Images[ii - 1, oHeight - 2, k - 1] + Images[ii + 1, oHeight - 2, k - 1] + Images[ii - 1, oHeight - 1, k - 1] + Images[ii + 1, oHeight - 1, k - 1]) shr 4; end; {处理上下边} for j := 1 to nHeight - 2 do begin jj := j shl 1; Images[0, j, k] := (Images[0, jj, k - 1] shl 2 + Images[0, jj, k - 1] shl 1 + Images[1, jj, k - 1] shl [1] [2] [3] 下一页 |