Einzelnen Beitrag anzeigen

skybibo

Registriert seit: 23. Jun 2008
Ort: NRW
23 Beiträge
 
Delphi 12 Athens
 
#41

AW: Durchschnittsfarbe eines Bitmap "schnell" ermitteln

  Alt 11. Mai 2021, 20:45
Hallo, ich will mal noch meine Version ins Spiel bringen.

Die Funktion GetAverageColor1 wäre die exakte Berechnung. Wenn das Ergebnis nicht 100% exakt sein muss, kann die Funktion GetAverageColor2 verwendet werden.
Delphi-Quellcode:
Type
  TRgb = packed record
    b:Byte;
    g:Byte;
    r:Byte;
    d:Byte;
  end;

  TRgbLine = array[0..MaxInt div 4 - 1] of TRgb;
  PRgbLine = ^ TRgbLine;

function GetAverageColor1(bmp:TBitmap):TRgb;
  var
    r,g,b:Integer;
    RgbLine: PRgbLine;
    p:Integer;
    PixelCount: Integer;
begin
  PixelCount := bmp.Width * bmp.Height;
  r := 0;
  g := 0;
  b := 0;
  rgbline := bmp.ScanLine[bmp.Height - 1];
  for p := 0 to PixelCount -1 do
  begin
    r := r + RgbLine[p].r;
    g := g + RgbLine[p].g;
    b := b + RgbLine[p].b;
  end;
  Result.r := r div PixelCount;
  Result.g := g div PixelCount;
  Result.b := b div PixelCount;
end;

function GetAverageColor2(bmp:TBitmap;DivFaktor:Integer):TRgb;
  var
    r,g,b:Integer;
    RgbLine: PRgbLine;
    p:Integer;
    PixelCount: Integer;
    i:Integer;
begin
  PixelCount := bmp.Width * bmp.Height;
  r := 0;
  g := 0;
  b := 0;
  rgbline := bmp.ScanLine[bmp.Height - 1];
  for i := 1 to PixelCount div DivFaktor do
  begin
    p := Random(PixelCount);
    r := r + RgbLine[p].r;
    g := g + RgbLine[p].g;
    b := b + RgbLine[p].b;
  end;
  Result.r := r div (PixelCount div DivFaktor);
  Result.g := g div (PixelCount div DivFaktor);
  Result.b := b div (PixelCount div DivFaktor);
end;
Ich habe absichtlich auf bereits vorhandene Strukturen (TRgbQuad) die bereits definiert sind verzichtet. Auch auf notwendige try .. finally .. end Strukturen habe ich zur Vereinfachung verzichtet. Der Code läßt sich natürlich noch optimieren, mir geht es hier in erster Linie um das Prinzip.

Die Funktion GetAverageColor2 ist bei einem DivFaktor = 1000 um den Faktor 60 schneller als die Funktion GetAverageColor1.

Das Prinzip beruht grundsätzlich auf die Tatsache, dass man nicht jeden Pixel auswerten muss. Ich habe das Ganze mit 10 verschiedenen Bildern durchrechnen lassen. In der folgenden Tabelle ist die erste Spalte das exakte Ergebnis. Die 2. Spalte bei einen DivFaktor = 1000 und die 3. Spalte bei einem DivFaktor von 10000.

Code:
 R   G   B       R   G   B       R   G   B
131 102  86     130 102  86     135 105  89
101  89  79     102  89  79     101  89  78
113 118  82     114 119  83     113 118  83
 78  81  61      79  82  62      75  76  59
133 119  99     132 118  99     133 119  98
129 141 155     129 141 154     130 142 154
135 145 157     135 145 157     136 145 157
127 123 122     127 123 123     125 121 120
151 146 138     151 146 138     149 144 136
124 117 106     124 117 106     122 115 105
Bernd
  Mit Zitat antworten Zitat