unit filterCutter;
(* ***** 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)
}
interface
uses
filter, fparameters, image, windows, filterCopy, filterBlobExplorer, filterBlobRepositioning2;
type
TFilterCutter = class(TFilter)
public
constructor Create; override;
destructor Destroy; override;
procedure Run(); override;
procedure setParameterImage( const aName: String; const aImage: PBitmap32); override ;
private
parameterMonitoring : TParameterBoolean;
parameterType : TParameterString;
parameterMargin : TParameterInteger;
parameterImageIn : TParameterImage;
parameterImageOutMonitoring : TParameterImage;
parameterImageOuts : TParameterImages;
parameterCutterTiles_RectWidth, parameterCutterTiles_RectHeight : TParameterInteger;
parameterCutterBlob_TrhesholdBackground : TParameterInteger;
parameterCutterBlob_AreaMin, parameterCutterBlob_AreaMax : TParameterInteger;
parameterCutterBlob_Clean : TParameterBoolean;
parameterCutterBlob_UseBlobRepositioning : TParameterBoolean;
imageOuts : ArrayOfPBitmap32;
filterCopy : TFilterCopy;
filterBlob : TFilterBlobExplorer;
filterBlobRepositioning : TFilterBlobRepositioning2;
imgIn, imgOutMonitoring : PBitmap32;
innerImgIn, blobOutImage : PBitmap32;
margin : Integer;
procedure _run();
procedure destroyImageOuts();
procedure _tiles();
procedure _blob();
end;
implementation
uses
imageIO, Math, filterPyramid, Types;
constructor TFilterCutter.Create;
begin
inherited;
parameterMonitoring:=addParameterBoolean('monitoring','monitoring',True);
parameterType:=addParameterString('type','cutter type [TILES/RECTANGULAR]','TILES');
parameterMargin:=addParameterInteger('margin','margin to add on each side of the calculated rectangle',0,100,10);
parameterImageIn:=addParameterImage('inImage', 'input image');
parameterImageOutMonitoring:=addParameterImage('outImageMonitoring', 'image out monitoring');
parameterImageOuts:=addOutputParameterImages('outImages', 'outImages');
// tiles
parameterCutterTiles_RectWidth := addParameterInteger('cutterTiles_RectWidth', 'width of images with tiles cutter', 16, 10000, 32) ;
parameterCutterTiles_RectHeight := addParameterInteger('cutterTiles_RectHeight', 'height of images with tiles cutter', 16, 10000, 32) ;
// blob
parameterCutterBlob_TrhesholdBackground:=addParameterInteger('cutterBlob_ThresholdBackground','',0,255,200);
parameterCutterBlob_AreaMin:=addParameterInteger('cutterBlob_AreaMin','explication...',0,999999,0);
parameterCutterBlob_AreaMax:=addParameterInteger('cutterBlob_AreaMax','explication...',0,999999,999999);
parameterCutterBlob_Clean:=addParameterBoolean('cutterBlob_Clean','if true then show only blobs one by one',true);
parameterCutterBlob_UseBlobRepositioning:=addParameterBoolean('cutterBlob_UseBlobRepositioning','use TFilterBlobRepositioning2',true);
//
SetLength(imageOuts, 0);
filterCopy:=TFilterCopy.Create;
filterBlob:=TFilterBlobExplorer.Create;
innerImgIn:=image.createImage(0,0);
blobOutImage:=image.createImage(0,0);
filterBlobRepositioning:=TFilterBlobRepositioning2.Create;
end;
destructor TFilterCutter.Destroy;
begin
image.freeImage(innerImgIn);
image.freeImage(blobOutImage);
filterBlobRepositioning.Free;
filterBlob.Free;
filterCopy.Free;
destroyImageOuts();
inherited;
end;
procedure TFilterCutter.destroyImageOuts();
var
i : Integer;
begin
for i:=Low(imageOuts) to High(imageOuts) do begin
image.freeImage(imageOuts[i]);
end;
SetLength(imageOuts,0);
end;
procedure TFilterCutter.setParameterImage( const aName: String; const aImage: PBitmap32);
begin
if aName='inImage' then begin
imgIn:=aImage;
innerImgIn:=image.eraseOrCreateImageLike(innerImgIn,imgIn);
blobOutImage:=image.eraseOrCreateImageLike(blobOutImage,imgIn);
end;
inherited;
end;
procedure TFilterCutter.run();
begin
if (imgIn<>nil) then begin
_run();
end;
end;
procedure TFilterCutter._run();
begin
destroyImageOuts();
margin:=parameterMargin.Value;
// monitoring
imgOutMonitoring:=parameterImageOutMonitoring.Image;
if (parameterMonitoring.Value=True) and (imgOutMonitoring<>nil) then begin
image.copyImageToImage(imgIn,imgOutMonitoring);
end else
if imgOutMonitoring<>nil then begin
image.eraseImage(imgOutMonitoring);
end;
// process
if parameterType.Value='BLOB' then begin
_blob()
end else begin
_tiles();
end;
end;
procedure TFilterCutter._tiles();
var
cutterRectWidth, cutterRectHeight : Integer;
rectSubImg, rectSubImgWithMargin : TRect;
filterCopyOutImage : PBitmap32;
tmpF : Single;
row, nbRow, errorHeight, correctionHeight, nextRowPosition : Integer;
col, nbCol, errorWidth, correctionWidth, nextColPosition : Integer;
begin
filterCopy.setParameterImage('inImage',imgIn);
cutterRectWidth:=parameterCutterTiles_RectWidth.Value;
cutterRectHeight:=parameterCutterTiles_RectHeight.Value;
if cutterRectWidth>imgIn.Width then begin
cutterRectWidth:=imgIn.Width;
end;
if cutterRectHeight>imgIn.Height then begin
cutterRectHeight:=imgIn.Height;
end;
tmpF:=imgIn.Height/cutterRectHeight;
if Frac(tmpF)=0.0 then begin
nbRow:=Trunc(tmpF);
correctionHeight:=0;
end else begin
nbRow:=Trunc(tmpF)+1;
errorHeight:=(nbRow*cutterRectHeight)-imgIn.Height;
correctionHeight:=Round(errorHeight/(nbRow-1));
end;
tmpF:=imgIn.Width/cutterRectWidth;
if Frac(tmpF)=0.0 then begin
nbCol:=Trunc(tmpF);
correctionWidth:=0;
end else begin
nbCol:=Trunc(tmpF)+1;
errorWidth:=(nbCol*cutterRectWidth)-imgIn.Width;
correctionWidth:=Round(errorWidth/(nbCol-1));
end;
rectSubImg.Top:=0;
rectSubImg.Bottom:=cutterRectHeight;
for row:=1 to nbRow do begin
rectSubImg.Left:=0;
rectSubImg.Right:=cutterRectWidth;
for col:=1 to nbCol do begin
rectSubImgWithMargin:=rectSubImg;
Dec(rectSubImgWithMargin.Left,margin);
Dec(rectSubImgWithMargin.Top,margin);
Inc(rectSubImgWithMargin.Right,margin);
Inc(rectSubImgWithMargin.Bottom,margin);
// monitoring
if (parameterMonitoring.Value=True) and (imgOutMonitoring<>nil) then begin
image.drawRect(imgOutMonitoring,rectSubImgWithMargin,clYellow32,2);
image.drawLine(imgOutMonitoring,rectSubImg.Left,rectSubImg.Top,rectSubImg.Right,rectSubImg.Bottom,clYellow32,1);
image.drawLine(imgOutMonitoring,rectSubImg.Right,rectSubImg.Top,rectSubImg.Left,rectSubImg.Bottom,clYellow32,1);
end;
SetLength(imageOuts, Length(imageOuts)+1);
filterCopy.setRegionOfInterest(rectSubImgWithMargin);
filterCopy.Run;
filterCopyOutImage:=filterCopy.getOutputParameterImage('outImage').Image;
imageOuts[Length(imageOuts)-1]:=image.createImageFromImage(filterCopyOutImage);
nextColPosition:=rectSubImg.Left+cutterRectWidth-correctionWidth;
rectSubImg.Left:=nextColPosition;
rectSubImg.Right:=nextColPosition+cutterRectWidth;
end;
nextRowPosition:=rectSubImg.Top+cutterRectHeight-correctionHeight;
rectSubImg.Top:=nextRowPosition;
rectSubImg.Bottom:=nextRowPosition+cutterRectHeight;
end;
setOutputParameterImages('outImages', imageOuts);
end;
procedure TFilterCutter._blob();
var
blobCount : Integer;
blob : PBlob;
i : Integer;
x,y : Integer;
rectSubImg, rectSubImgWithMargin : TRect;
cuttedImage : PBitmap32;
blobs : TParameterArrayPointers;
clean, useBlobRepositioning : Boolean;
begin
clean:=parameterCutterBlob_Clean.Value;
useBlobRepositioning:=parameterCutterBlob_UseBlobRepositioning.Value;
if useBlobRepositioning=true then begin
filterBlobRepositioning.setParameterBoolean('monitoring',false);
filterBlobRepositioning.setParameterInteger('margin', margin);
end;
// extract blobs
filterBlob.setParameterImage('inImage',imgIn);
filterBlob.setParameterInteger('intensityBackground', parameterCutterBlob_TrhesholdBackground.Value);
filterBlob.setParameterInteger('blobAreaMin', parameterCutterBlob_AreaMin.Value);
filterBlob.setParameterInteger('blobAreaMax', parameterCutterBlob_AreaMax.Value);
filterBlob.setParameterImage('outImage',blobOutImage);
filterBlob.setParameterBoolean('contour',false);
if useBlobRepositioning=false then begin
filterBlob.setParameterBoolean('criticalPoints',false);
end else begin
filterBlob.setParameterBoolean('criticalPoints',true);
filterBlob.setParameterInteger('contourCriticalPointsAppoximationAccuracy',20);
end;
filterBlob.setParameterBoolean('blobSurfaceInfo',true);
filterBlob.setParameterBoolean('monitoring',false);
filterBlob.Run;
// monitoring
if (parameterMonitoring.Value=True) and (imgOutMonitoring<>nil) then begin
image.copyImageToImage(blobOutImage,imgOutMonitoring);
end;
// for each blob found
blobs:=filterBlob.getOutputParameterArrayPointers('blobs');
blobCount:=Length(blobs.Pointers);
SetLength(imageOuts, blobCount);
for i:=blobCount-1 downto 0 do begin
blob:=blobs.Pointers[i];
rectSubImg.Left:=Round(blob.rectangleContainer.Left);
rectSubImg.Top:=Round(blob.rectangleContainer.Top);
rectSubImg.Right:=Round(blob.rectangleContainer.Right);
rectSubImg.Bottom:=Round(blob.rectangleContainer.Bottom);
rectSubImgWithMargin:=rectSubImg;
Dec(rectSubImgWithMargin.Left,margin); rectSubImgWithMargin.Left:=Max(0,rectSubImgWithMargin.Left);
Dec(rectSubImgWithMargin.Top,margin); rectSubImgWithMargin.Top:=Max(0,rectSubImgWithMargin.Top);
Inc(rectSubImgWithMargin.Right,margin); rectSubImgWithMargin.Right:=Min(imgIn.Width-1,rectSubImgWithMargin.Right);
Inc(rectSubImgWithMargin.Bottom,margin); rectSubImgWithMargin.Bottom:=Min(imgIn.Height-1,rectSubImgWithMargin.Bottom);
// monitoring
if (parameterMonitoring.Value=True) and (imgOutMonitoring<>nil) then begin
image.drawRect(imgOutMonitoring,rectSubImgWithMargin,clYellow32,2);
end;
if (clean=false) and (useBlobRepositioning=false) then begin
filterCopy.setParameterImage('inImage',imgIn);
filterCopy.setRegionOfInterest(rectSubImgWithMargin);
filterCopy.Run;
cuttedImage:=filterCopy.getOutputParameterImage('outImage').Image;
end else begin
image.eraseImage(innerImgIn);
// we keep only pixel of the current blob
for y:=rectSubImgWithMargin.Top to rectSubImgWithMargin.Bottom-1 do begin
for x:=rectSubImgWithMargin.Left to rectSubImgWithMargin.Right-1 do begin
{if image.getPixel(blobOutImage,x,y)=blob.color then begin
image.setPixel(innerImgIn,x,y,clWhite32);
end;}
if image.getPixel(blobOutImage,x,y)=blob.color then begin
image.setPixel(innerImgIn,x,y,image.getPixel(imgIn,x,y));
end;
end;
end;
filterCopy.setParameterImage('inImage',innerImgIn);
filterCopy.setRegionOfInterest(rectSubImgWithMargin);
filterCopy.Run;
cuttedImage:=filterCopy.getOutputParameterImage('outImage').Image;
end;
if useBlobRepositioning=true then begin
filterBlobRepositioning.setParameterImage('inImage',cuttedImage);
filterBlobRepositioning.setParameterBoolean('monitoring',false);
filterBlobRepositioning.setParameterInteger('margin',margin);
filterBlobRepositioning.setParameterInteger('blob_ThresholdBackground',1);
filterBlobRepositioning.Run;
cuttedImage := filterBlobRepositioning.getOutputParameterImage('outImage').Image;
end;
imageOuts[i]:=image.createImageFromImage(cuttedImage);
end;
setOutputParameterImages('outImages', imageOuts);
end;
end.