Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Pixel gleicher Farbe zählen (https://www.delphipraxis.net/116050-pixel-gleicher-farbe-zaehlen.html)

dominikkv 22. Jun 2008 17:30


Pixel gleicher Farbe zählen
 
Hi

ich brauche von euch die schnellste Möglichkeit die Anzahl Pixel gleicher Farbe herauszufinden.
Ganz einfaches Beispiel:
Delphi-Quellcode:
type
  TColorArray = Array of TColor;
  TAnzahlArray = Array of Integer;

function CountColor(aBitmap: TBitmap; Colors: TColorArray ): TAnzahlArray ;
var
  I, J, K: Integer;
  Unten, Oben: Integer;
begin
  Unten := Low(Colors); // Um nacher nicht so oft die Funktionen zu benutzen
  Oben := High(Colors);

  SetLength(Result, Succ(Oben));

  for I := Unten to Oben do
    Result[I] := 0;

  for I := 0{oder 1?} to aBitmap.Width do
    for J := 0{oder 1?} to aBitmap.Height do
      for K := Unten to Oben do
        if aBitmap.Canvas.Pixels[I, J] = Color[K] then
          Inc(Result[K]);
end;

procedure bla;
var
  Colors: TColorArray;
  Anzahl: TAnzahlArray;
begin
  SetLength(Colors, 2);
  Colors[0] := clRed;
  Colors[1] := clBlue;
  Anzahl := CountColor(meinBitmap, Colors);
  showmessage(Format('%d Pixel sind Rot, %d Pixel sind Blau', [Anzahl[0], Anzahl[1]));
end;
Ich hoffe ihr versteht was ich meine. Ich bin mir sicher das geht noch schneller als bei meinem Beispiel...
Hat jemand von euch ne Idee?

mfg.Dominik

Apollonius 22. Jun 2008 17:35

Re: Pixel gleicher Farbe zählen
 
Nimm TBitmap.Scanline.

dominikkv 22. Jun 2008 17:58

Re: Pixel gleicher Farbe zählen
 
Zitat:

Zitat von Apollonius
Nimm TBitmap.Scanline.

Ich kenne ScanLine zwar nicht, habe mal aber hier im Forum gesucht und das ist dabei rausgekommen:
Delphi-Quellcode:
type
  TColorArray = Array of TColor;
  TAnzahlArray = Array of Integer;
  TLine = Array[1..3] of Byte;

function CountColor(aBitmap: TBitmap; Colors: TColorArray): TAnzahlArray;
var
  I, J, K: Integer;
  Unten, Oben: Integer;
  Line: ^TLine;
begin
  Unten := Low(Colors); // Um nacher nicht so oft die Funktionen zu benutzen
  Oben := High(Colors);

  SetLength(Result, Succ(Oben));

  for I := Unten to Oben do
    Result[I] := 0;

  for I := 0{oder 1?} to aBitmap.Height do
    begin
      Line := aBitmap.ScanLine[I];
      for J := 0{oder 1?} to aBitmap.Width do
        for K := Unten to Oben do
          if Line[J] = Colors[K] then
            Inc(Result[K]);
    end;
end;
Leider kommt in der Zeile
Delphi-Quellcode:
if Line[J] = Colors[K] then
eine AV. Wo ist mein Fehler?

Neutral General 22. Jun 2008 18:12

Re: Pixel gleicher Farbe zählen
 
Zitat:

Zitat von dominikkv
Leider kommt in der Zeile
Delphi-Quellcode:
if Line[J] = Colors[K] then
eine AV. Wo ist mein Fehler?

Mich wundert es, das der code überhautp compiliert...

Delphi-Quellcode:
if Line[J]{!}^{/!} = Colors[K] then // dereferenzieren nicht vergessen!
// ==>
if Array[1..3] of Byte = TColor then
// Das wird nichts oder?
Außerdem geht dein Array nur von 1-3 und nicht bis j (Das Bild wird wohl breiter als 3 Pixel sein ;) )

Line^ enthält den RGB wert, des ersten Pixels der gescannten Reihe.

Delphi-Quellcode:
Line^[1] = Rot
Line^[2] = Grün
Line^[3] = Blau
Wenn du jetzt den nächsten Pixel haben willst, musst du den Zeiger nach jedem j-Schleifendurchlauf inkrementieren:

Delphi-Quellcode:
inc(Line);
Der Vergleich wäre dann so möglich:

Delphi-Quellcode:
if RGB(line[1],line[2],line[3]) = Colors[k] then
Ich hoffe du hast es ungefähr verstanden ;)

Gruß
Neutral General

marabu 22. Jun 2008 18:24

Re: Pixel gleicher Farbe zählen
 
Hallo Dominik,

bitte auch den Gültigkeitsbereich der Laufvariablen (off by one) beachten.

Grüße vom marabu

dominikkv 22. Jun 2008 18:47

Re: Pixel gleicher Farbe zählen
 
hey danke für eure Antworten :mrgreen:

ich hab das nun so hingepfrimelt:
Delphi-Quellcode:
type
  TLine = TRGBTriple;

function TPaintEngine.CountColor(Colors: TColorArray): TAnzahlArray;
var
  I, J, K: Integer;
  Unten, Oben: Integer;
  Line: ^TLine;
begin
  Unten := Low(Colors); // Um nacher nicht so oft die Funktionen zu benutzen
  Oben := High(Colors);

  SetLength(Result, Succ(Oben));

  for I := Unten to Oben do
    Result[I] := 0;

  for I := 1 to fBuffer.Height - 1 do
    begin
      Line := fBuffer.ScanLine[I];
      for J := 1 to fBuffer.Width - 1 do
        begin
          for K := Unten to Oben do
            if RGB(line^.rgbtRed,line^.rgbtGreen,line^.rgbtBlue) = Colors[k] then
              Inc(Result[K]);
          Inc(Line);
        end;
    end;
end;
Ergebnis: braucht ca doppelt so viel Zeit wie die Methode über Pixels[I, J] und liefert zudem noch falsche Werte.

littleDave 22. Jun 2008 19:14

Re: Pixel gleicher Farbe zählen
 
Zitat:

Zitat von Neutral General
Delphi-Quellcode:
Line^[1] = Rot
Line^[2] = Grün
Line^[3] = Blau

*ZONK*

In Bitmaps werden die RGB-Werte anders herum gespeichert (BGR):

Delphi-Quellcode:
Line^[1] = Blau
Line^[2] = Grün
Line^[3] = Rot

Neutral General 22. Jun 2008 19:17

Re: Pixel gleicher Farbe zählen
 
Mist, ich war mir nichtmehr sicher :mrgreen:

dominikkv 22. Jun 2008 19:37

Re: Pixel gleicher Farbe zählen
 
Zitat:

Zitat von littleDave
In Bitmaps werden die RGB-Werte anders herum gespeichert (BGR):

Delphi-Quellcode:
Line^[1] = Blau
Line^[2] = Grün
Line^[3] = Rot

Trotzdem falsche Werte:
Delphi-Quellcode:
type
  TLine = array [1..3] of Byte;

function CountColor(aBitmap: TBitmap; Colors: TColorArray): TAnzahlArray;
var
  I, J, K: Integer;
  Unten, Oben: Integer;
  Line: ^TLine;
begin
  Unten := Low(Colors); // Um nacher nicht so oft die Funktionen zu benutzen
  Oben := High(Colors);

  SetLength(Result, Succ(Oben));

  for I := Unten to Oben do
    Result[I] := 0;

  for I := 1 to aBitmap.Height - 1 do
    begin
      Line := aBitmap.ScanLine[I];
      for J := 1 to aBitmap.Width - 1 do
        begin
          for K := Unten to Oben do
            if RGB(line^[3],line^[2],line^[1]) = Colors[k] then
              Inc(Result[K]);
          Inc(Line);
        end;
    end;
end;

Neutral General 22. Jun 2008 19:57

Re: Pixel gleicher Farbe zählen
 
Hi,

... Ich weiß nicht genau was bei dir schief läuft. Ich habe mal selbst eine Funktion geschrieben, die, soweit ich sie getestet habe, funktioniert.

Ich hoffe ich werde nicht erschlagen weil ich fertigen Code poste.

Delphi-Quellcode:
TIntArray = Array of Integer;

function CountColors(bmp: TBitmap; Colors: Array of TColor): TIntArray;
var i,j,k: Integer;
    old: TPixelformat;
    x: PRGBQuad;
    tmp: TColor;
begin
  SetLength(Result,Length(Colors));
  old := bmp.PixelFormat; // Pixelformat sichern
  bmp.PixelFormat := pf32Bit; //Mit 32-Bit Bitmaps gehts schneller
  for i := 0 to bmp.Height-1 do
  begin
    x := bmp.ScanLine[i];
    for j:= 0 to bmp.Width-1 do
    begin
      tmp := RGB(x^.rgbRed,x^.rgbGreen,x^.rgbBlue);
      for k := 0 to High(Colors) do
        if Colors[k] = tmp then
          inc(Result[k]);
      inc(x);
    end;
  end;
  bmp.PixelFormat := old; // Altes Pixelformat wiederherstellen
end;
Gruß
Neutral General


Alle Zeitangaben in WEZ +1. Es ist jetzt 22:13 Uhr.
Seite 1 von 2  1 2      

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz