// ##############################################################
// Prozedur um Graubild zu erzeugen
// ##############################################################
Procedure ConvertToGrayScale(ImgIn : TBitmap;
var ImgOut : TBitmap);
type TRGB =
Array[1..3]
of Byte;
PixArray =
Array[1..MaxInt
div SizeOf(TRGB)-1]
of TRGB;
PPixArray = ^PixArray;
PixArray2D =
Array of PPixArray;
var ImgIn2D : PixArray2D;
// Access to ImgIn Pixels
ImgOut2D : PixArray2D;
// Access to ImgOut Pixels
rows,cols : Integer;
GrayShade : Byte;
begin
// Build 2D Arrays via 'scanline' to speed up pixel operations
// access pixels: Img[a]^[b][c] , a=line, b=col, c: 3=R,2=G,or 1=B
// Input Image:
SetLength(ImgIn2D,ImgIn.Height);
For rows := 0
to ImgIn.Height-1
do ImgIn2D[rows] := ImgIn.ScanLine[rows];
// Output Image:
SetLength(ImgOut2D,ImgOut.Height);
For rows := 0
to ImgOut.Height-1
do ImgOut2D[rows] := ImgOut.ScanLine[rows];
// Convert to grayscale
for rows := 0
to ImgIn.Height-1
do
for cols := 0
to ImgIn.Width-1
do
begin
GrayShade := Round( 0.3 * ImgIn2D[rows]^[cols][3]
+ 0.6 * ImgIn2D[rows]^[cols][2]
+ 0.1 * ImgIn2D[rows]^[cols][1]);
ImgOut2D[rows]^[cols][1] := GrayShade;
// B-value
ImgOut2D[rows]^[cols][2] := GrayShade;
// G-value
ImgOut2D[rows]^[cols][3] := GrayShade;
// R-value
end;
end;
// ##############################################################
// Prozeduren um Filter Matrizen zu erzeugen
// ##############################################################
Procedure MakeSmoothenFilter(
var Filter : TFilter);
var i : Integer;
begin
// Set Dimensions of Filter Array
SetLength(Filter,5);
for i := 0
to High(Filter)
do SetLength(Filter[i],5);
// Define Gauss Filter Matrix
// 2 4 5 4 2
// 4 9 12 9 4
// 5 12 15 12 5
// 4 9 12 9 4
// 2 4 5 4 2
// first Line
Filter[0,0] := 2; Filter[0,1] := 4; Filter[0,2] := 5;
Filter[0,3] := 4; Filter[0,4] := 2;
// second Line
Filter[1,0] := 4; Filter[1,1] := 9; Filter[1,2] := 12;
Filter[1,3] := 9; Filter[1,4] := 4;
// third Line
Filter[2,0] := 5; Filter[2,1] := 12; Filter[2,2] := 15;
Filter[2,3] := 12; Filter[2,4] := 5;
// fourth Line
Filter[3,0] := 4; Filter[3,1] := 9; Filter[3,2] := 12;
Filter[3,3] := 9; Filter[3,4] := 4;
// fifth Line
Filter[4,0] := 2; Filter[4,1] := 4; Filter[4,2] := 5;
Filter[4,3] := 4; Filter[4,4] := 2;
end;
Procedure MakeSobelFilterX(
var Filter : TFilter);
var i : integer;
begin
// Set Dimensions of Filter Array
SetLength(Filter,3);
for i := 0
to High(Filter)
do SetLength(Filter[i],3);
// Define Sobel-X Filter Matrix
// -1 0 1
// -2 0 2
// -1 0 1
// first Line
Filter[0,0] := -1; Filter[0,1] := 0; Filter[0,2] := 1;
// second Line
Filter[1,0] := -2; Filter[1,1] := 0; Filter[1,2] := 2;
// third Line
Filter[2,0] := -1; Filter[2,1] := 0; Filter[2,2] := 1;
end;
Procedure MakeSobelFilterY(
var Filter : TFilter);
var i : integer;
begin
// Set Dimensions of Filter Array
SetLength(Filter,3);
for i := 0
to High(Filter)
do SetLength(Filter[i],3);
// Define Sobel-Y Filter Matrix
// 1 2 1
// 0 0 0
// -1 -2 -1
// first Line
Filter[0,0] := 1; Filter[0,1] := 2; Filter[0,2] := 1;
// second Line
Filter[1,0] := 0; Filter[1,1] := 0; Filter[1,2] := 0;
// third Line
Filter[2,0] := -1; Filter[2,1] := -2; Filter[2,2] := -1;
end;
// ##############################################################
// Prozedur um Filter auf ein Bild anzuwenden (Faltung)
// ##############################################################
Procedure ApplyFilterOnImage(
var ImgIn, ImgOut : TBitmap; Filter : TFilter);
type TRGB =
Array[1..3]
of Byte;
PixArray =
Array[1..MaxInt
div SizeOf(TRGB)-1]
of TRGB;
PPixArray = ^PixArray;
PixArray2D =
Array of PPixArray;
var rows,cols : Integer;
// rows and cols in the image
FLowX, FHighX : Integer;
FLowY, FHighY : Integer;
weight : Integer;
// Weight for Filter Matrix
ImgIn2D : PixArray2D;
// Access to ImgIn Pixels
ImgOut2D : PixArray2D;
// Access to ImgOut Pixels
SumMinus : Integer;
ScaleShift : Integer;
PixelSum, x, y : Integer;
Pixel : Integer;
begin
// Filter matrix, element -> pixel position with respect to center pixel
// Calculate extremes in x and y direction
FLowX := -Round(0.5 * Length(Filter)-1);
FHighX := +Round(0.5 * Length(Filter)-1);
FLowY := -Round(0.5 * Length(Filter[0])-1);
FHighY := +Round(0.5 * Length(Filter[0])-1);
// Determine matrix weight and scaleshift required after convolution:
ScaleShift := 0;
SumMinus := 0;
weight := 0;
For y := 0
to High(Filter[0])
do
For x := 0
to High(Filter)
do
begin
if Filter[x,y] < 0
then SumMinus := SumMinus + Filter[x,y];
weight := weight + Abs(Filter[x,y]);
end;
ScaleShift := Abs(Round((SumMinus/weight)*255));
// Build 2D Arrays via 'scanline' to speed up pixel operations
// access pixels: Img[a]^[b][c] , a=line, b=col, c: 3=R,2=G,or 1=B
// Input Image:
SetLength(ImgIn2D,ImgIn.Height);
For rows := 0
to ImgIn.Height-1
do ImgIn2D[rows] := ImgIn.ScanLine[rows];
// Output Image:
SetLength(ImgOut2D,ImgOut.Height);
For rows := 0
to ImgOut.Height-1
do ImgOut2D[rows] := ImgOut.ScanLine[rows];
// Calculate filtered Image, i.e. convolution of Filter and ImgIn -> ImgOut
For rows := 0-FLowY
to ImgIn.Height-1-FHighY
do
For cols := 0-FLowX
to ImgIn.Width-1-FHighX
do
begin
// Perform Convolution
PixelSum := 0;
For y := FLowY
to FHighY
do
For x := FLowX
to FHighX
do
begin
PixelSum := PixelSum +
Filter[x-FLowX,y-FLowY]* ImgIn2D[rows+y]^[cols+x][1];
end;
Pixel := Round(PixelSum/weight) + ScaleShift;
ImgOut2D[rows]^[cols][1] := Pixel;
ImgOut2D[rows]^[cols][2] := Pixel;
ImgOut2D[rows]^[cols][3] := Pixel;
end;
end;
// ##############################################################
// Prozedur um finales Sobelbild aus Einzelbildern zu erzeugen
// ##############################################################
Procedure GenerateFinalSobel(ImgSx, ImgSy : TBitmap;
var ImgOut : TBitmap);
type TRGB =
Array[1..3]
of Byte;
PixArray =
Array[1..MaxInt
div SizeOf(TRGB)-1]
of TRGB;
PPixArray = ^PixArray;
PixArray2D =
Array of PPixArray;
var rows,cols : Integer;
// rows and cols in the image
ImgSx2D : PixArray2D;
// Access to ImgSx Pixels
ImgSy2D : PixArray2D;
// Access to ImgSy Pixels
ImgOut2D : PixArray2D;
// Access to ImgOut Pixels
Gx,Gy,Gf : Byte;
begin
// Build 2D Arrays via 'scanline' to speed up pixel operations
// access pixels: Img[a]^[b][c] , a=line, b=col, c: 3=R,2=G,or 1=B
// SobelX Image:
SetLength(ImgSx2D,ImgSx.Height);
For rows := 0
to ImgSx.Height-1
do ImgSx2D[rows] := ImgSx.ScanLine[rows];
// SobelY Image:
SetLength(ImgSy2D,ImgSy.Height);
For rows := 0
to ImgSy.Height-1
do ImgSy2D[rows] := ImgSy.ScanLine[rows];
// Output Image:
SetLength(ImgOut2D,ImgOut.Height);
For rows := 0
to ImgOut.Height-1
do ImgOut2D[rows] := ImgOut.ScanLine[rows];
// Perform G = sqrt(Gx*Gx + Gy*Gy);
for rows := 0
to ImgSx.Height-1
do
for cols := 0
to ImgSx.Width-1
do
begin
Gx := ImgSx2D[rows]^[cols][1];
Gy := ImgSy2D[rows]^[cols][1];
Gf := Round(sqrt(Abs(Gx*Gx)+Abs(Gy*Gy)));
ImgOut2D[rows]^[cols][1] := Gf;
ImgOut2D[rows]^[cols][2] := Gf;
ImgOut2D[rows]^[cols][3] := Gf;
end;
end;
// ##############################################################
// Prozedur um geglaettetes Graubild zu erzeugen
// ##############################################################
Procedure Smoothen(
var ImgIn, ImgOut : TBitmap);
var GaussFilter : TFilter;
SobelXFilter : TFilter;
ImgGray : TBitmap;
begin
//convert to Grayscale
ImgGray := TBitmap.Create;
ImgGray.Width := ImgIn.Width;
ImgGray.Height := ImgIn.Height;
ConvertToGrayScale(ImgIn, ImgGray);
//smoothen grayscale image
MakeSmoothenFilter(GaussFilter);
ApplyFilterOnImage(ImgGray, ImgOut, GaussFilter);
end;
// ##############################################################
// Prozedur fuer kompletten Sobel
// ##############################################################
Procedure Sobel(
var ImgIn, ImgOut : TBitmap);
var SobelX, SobelY : TFilter;
ImgSmooth, ImgSx, ImgSy : TBitmap;
begin
// create ImgSmooth
ImgSmooth := TBitmap.create;
ImgSmooth.width := ImgIn.width;
ImgSmooth.height := ImgIn.height;
// Smoothen Image
Smoothen(ImgIn, ImgSmooth);
// create ImgSx
ImgSx := TBitmap.create;
ImgSx.width := ImgIn.width;
ImgSx.height := ImgIn.height;
// create ImgSy
ImgSy := TBitmap.create;
ImgSy.width := ImgIn.width;
ImgSy.height := ImgIn.height;
// Make SobelX and SobelY Filter
MakeSobelFilterX(SobelX);
MakeSobelFilterY(SobelY);
// Apply Sobel Filter on ImgIn -> ImgSx and ImgSy
ApplyFilterOnImage(ImgSmooth, ImgSx, SobelX);
ApplyFilterOnImage(ImgSmooth, ImgSy, SobelY);
// ImgSx and ImgSy -> ImgOut
GenerateFinalSobel(ImgSx, ImgSy, ImgOut);
end;