|
Registriert seit: 29. Sep 2013 152 Beiträge |
#5
Hallo Medium,
danke fuer die Antwort. Dass man aus den x und y gradienten das endgueltige bild mittels G=sqrt(Gx*Gx + Gy*Gy) berechnet ist mir klar. Es geht mir um eine vernuenftige Darstellung der einzelnen Bilder Gx und Gy und da muessen alle Werte positiv sein. Ich habe immer noch das Problem, dass sowohl die einzelnen Bilder als auch das endgueltige Sobel Bild keinerlei Kannten zeigen. Wahrscheinlich habe ich irgendwo einen Fehler in der Implementierung. Hier mein Code:
Delphi-Quellcode:
Hier eine Prozedur zum Aufruf des Ganzen:// ############################################################## // 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;
Delphi-Quellcode:
Die Umwandlung in ein Graubild und das Glaetten mittels Gaussfilter klappt wunderbar. Die einzelnen Sobelbilder sehen nicht aus wie Bilder in denen horizontale oder vertikale Kannten betont sind sondern eher wie helle oder dunkle Bilder mit stark veraendertem Gammawert. Im finalen Sobelbild ist quasi nichts zu sehen, d.h. mehr oder weniger einfarbige Flaeche.
procedure TForm1.Button2Click(Sender: TObject);
var ImgIn, ImgOut : TBitmap; begin ImgIn := TBitmap.Create; ImgOut := TBitmap.Create; ImgIn.LoadFromFile('Book.bmp'); ImgOut.Width := ImgIn.Width; ImgOut.Height := ImgIn.Height; //Smoothen(ImgIn, ImgOut); Sobel(ImgIn, ImgOut); Image3.Picture.Bitmap := ImgOut; end; Gutelo Edit: Code ist mit Lazarus erstellt, sollte aber 1:1 auf Delphi laufen Geändert von Gutelo (27. Jul 2014 um 17:41 Uhr) |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |