این هم یه Class که برات Sobel می گیره.
دیگه فکر کنم با اون توضیحات و این کد کارت راه بیفته.
unit filterSobel;
interface
uses
filter, fparameters, filterblur, filterConvolution, filterThresholdBinary, image;
type
TFilterSobel = class(TFilter)
public
constructor Create; override;
destructor Destroy; override;
procedure run(); override;
procedure setParameterImage( const aName: String; const aImage: PBitmap32); override ;
private
parameterImageIn, parameterImageOut, parameterImageOutDirection : TParameterImage;
parameterBlurIteration : TParameterInteger;
parameterGain : TParameterInteger;
parameterThresholdLower : TParameterInteger;
parameterThresholdUpper : TParameterInteger;
parameterModeFast : TParameterString;
filterBlur : TFilterBlur ;
filterConvSobelHorizontal, filterConvSobelVertical : TFilterConvolution ;
filterThresholdBinary : TFilterThresholdBinary;
convImageSobelHorizontal, convImageSobelVertical : PBitmap32 ;
imageBlurOut, imageSobelHorizontalOut, imageSobelVerticalOut, imageNormOut : PBitmap32;
imageIn : PBitmap32;
procedure _run();
procedure deleteImages;
procedure processNormal(imageIn : PBitmap32);
procedure processFast(imageIn : PBitmap32);
end;
implementation
uses
imageIO, Math;
constructor TFilterSobel.Create;
begin
inherited;
parameterImageIn := addParameterImage( 'inImage','input image');
parameterImageOut := addParameterImage( 'outImage','output image for the magnitude (edge strength)');
parameterImageOutDirection := addParameterImage( 'outImageDirection','output image for the edge direction');
parameterBlurIteration := addParameterInteger( 'blurIteration', 'if you want to preprocess to input image with a blur',0,50,1);
parameterGain := addParameterInteger( 'gain', 'to amplify the magnitude', 1,1000,200);
parameterThresholdLower := addParameterInteger( 'thresholdLower', 'if you want to postprocess the output image with a threshold',0,255,200);
parameterThresholdUpper := addParameterInteger( 'thresholdUpper', 'if you want to postprocess the output image with a threshold',0,255,255);
parameterModeFast := addParameterString( 'modeFast', 'TRUE/FALSE', 'TRUE');
filterBlur := TFilterBlur.Create ;
filterThresholdBinary:=TFilterThresholdBinary.Crea te;
filterConvSobelHorizontal := TFilterConvolution.Create ;
convImageSobelHorizontal := image.createImage(3, 3) ;
filterConvSobelHorizontal.setParameterImage('image Conv',convImageSobelHorizontal);
filterConvSobelHorizontal.setConvType(convSobelHor izontal);
filterConvSobelVertical := TFilterConvolution.Create ;
convImageSobelVertical := image.createImage(3, 3) ;
filterConvSobelVertical.setParameterImage('imageCo nv',convImageSobelVertical);
filterConvSobelVertical.setConvType(convSobelVerti cal);
end;
destructor TFilterSobel.Destroy;
begin
deleteImages;
filterBlur.Free;
filterConvSobelHorizontal.Free;
filterConvSobelVertical.Free;
filterThresholdBinary.Free;
image.freeImage(convImageSobelHorizontal);
image.freeImage(convImageSobelVertical);
end;
procedure TFilterSobel.deleteImages;
begin
image.freeImage(imageBlurOut);
image.freeImage(imageSobelHorizontalOut);
image.freeImage(imageSobelVerticalOut);
image.freeImage(imageNormOut);
end;
procedure TFilterSobel.setParameterImage( const aName: String; const aImage: PBitmap32);
begin
if aName='inImage' then begin
deleteImages;
imageBlurOut := createImageFromImage(aImage);
imageSobelHorizontalOut := createImageFromImage(aImage);
imageSobelVerticalOut := createImageFromImage(aImage);
imageNormOut := createImageFromImage(aImage);
end;
inherited;
end;
procedure TFilterSobel.run();
begin
imageIn := parameterImageIn.Image;
if (imageIn<>nil) then begin
_run();
end;
end;
procedure TFilterSobel._run();
var
i : Integer;
begin
// preprocess with blur
if parameterBlurIteration.Value>0 then begin
filterBlur.setParameterImage('inImage',imageIn);
filterBlur.setParameterImage('outImage',imageBlurO ut);
i:=parameterBlurIteration.Value;
while i>0 do begin
filterBlur.Run;
Dec(i);
if imageIn<>parameterImageIn.Image then begin
image.freeImage(imageIn);
end;
if i>0 then begin
imageIn:=createImageFromImage(imageBlurOut);
filterBlur.setParameterImage('inImage',imageIn);
end;
end;
imageIn:=imageBlurOut;
end;
// process
if parameterModeFast.Value='FALSE' then begin
processNormal(imageIn);
end else begin
processFast(imageIn);
end;
// postprocess with Threshold
if (parameterThresholdLower.Value<>0) and (parameterThresholdLower.Value<>255) then begin
filterThresholdBinary.setParameterImage('inImage', imageNormOut);
filterThresholdBinary.setParameterImage('outImage' ,parameterImageOut.Image);
filterThresholdBinary.setParameterInteger('thresho ldLower',parameterThresholdLower.Value);
filterThresholdBinary.setParameterInteger('thresho ldUpper',parameterThresholdUpper.Value);
filterThresholdBinary.Run;
end else begin
copyImageToImage(imageNormOut, parameterImageOut.Image);
end;
end;
procedure TFilterSobel.processNormal(imageIn : PBitmap32);
var
pSrcGx, pSrcGy, pDest, pDestDirection : PColor32Array;
g : Integer;
w, h :Integer;
x, y : Cardinal ;
valueGx, valueGy : Integer;
Flt : double;
angleRad : Single;
angleDeg : Integer;
indexBuffer : Integer;
const Half : double = 0.5;
begin
// Sobel Horizontal
filterConvSobelHorizontal.setParameterImage('inIma ge',imageIn);
filterConvSobelHorizontal.setParameterImage('outIm age',imageSobelHorizontalOut);
filterConvSobelHorizontal.setParameterInteger('z', parameterGain.Value);
filterConvSobelHorizontal.Run;
// Sobel Vertical
filterConvSobelVertical.setParameterImage('inImage ',imageIn);
filterConvSobelVertical.setParameterImage('outImag e',imageSobelVerticalOut);
filterConvSobelVertical.setParameterInteger('z', parameterGain.Value);
filterConvSobelVertical.Run;
// g=Sqrt(Gx^2+Gy^2)
pSrcGx := imageSobelHorizontalOut.Bits;
pSrcGy := imageSobelVerticalOut.Bits;
pDest := imageNormOut.Bits;
if parameterImageOutDirection.Image<>nil then begin
pDestDirection := parameterImageOutDirection.Image.Bits;
end;
h := parameterImageIn.Image.Height-1;
w := parameterImageIn.Image.Width-1;
for y:=h-1 downto 0 do Begin
for x:=w-1 downto 0 do begin
indexBuffer := y*w+x;
valueGx := pSrcGx^[indexBuffer] and $000000FF;
valueGy := pSrcGy^[indexBuffer] and $000000FF;
Flt := Sqrt( valueGx*valueGx + valueGy*valueGy );
// trunc float 'Flt' to integer 'g'
asm
fld Flt;
fsub Half;
fistp g;
end;
if g>255 then g:=255;
pDest[indexBuffer] := Gray32( g );
end;
end ;
end;
procedure TFilterSobel.processFast(imageIn : PBitmap32);
var
pSrc, PDest : PColor32Array;
w,h :Integer;
p1,p2,p3,p4,p6,p7,p8,p9 : Integer;
g : Integer;
imageSrcRow, imageSrcCol : Integer;
imageSrcRowmax, imageSrcColmax : Integer;
imageSrcNeighborRowmin, imageSrcNeighborColmin : Integer;
imageSrcNeighborRowmax, imageSrcNeighborColmax : Integer;
begin
h:=imageIn.Height;
w:=imageIn.Width;
pSrc:=imageIn.Bits;
imageSrcRowmax:=h-1;
imageSrcColmax:=w-1;
for imageSrcRow:=0 to imageSrcRowmax do begin
pDest:=imageNormOut.Bits;
Inc(pDest,imageSrcRow*w);
for imageSrcCol:=0 to imageSrcColmax do begin
imageSrcNeighborRowmin:=imageSrcRow-1; if imageSrcNeighborRowmin<0 then imageSrcNeighborRowmin:=0;
imageSrcNeighborColmin:=imageSrcCol-1; if imageSrcNeighborColmin<0 then imageSrcNeighborColmin:=0;
imageSrcNeighborRowmax:=imageSrcRow+1; if imageSrcNeighborRowmax>imageSrcRowmax then imageSrcNeighborRowmax:=imageSrcRowmax;
imageSrcNeighborColmax:=imageSrcCol+1; if imageSrcNeighborColmax>imageSrcColmax then imageSrcNeighborColmax:=imageSrcColmax;
p1:=pSrc[imageSrcNeighborRowmin*w+imageSrcNeighborColmin] and $000000FF;
p2:=pSrc[imageSrcNeighborRowmin*w+imageSrcCol] and $000000FF;
p3:=pSrc[imageSrcNeighborRowmin*w+imageSrcNeighborColmax] and $000000FF;
p4:=pSrc[imageSrcRow*w+imageSrcNeighborColmin] and $000000FF;
p6:=pSrc[imageSrcRow*w+imageSrcNeighborColmax] and $000000FF;
p7:=pSrc[imageSrcNeighborRowmax*w+imageSrcNeighborColmin] and $000000FF;
p8:=pSrc[imageSrcNeighborRowmax*w+imageSrcCol] and $000000FF;
p9:=pSrc[imageSrcNeighborRowmax*w+imageSrcNeighborColmax] and $000000FF;
g:=abs((p1+2*p2+p3)-(p7+2*p8+p9))+abs((p3+2*p6+p9)-(p1+2*p4+p7));
if g>255 then g:=255;
// set gray value with Color32 for optimization
pDest^[0]:= Color32(g,g,g);
Inc(pDest);
end;
end;
end;
end.