Hallo Atlunch,
da der von mir verlinkte Code auf
DP bei mir nicht funktioniert und zudem etwas langsam ist, habe ich hier rasch einen "Sobelcode" geschrieben. [Man könnte den Code - auch ohne
asm - noch optimieren. Siehe Link "Sperarierbarkeit"
https://de.wikipedia.org/wiki/Sobel-Operator Für ein 1150x1150 Bild werden auf meiner langsamen Kiste nur 65ms benötigt.]
Dieses Beispiel funktioniert für Graustufenbilder. Den Vorprozess für "Farbbilder als Quelle", hast du ja sicher bereits.
Im Beispiel unten nutze ich für jedes Bild den ganzen Graustufenraum [0..255], indem ich mir den maximalen Gradient merke und diesem 255 zuweise (für den minimalen Wert nehme ich 0 an, da es praktisch in jedem Bild einen Punkt mit 8 Umgebungspixel mit Ableitung 0 gibt). Falls dein Grafiksystem mehr Grauwerte hergibt, dann kannst du den Code (siehe //normieren) leicht anpassen.
Wenn du mehrere "Sobelbilder" miteinander vergleichen möchtest, dann willst du pro Bild eventuell nicht den gesamten Graustufenraum ausnutzen [damit du Unterschiede erkennen kannst]. In diesem Fall müsstest du berechnen wie gross g^2 = gx^2+gy^2 werden kann. Ich glaube du kannst dir überlegen, dass zum Beispiel folgendes Umgebungspixel-Muster maximales g liefert:
Delphi-Quellcode:
Für gx:
S - W
S - W
S - W
Für gy:
S S S
- - -
W W W
Für den Punkt unten links könnte a=W oder a=S oder ein Zwischenwert gut sein, für den Punkt oben rechts könnte b=S oder b=W oder ein Zwischenwert optimal sein.
Du hast also eine Funktion g(a,b), welche du maximieren musst. Zwei Lösungen: 1. a=W und b=S und 2. a=S und b=W
Wenn ich richtig gerechnet habe ist max(g^2) = 1300500 oder max(g) = 1140.4.
Du müsstest als g normieren mittels norm(g) = g*256 div 1141, um Werte zwischen 0 und 255 zu erhalten.
Falls ich mich verrechnet habe, dann möge man diese Meldung für immer löschen
.
Hier der Sobelcode mit Ausnutzung des ganzen Graustufenbereichs
(Wie erwähnt könntest du auch gnorm := (grauwerte[x,y] shl 8) div 1141 verwenden.)
Delphi-Quellcode:
type
TRGB32 = packed record
B, G, R, A: Byte;
end;
TRGB32Array = packed array[0..0] of TRGB32;
PRGB32Array = ^TRGB32Array;
procedure SobelSL_GRAU( graubit , sobelbit : TBitMap );
var gnorm, ming, maxg, gw, g, gx, gy, x, y : integer;
Line_m1, line, line_p1 : PRGB32Array;
grauwerte : array of array of integer;
begin
ming := maxint;
maxg := 0;
setlength( grauwerte, graubit.Width, graubit.Height );
for y := 1 to graubit.height-2 do
begin
line_m1 := graubit.ScanLine[y-1];
line := graubit.ScanLine[y];
line_p1 := graubit.ScanLine[y+1];
for x := 1 to graubit.Width-2 do
begin
gx := -line_m1[x-1].R - 2*line[x-1].R - line_p1[x-1].R
+line_m1[x+1].R + 2*line[x+1].R + line_p1[x+1].R;
gy := -line_m1[x-1].R - 2*line_m1[x].R - line_m1[x+1].R
+line_p1[x-1].R + 2*line_p1[x].R + line_p1[x+1].R;
g := round(sqrt( gx*gx + gy*gy ));
if g > maxg then maxg := g;
if g < ming then ming := g;
grauwerte[x,y] := g;
end;
end;
// normieren:
for y := 1 to graubit.height-2 do
begin
line := sobelbit.ScanLine[y];
for x := 1 to graubit.Width-2 do
begin
gnorm := (grauwerte[x,y] shl 8) div maxg;
if gnorm=256 then gnorm := 255;
line[x].R := gnorm;
line[x].G := gnorm;
line[x].B := gnorm;
end;
end;
end;
procedure SobelFromFile( const fileQuelle, fileZiel : string );
var quelle, ziel : TBitMap;
begin
quelle := TBitMap.Create;
ziel := TBitMap.Create;
try
quelle.LoadFromFile( fileQuelle );
quelle.PixelFormat := pf32bit;
ziel.PixelFormat := pf32bit;
ziel.SetSize( quelle.Width, quelle.Height );
SobelSL_GRAU( quelle, ziel );
ziel.SaveToFile( fileZiel );
finally
quelle.Free;
ziel.Free;
end;
end;