Einzelnen Beitrag anzeigen

Michael II

Registriert seit: 1. Dez 2012
Ort: CH BE Eriswil
760 Beiträge
 
Delphi 11 Alexandria
 
#3

AW: Sobel Normalisierungsschritt

  Alt 8. Mai 2017, 23:03
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;
Michael Gasser

Geändert von Michael II ( 9. Mai 2017 um 01:10 Uhr)
  Mit Zitat antworten Zitat