unit filterBlobBalance;
(* ***** BEGIN LICENSE BLOCK *****
* Copyright (C) 2004 Durand Emmanuel
* Copyright (C) 2004 Burgel Eric
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Contact :
* filters@edurand.com
* filters@burgel.com
*
* ***** END LICENSE BLOCK ***** *)
{
edurand (filters@edurand.com)
eburgel (filters@burgel.com)
}
interface
uses
filter, fparameters, image, windows, filterBlobExplorer;
type
TFilterBlobBalance = class(TFilter)
public
constructor Create; override;
procedure Run(); override;
procedure Run(command:String); override;
private
parameterImageBlob : TParameterImage;
parameterBlob : TParameterPointer;
parameterMonitoring : TParameterBoolean;
parameterImageOutMonitoring : TParameterImage;
ouputParameterAngle : TParameterSingle;
imageBlob, imgOutMonitoring : PBitmap32;
blob : PBlob;
angle,angleOffset : Single;
procedure _run();
end;
implementation
uses
imageIO, Math, divers;
constructor TFilterBlobBalance.Create;
begin
inherited;
parameterImageBlob:=addParameterImage('blobImage','input image containing the blob');
parameterBlob:=addParameterPointer('blob','a pointer on a TBlob object, provides for example by TFilterBlobExplorer');
parameterMonitoring:=addParameterBoolean('monitoring','monitoring',True);
parameterImageOutMonitoring:=addParameterImage('outImageMonitoring', 'image out monitoring');
ouputParameterAngle := addOutputParameterSingle('angle', 'computed angle') ;
angleOffset:=0;
end;
procedure TFilterBlobBalance.run();
begin
imageBlob := parameterImageBlob.Image ;
blob := parameterBlob.Value;
if (imageBlob<>nil) and (blob<>nil) then begin
_run();
end;
end;
procedure TFilterBlobBalance._run();
var
x,y : Integer;
xMin,xMax,yMin,yMax : Integer;
pSrc : PColor32Array;
c : TColor32;
gravityCenterLeft, gravityCenterRight : TFPoint;
pixelAreaLeft, pixelAreaRight : Integer;
dx,dy : Single;
begin
// monitoring
imgOutMonitoring:=parameterImageOutMonitoring.Image;
if (parameterMonitoring.Value=True) and (imgOutMonitoring<>nil) then begin
image.copyImageToImage(imageBlob,imgOutMonitoring);
image.drawLine(imgOutMonitoring,blob.gravityCenter.x,0,blob.gravityCenter.x,imgOutMonitoring.Height-1,clYellow32);
end else
if imgOutMonitoring<>nil then begin
image.eraseImage(imgOutMonitoring);
end;
// step 1
xMin:=Floor(blob.rectangleContainer.Left);
xMax:=Floor(blob.rectangleContainer.Right);
yMin:=Floor(blob.rectangleContainer.Top);
yMax:=Floor(blob.rectangleContainer.Bottom);
gravityCenterLeft.x:=0;
gravityCenterLeft.y:=0;
pixelAreaLeft:=0;
gravityCenterRight.x:=0;
gravityCenterRight.y:=0;
pixelAreaRight:=0;
for y:=yMin to yMax do begin
pSrc:=imageBlob.Bits;
Inc(pSrc,y*imageBlob.Width);
Inc(pSrc,xMin);
for x:=xMin to xMax do begin
c:=pSrc^[0];
if c=blob.color then begin
if x<blob.gravityCenter.x then begin
gravityCenterLeft.x:=gravityCenterLeft.x+x;
gravityCenterLeft.y:=gravityCenterLeft.y+y;
Inc(pixelAreaLeft);
end else
if x>blob.gravityCenter.x then begin
gravityCenterRight.x:=gravityCenterRight.x+x;
gravityCenterRight.y:=gravityCenterRight.y+y;
Inc(pixelAreaRight);
end;
end;
Inc(pSrc);
end;
end;
if (pixelAreaLeft>0) and (pixelAreaRight>0) then begin
gravityCenterLeft.x:=gravityCenterLeft.x/pixelAreaLeft;
gravityCenterLeft.y:=gravityCenterLeft.y/pixelAreaLeft;
gravityCenterRight.x:=gravityCenterRight.x/pixelAreaRight;
gravityCenterRight.y:=gravityCenterRight.y/pixelAreaRight;
if parameterMonitoring.Value=True then begin
image.drawDisk(imgOutMonitoring,blob.gravityCenter.x,blob.gravityCenter.y,2,clRed32);
image.drawDisk(imgOutMonitoring,gravityCenterLeft.x,gravityCenterLeft.y,2,clRed32);
image.drawDisk(imgOutMonitoring,gravityCenterRight.x,gravityCenterRight.y,2,clRed32);
image.drawLine(imgOutMonitoring,gravityCenterLeft,gravityCenterRight,clYellow32);
end;
dx:=gravityCenterRight.x-gravityCenterLeft.x;
dy:=-(gravityCenterRight.y-gravityCenterLeft.y);
angle:=RadToDeg(arcTan(dy/dx))-angleOffset;
end;
setOutputParameterSingle('angle',angle);
end;
procedure TFilterBlobBalance.Run(command:String);
begin
if (command='setAngleToZero') then begin
angleOffset:=angle+angleOffset;
end else
inherited Run(command);
end;
end.