Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi Farbe von Bildschirminhalt ermitteln ? (https://www.delphipraxis.net/136507-farbe-von-bildschirminhalt-ermitteln.html)

Blamaster 1. Jul 2009 23:18


Farbe von Bildschirminhalt ermitteln ?
 
Hi,

ich habe beriets rausgefunden wie man die Farbe eines bestimmten Pixel auf dem Bildschirm ermitteln kann.

Ich bin gerade dabei ein Art Ambilight zu programmieren, welches mir die überweigende Farbe in einem bestimmten Bereich des Bildschirms ausgeben soll.

Meine Fragen dazu ist nun wie kann man am besten eine Berechnung der überweigenden Farbe realisieren ?

Um es nochmal ein wenig vorstellbarer zu umschreiben. Ich nehme mal eine Fläche von 500x500px in der Bildschirmmitte die darin enthaltenen Pixel sollen nun ausgewertet werden und die am häufigsten vorkommende Farbe soll ausgegeben werden. Dabei reicht allerdings nicht die Aussage Rot, Grün, Blau, usw. überwiegt, sondern es sollte schon ein genauer Farbwert sein.

Ich hoffe mir kann da jemand auf die Sprünge helfen.

mfg Yannic

Aphton 2. Jul 2009 01:10

Re: Farbe von Bildschirminhalt ermitteln ?
 
Ich würd immer für jeden Pixel, welcher noch nicht in einer (def.) Liste existiert, einen neuen Eintrag erstellen und für jeden Pixel, der schon besteht, würde ich den Counter des Eintrages erhöhen

Programmiertechnisch würde das so aussehen:

Delphi-Quellcode:
PPixelCounter = ^TPixelCounter;
TPixelCounter = record
  Pixel: TColor;
  Count: Cardinal;
  Prev, Next: PPixelCounter;
end;

TPixelContainer = class
public
  property List: PPixelCounter Read FList Write SetList;
  procedure Add( Pixel: TColor );
  function GetLastItem(): PPixelContainer;
  function SearchPixel( Pixel: TColor ): PPixelContainer;
end;

// Add erweitert die doppelt verkettete Liste um ein neues Element;
// SearchPixel geht die ganze Liste durch und schaut, ob Pixel enthalten ist und liefert die Adresse des Eintrages zurück
Konkrete Vorgehensweise:
Code:
1. Bildpunkt vom Display/Desktop ermitteln
2. Per SearchPixel prüfen, ob der Pixel schon vorhanden ist (NIL?)
3. Falls es vorhanden ist, dann den Rückgabewert von SearchPixel dereferenzieren und dessen Count Wert um 1 erhöhen
4. Ansonsten einen neuen Eintrag erstellen
So ausführlich hab ich noch niemandem geholfen :P
Hoffe ich konnt dir helfen

MfG :D

Medium 2. Jul 2009 03:03

Re: Farbe von Bildschirminhalt ermitteln ?
 
Ein naiver Ansatz wäre es, einfach die Durchschnittsfarbe für den Bereich zu ermitteln. Etwas geschickter würde das evtl. noch, wenn man die Pixel die näher zum Rand liegen dabei stärker gewichtet. Was aber eine recht gute Näherung sein dürfte, stützt sich auf Aphtons Idee, welche letztlich ein sog. Histogramm beschreibt - in dem Fall eines über die ganzen Farben. Wenn man von diesem dann noch die obersten ~10% mittelt, dürfte das recht gut werden.

Histogramme sind in der Grafikverarbeitung recht üblich, meist aber für R, G und B separat. Dabei ist dann die Verwaltung der Datenstruktur weit einfacher und schneller, falls das o.g. Methode ausschließt. Ein Array[0..2, 0..255] of Cardinal, 1. Dimension 0-2 für RGB, und 2. Dimension für den Wert den die Farbanteile je annehmen können.
Mal Pseudocode wie man so ein Histogramm aufbaut:
Delphi-Quellcode:
for y := 0 to Bild.Height-1 do
begin
  for x := 0 to Bild.Width-1 do
  begin
    inc(Array[0, Bild.Pixel[x, y].R]);
    inc(Array[1, Bild.Pixel[x, y].G]);
    inc(Array[2, Bild.Pixel[x, y].B]);
  end;
end;
Der Wert von z.B. "Array[1, 128]" gibt dann also an, wie viele Pixel den Grünanteil 128 haben. Aus diesen 3 Listen kann man nun wieder die obersten 10% mitteln, und daraus eine Farbe zusammensetzen.


Eine weitere Variante wäre es das ganze von RGB nach HSV zu konvertieren. Dann nimmt man sich nur die Hue-Werte, für die Saturation und Value einen Mindestwert überschreiten, da diese dann die meiste Farbigkeit und Leuchtkraft beitragen. Aus diesen ermittelten Hue-Werten erstellt man wiederum ein Histogramm, uuuuund mittelt einen Teil am oberen Ende.
Hierbei erhält man allerdings nur eine Farbe, keine Indikation für die Helligkeit. Diese würde ich dann aus den Randpixeln gemittelt herleiten, um einen guten Anschluss an den Bildrand zu bekommen.


Ich habe selbst noch keine der Dinge getestet, und es ist vermutlich sinnvoll alles Mögliche in diese Richtung mal auszuprogrammieren und zu begutachten, da hier ja das subjektive Empfinden den größten Faktor bei der Beurteilung der Güte stellt - und das ist ja bekanntlich nicht immer mit rechnerisch sinnvollen Verfahren gleichzusetzen :)
Auch spielt eine große Rolle ob die Anzeige vom Bild und dem Ambilight durch das selbe Medium (yeah) geschieht oder nicht. Wenn du z.B. um deinen Monitor verteilte RGB-LEDs ansteuerst, kann es durchaus nötig sein die Farben (bzw. die Farbkanäle) noch weiter zu verarbeiten um einen guten und ähnlichen Farbeindruck herzustellen. (Anhebung von Blau z.B., was bei LEDs meist eine geringere Leuchtkraft hat als Rot und Grün.)

Interessante Sache! Ich fühle mich fast schon genötigt mal was ähnliches in Angriff zu nehmen :)

Blamaster 2. Jul 2009 11:34

Re: Farbe von Bildschirminhalt ermitteln ?
 
Hi,

Danke schonmal für die Hilfe.

Ich glaube die Methode von Aphton iost zu resourcen fressend. Ein "scan" sollte ca. alle 25ms erfolgen können.

@ Medium

das sieht ganz interessant aus. Allerdings habe ich da gerade ein Verständnisproblem.

inc(Array[0, Bild.Pixel[x, y].R]);

was wir denn da inkrementiert ?

mfg Yannic

Ah ich glaube jetzt versteh ich es doch. Array[0, Bild.Pixel[x, y].R], Bild.Pixel[x, y].R gibt den Farbwert des aktuellen Pixels (0 - 255) an. Wenn der Wert nun mal angenommen 122 ist wird der Arraysatz Array[0, 122] um 1 richtig ?

Blamaster 2. Jul 2009 13:44

Re: Farbe von Bildschirminhalt ermitteln ?
 
Hi,

ich habe gerade mal testweise etwas zusammengeschustert.

Delphi-Quellcode:
procedure TForm1.Button3Click(Sender: TObject);
var
  Color: TColor;
  x, y, i, high_r, high_g, high_b, end_r, end_g, end_b: integer;
  ColorArray: array[0..2, 0..255] of cardinal;
begin

  for y := 200 to 210 do
  begin
    for x := 200 to 210 do
    begin
      Color := GetDesktopColor(x, y);
      inc(ColorArray[0, GetRValue(Color)]);
      inc(ColorArray[1, GetGValue(Color)]);
      inc(ColorArray[2, GetBValue(Color)]);
    end;
  end;

  for i := 0 to 255 do
  begin
    if ColorArray[0, i] > high_r then
    begin
      high_r := ColorArray[0, i];
      end_r := i;
    end;
    if ColorArray[1, i] > high_g then
    begin
      high_g := ColorArray[1, i];
      end_g := i;
    end;
    if ColorArray[2, i] > high_b then
    begin
      high_b := ColorArray[2, i];
      end_b := i;
    end;
  end;

  ShowMessage(IntToStr(end_r));
  ShowMessage(IntToStr(end_g));
  ShowMessage(IntToStr(end_b));

  JvPanel2.Color := RGB(end_r, end_g, end_b);
end;
Da kommen dann bei den 3 ShowMessage flasche Werte raus. Beispiel Hintergrund vom Desktop komplett rot gestellt. Nun kommen bei GetDesktopColor(x, y); auch das richtige raus, wenn ich mir die Farbe anzeigen lasse 255,0,0. Wenn das Programm nun allerdings zu

ShowMessage(IntToStr(end_r));
ShowMessage(IntToStr(end_g));
ShowMessage(IntToStr(end_b));

kommt, dann bekomme ich da bei Rot 251,213,253. Habe ich da etwas übersehen ?

mfg Yannic

turboPASCAL 2. Jul 2009 14:27

Re: Farbe von Bildschirminhalt ermitteln ?
 
Oder so was ?

Delphi-Quellcode:
function TForm1.GetBitmapAmbiColor(inBmp: TBitmap): TColor;
type
  TRGBArray = array [Word] of TRGBTRIPLE;
  pRGBArray= ^TRGBArray;
var
  x, y: integer;
  LineScan: pRGBArray;
  AmbiCol: record
    aB, aG, aR: int64;
  end;
  counts: cardinal;
begin
  if inBmp.PixelFormat <> pf24Bit then
    inBmp.PixelFormat := pf24Bit;

  AmbiCol.aR := 0;
  AmbiCol.aG := 0;
  AmbiCol.aB := 0;

  counts := 0;

  for y := 0 to inBmp.Height-1 do  // Farbe im Drurchschnitt per Bitmap
  begin
    LineScan := inBmp.Scanline[y];
    for x := 0 to inBmp.Width-1 do
    begin
      inc(AmbiCol.aR, LineScan[x*3].rgbtRed);
      inc(AmbiCol.aG, LineScan[x*3+1].rgbtGreen);
      inc(AmbiCol.aB, LineScan[x*3+2].rgbtBlue);

      inc(counts);
    end;
  end;

  AmbiCol.aR := AmbiCol.aR div counts;
  AmbiCol.aG := AmbiCol.aG div counts;
  AmbiCol.aB := AmbiCol.aB div counts;

  Result := RGB(AmbiCol.aR , AmbiCol.aG , AmbiCol.aB );
end;

Medium 2. Jul 2009 14:30

Re: Farbe von Bildschirminhalt ermitteln ?
 
Jub, du musst high_*, end_* und das Array natürlich alle mit 0 initialisieren. So stehen da zunächst einmal zufälige Werte von Anfang an drin - sind ja lokale Variablen.

Edit: Redbox, aber trotzdem. Antwort bezieht sich auf den vorletzten Beitrag.

Reinhard Kern 2. Jul 2009 14:52

Re: Farbe von Bildschirminhalt ermitteln ?
 
Zitat:

Zitat von Aphton
Ich würd immer für jeden Pixel, welcher noch nicht in einer (def.) Liste existiert, einen neuen Eintrag erstellen und für jeden Pixel, der schon besteht, würde ich den Counter des Eintrages erhöhen
...

Hallo,

falsch ist das nicht - aber ich weise mal drauf hin, dass heutige Bildschirme i.a. 16 Mio Farben darstellen. Und auch wenn er 500 x 500 Pixel betrachtet, ist es bei einem realen Foto immer noch gut möglich, 100000 verschiedene Farben zu finden. M.a.W. du brauchst 100000 Counter.

Man könnte ja eine Toleranz definieren und so die Zahl verringern, aber der Fragesteller wollte ausdrücklich eine exakte Farbe, wofür auch immer - ich halte das eher für abwegig, denn bei der Fotografie eines Waldes ist die beherrschende Farbe nach intuitivem Verständnis grün, aber in seinem Sinn können es hunderte oder tausende verschiedene Grüns sein.

Gruss Reinhard

Blamaster 2. Jul 2009 15:04

Re: Farbe von Bildschirminhalt ermitteln ?
 
Hi,

dann habe ich mich etwas unklar ausgedrückt :(

Es muss natürlich nicht eine exakte Farbe sein, es reicht natürlich ein Näherungswert ich meine damit eher das z.B. Orange nicht als Rot gewertet werden soll, oder Lila als Blau :)

mfg Yannic

Blamaster 2. Jul 2009 16:22

Re: Farbe von Bildschirminhalt ermitteln ?
 
Hi,

der Code funktioniert jetzt soweit. Allerdings ist das ganze wie vermutet etwas langsam gerade bei großen scan bereichen.

Deswegen hatte ich mal weitergesucht und bin recht oft auf eine G32 oder Graphic 32 unit gestoßen, die wohl funktionen beinhalten soll mit denen das ganze sehr schnell und einfach geht.

Kennt jemand die Unit bzw. weiß mit welcher Funktion es schnell gehen soll ?

Mein aktueller Stand ist folgender:

Delphi-Quellcode:
procedure TForm1.Timer3Timer(Sender: TObject);
var
  Color: TColor;
  Screenshot: TBitmap32;
  x, y, i, high_r, high_g, high_b, end_r, end_g, end_b: integer;
  ColorArray: array[0..2, 0..255] of cardinal;
begin
  high_r := 0;
  high_g := 0;
  high_b := 0;
  end_r := 0;
  end_g := 0;
  end_b := 0;

  for i := 0 to 255 do
  begin
    ColorArray[0, i] := 0;
    ColorArray[1, i] := 0;
    ColorArray[2, i] := 0;
  end;

  Screenshot := TBitmap32.Create;
  FormularScreenShot(Screenshot, GetDesktopWindow);

  for y := 700 to 1000 do
  begin
    for x := 200 to 500 do
    begin
      Color := Screenshot.Pixel[x, y];
      inc(ColorArray[0, GetRValue(Color)]);
      inc(ColorArray[1, GetGValue(Color)]);
      inc(ColorArray[2, GetBValue(Color)]);
    end;
  end;

  for i := 0 to 255 do
  begin
    if ColorArray[0, i] > high_r then
    begin
      high_r := ColorArray[0, i];
      end_r := i;
    end;
    if ColorArray[1, i] > high_g then
    begin
      high_g := ColorArray[1, i];
      end_g := i;
    end;
    if ColorArray[2, i] > high_b then
    begin
      high_b := ColorArray[2, i];
      end_b := i;
    end;
  end;
  Screenshot.Free;
  JvPanel2.Color := RGB(end_r, end_g, end_b);
end;
Ich speichere jetzt erstmal das Dektopbild in ein Bitmap um dann später daraus die Farben zu lesen.

Mit dem Code oben indem ich nun versucht habe die G32 zu verwenden, gibt es probleme mit der Farbausgabe (farbe stimmt nicht blau anstelle von rot) und schneller als die alte Methode ist das auch nicht.

Wenn man im obigen die Screenshot: TBitmap32; wieder gegen TBitmap tauscht stimmt die angezeigte Farbe auch wieder, allerdings auch bei einer zu langsamen Geschwindigkeit.

Jemand eine Idee wie ich mit der G32 schneller zum laufen bekomme ?

mfg Yannic

Edit1. Das Farbproblem habe ich gerade gelöst hatte nicht bedacht das ich TColor32 erstmal wieder in TColor zurückwandeln muss.

Medium 2. Jul 2009 17:34

Re: Farbe von Bildschirminhalt ermitteln ?
 
RGB wird unter Windows meist in der Reihenfolge BGR gespeichert. Du kommst ohne Konvertierungen aus, wenn du statt TColor TColor32 nimmst, und statt Get*Value die Funktionen RedComponent usw. der G32 nimmst. Die G32 ist in der Tat mit das schnellste beim Pixelzugriff. Bist du sicher, dass die Screenshotfunktion nicht der Engpass ist?
Ich würde mir da lieber den DC vom Desktop abholen (GetDC(0)), und aus diesem auch wirklich immer nur die Stücke die ich brauche in ein passend großes Bitmap werfen. Das spart eine Menge Pixel aus der Mitte, und ist je nach dem wie die Screenshot-Funktion arbeitet auch von sich aus schon schneller.
Letztlich musst du aber auch sehen, dass es durchaus einige Arbeit ist diese Menge an Pixeln durchzuackern. Alle 25ms ist das ne ganz schön happige Angelegenheit.

Blamaster 2. Jul 2009 18:59

Re: Farbe von Bildschirminhalt ermitteln ?
 
Hi,

das hier ist die Screenshot Funktion:

Delphi-Quellcode:
function FormularScreenShot(Bmp: TBitmap32; h: hWnd): Boolean;
var
  Rec: TRect;
  iWidth, iHeight: Integer;
begin
  with Bmp do try
    GetWindowRect(h, Rec);

    iWidth := Rec.Right - Rec.Left;
    iHeight := Rec.Bottom - Rec.Top;

    Width := iWidth;
    Height := iHeight;

    BitBlt(Canvas.Handle, 0, 0, iWidth, iHeight, GetWindowDC(h), 0, 0, SRCCOPY);

    Result := True;
  finally
    ReleaseDC(h, GetWindowDC(h));
  end;
end;
Kann es daran liegen ?

Wenn es an der nicht liegt gibt es dann noch eine andere möglichkeit das ganze zu relisieren ? Denn um das Atomlight vernünftig wirken zu lassen, sollte schon alle 25ms ein scan erfolgen.

mfg Yannic

Apollonius 2. Jul 2009 19:02

Re: Farbe von Bildschirminhalt ermitteln ?
 
Eine wahrlich interessante Vorstellung zum Freigegeben von Gerätekontexten...

Mithrandir 2. Jul 2009 19:10

Re: Farbe von Bildschirminhalt ermitteln ?
 
Wie genau soll das Ambilight denn später arbeiten? Hast du dir schon Gedanken um die Hardware gemacht?

Blamaster 2. Jul 2009 19:35

Re: Farbe von Bildschirminhalt ermitteln ?
 
Hi,

den code für den Screenshot habe ich nicht selber entworfen sonder nfertig übernommen. Ob das nun eine gute oder schlechte Lösung ist kann ich mit meiner Kenntnis momentan nicht sagen.

Die Hardware für das Ambilight steht schon. Das Programm übergibt die RGB Werte über die Rs232 Schnitstelle an einen Microcontroller, dieser setzt dann die Farben.

mfg Yannic

Mithrandir 2. Jul 2009 19:44

Re: Farbe von Bildschirminhalt ermitteln ?
 
Nö, nicht unbedingt. Wenn deine Idee dazu steht, und die HW funktioniert, ist es ja ok. Was Apollonius mit seinem Post sagen wollte, habe ich allerdings nicht so ganz verstanden...

Btw, ich halte 25ms für übertrieben. 4 mal die Sekunde (alle 250 ms) sollte imho reichen.

Blamaster 2. Jul 2009 20:01

Re: Farbe von Bildschirminhalt ermitteln ?
 
Hi,

ich habe nun nochmal einen Direktvergleich gemacht.

1.) Einmal das ganze mit tbitmap, tcolor und Bitmap.Canvas.Pixels[x,y];
2.) Dann das ganze mit tbitmap32, tcolor32 und Bitmap.Pixel[x,y];

Der rest ist identisch bei einer Timer Zeit von 250ms habe ich bei Variante 1 eine Cpu Last von 11%, bei Variante 2 eine Cpu Last von 55% wie kann da sein ?

mfg Yannic

Blamaster 2. Jul 2009 22:47

Re: Farbe von Bildschirminhalt ermitteln ?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe jetzt nochmal ein kleines Programm geschrieben, welches das Problem verdeutlicht und den Code für das ambilight enthält.

Ich kann da definitiv zwischen der gr32 Methode und der normalen keine Verbesserung feststellen.

mfg Yannic

Reinhard Kern 2. Jul 2009 22:49

Re: Farbe von Bildschirminhalt ermitteln ?
 
Zitat:

Zitat von Blamaster
Hi,

der Code funktioniert jetzt soweit.
...

Hallo,

da steckt meiner Ansicht nach ein massiver Denkfehler drin: du berechnest das Vorkommen der R, G und B-Werte getrennt, aber das hat praktisch keine Aussagekraft über Farben. Ein Grünwert von 128 kann in vielen verschiedenen Farben vorkommen (um genau zu sein, in 65536). Nur zusammen definieren RGB eine Farbe, und die Farbe ist nun mal ein 24-Bit-Wert. Da kann man sich nicht drum herum tricksen, indem man 3 x 8-Bit-Werte getrennt verarbeitet. Genausogut könnte man die Häufigkeit von Buchstaben bestimmen wollen, indem man die beiden 4bit-Nibbel getrennt zählt, weil man dann nur 32 Zähler braucht anstatt 256 - tolle Einsparung, aber was sagt das Ergebnis über die Buchstabenverteilung aus? Die Ergebnisse sind also ohne jeden Wert.

Erfahrungsgemäss wird dieser Einwand völlig ignoriert, weil die Erkenntnis unangenehm wäre.

Gruss Reinhard

Blamaster 3. Jul 2009 08:56

Re: Farbe von Bildschirminhalt ermitteln ?
 
@ Reinhard Kern

von der Seite habe ich das noch garnicht betrachtet.

Allerdings möchte ich mich erstmal nicht um die Ausbesserung davon kümmern sondern das Programm überhaupt zum "schnellen" laufen bekommen.

mfg Yannic

Medium 3. Jul 2009 10:57

Re: Farbe von Bildschirminhalt ermitteln ?
 
Ich hab nun mal ein wenig rumprobiert, allerdings quick & dirty, ohne auge auf die geschwindigkeit, und auch erstmal nur in C# (weil ich grad keine Lust hatte mein XP System zu booten :)). Ich bin dabei den Weg über HSV gegangen, und mit folgender Taktik habe ich bisher ganz nette Ergebnisse gehabt:

Pre 1) Farbstreifen an den Bildrändern, nicht weiter unterteilt.
Pre 2) Für einen Streifen betrachte 1/8 Breite bzw. Höhe des angrenzenden Bildteiles.

A) Laufe durch alle Pixel eines Bereiches:
1) Umwandlung in HSV
2) Wenn S und V einen Mindestwert überschreitet, Eintrag in einer Liste an der Position von H um 1 erhöhen (bedingtes Hue-Histogramm erstellen)
3) Unabhängig davon S und V aufkummulieren (um später einen einfachen Durchschitt draus zu berechnen)

B) Laufe durch das Hue-Histogramm:
1) Finde den höchten Eintrag
2) Wenn der Eintrag > 5% der Gesamtpixelanzahl des Bereiches ausmacht, Aufkummulieren des H-Wertes - Zähler mitführen wie viele Werte man da zusammenrechnet.
3) Wenn 2 zutrifft, diesen Eintrag löschen und bei 1) weitermachen
(So lange Einträge aufsummieren bis kein Wert mehr >5% Beitrag hat. Sind meist nicht mehr als 2-5 Farbwerte.)

C) Erzeugen der Durchschnitte
1) H-Summe / Anzahl der Hue-Einträge mit >5% Beitrag an der Pixelmasse
2) V-Summe / Gesamtpixel des Bereiches
3) S-Summe / Gesamtpixel des Bereiches

D) Zurückwandeln in RGB


Die Mindestwerte aus A2 sind hier recht entscheident, gute Ergebnisse hab ich mit S>75% und H>30% erzielt. Da ist aber mächtig Spielraum. Ebenso verhält es sich mit den 5% aus B2. Ich hatte auch mit 10% und 2% durchaus noch sinnvolle Ergebnisse. Hier lohnt es sich eine größere Menge sehr unterschiedlicher Bilder anzuschauen, und diese 3 Werte so zu wählen dass sie möglichst immer gut aussehen. Ist halt Fummelei.
Der Vorteil hier ist, dass wenn 2 sehr unterschiedliche Farben dominieren ein Mittelwert aus dem Spektrum, und damit ein "guter" Verlaufswert entsteht. Bei Mittlung im RGB Raum läuft man nämlich schnell Gefahr sehr stark im Grau zu landen.

Ich hoffe dass ich am WE dazu komme das mal in Delphi auszuprobieren, und dann auch auf Geschwindigkeit zu achten. Das einzig wirklich eklige ist hierbei diese Hue-Liste, bzw. die Maxima zu finden. Einfach sortieren ist da nicht, da die Indizes ja auch einen Nutzwert enthalten und erhalten bleiben müssten. Mal schauen ob sich da nicht noch eine geschicktere Datenstruktur finden lässt.

Blamaster 3. Jul 2009 16:33

Re: Farbe von Bildschirminhalt ermitteln ?
 
Hi,

hört sich ja schonmal super an :shock:

An Hue bzw. den HSV Farbraum hatte ich auch schon gedacht komme da aber irgendwie nicht richtig hinter die Berechnungsmethode.

Meine Gedanken die ich mir gemacht hatte, bevor du das mit dem HSV Farbraum geschrieben hattest war folgender. (Bei der RGB Methode)

1.) Farbe von Pixel ermitteln.
2.) Farbe von Pixel auf schwarz/weiß/grau untersuchen. (Wenn R and G and B < 50 or R and G and B > 200)
3.) Wenn 2 für Pixel zutrifft zähler erhöhen.

4.) Wenn 2. nicht zutrifft R,G,B in ein Array schreiben.

5.) Wenn alle Pixel durchlaufen, dann Zählerwert von 3. mit anzahl der Einträge im Array aus 4. vergleichen.
- Wenn pixelzahl Schwarz/weiß/grau höher als Farbwerte im Array das ganze verwerfen und entweder Schwarz oder Weiß setzen
- Wenn Farbwerte in Array mehr als Schwarz/Weiß/Grau weiter zu Schritt 6.

6.) Nun die Werte im array für R, G, B nehmen jeweils addieren und durch Anzahl der Einträge im Array teilen um den durchschnitt zu bekommen.

Ob das ganze so funktionieren könnte weiß ich allerdings nicht.

mfg Yannic

hathor 3. Jul 2009 19:00

Re: Farbe von Bildschirminhalt ermitteln ?
 
Zum Thema AMBILIGHT:
.
http://www2.philips.de/entspannter_f...enresuemee.pdf
.
http://www.consumer.philips.com/cons.../discover.html

Medium 4. Jul 2009 03:18

Re: Farbe von Bildschirminhalt ermitteln ?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hmhmhmmmm, die HSV Variante erzeugt zwar bei Standbildern oft ganz nette Ergebnisse, bei Filmen dagegen neigt sie leider doch recht oft zu einigem "Blinken". Das Problem sind dabei vor allem sehr dunkle und sehr helle Bereiche, da diese ja nicht immer Farblos sind. Daher tragen sie einen viel zu großen Anteil an Farbigkeit bei. Eventuell lässt sich da noch das ein oder andere brauchbar verrechnen, was aber am Ende bleibt ist dennoch ein nicht zu knapper Rechenaufwand. (Der allerdings sehr stark von der "Dicke" der Bildränder die man einbezieht abhängt.)

Anbei mein Testprogrämmchen. Zum Kompilieren wird die Graphics32 und das DSPack benötigt, erstellt ist das ganze mit Delphi 7. (EXE liegt aber bei) Achtung: Nach start lässt sich nur ein Mal ein Video abspielen. Um ein neues/weiteres zu starten muss das Programm beendet und wieder gestartet werden - sauber auf Start/Stop-Events zu reagieren war mir jetzt zu anstrengend (und nicht das Ziel). Speicherlecks sollten aber nicht auftreten.
Es lassen sich alle Videoformate öffnen die das DSPack verkraftet, was in aller Regel alle sind für die man Codecs installiert hat. Der Open-Dialog kommt wegen Faulheit ungefiltert daher. Generell möge man mir mannigfaltige Verletzung von u.a. OOP Richtlinien vergeben. Es ist 4 Uhr, das Bier war lecker, und nach ein paar Monaten C# war es einfach mal wieder eine Freude ein paar Pointer schubsen zu können :).

Fazit: Brauchbarer Ansatz, der aber in der Praxis schwächen hat. Insbesondere wird die Verarbeitungsgeschwindigkeit noch ein echtes Thema! Mal die Tage ein wenig mit RGB basiertem Krams basteln... ein Framework ist ja nun da =)

Blamaster 4. Jul 2009 11:34

Re: Farbe von Bildschirminhalt ermitteln ?
 
Hi,

ich habe gerade mal über die exe gestartet und ein Video geladen. Das Video wird auch abgespielt allerdings bleiben die Ränder die ganze Zeit weiß, woran kann das liegen ?

mfg Yannic

Mithrandir 4. Jul 2009 11:43

Re: Farbe von Bildschirminhalt ermitteln ?
 
Beweg mal einen der Regler... ;)

Blamaster 4. Jul 2009 11:54

Re: Farbe von Bildschirminhalt ermitteln ?
 
Hi,

auch das bringt nichts. Die TForm1.SampleGrabber1Buffer wird ja nichtmal aufgerufen.

mfg Yannic

Medium 4. Jul 2009 13:37

Re: Farbe von Bildschirminhalt ermitteln ?
 
Arbeitest du unter Vista bzw. Win7? Es kann nämlich sein dass darunter das DSPack nicht mehr so 100%ig funktioniert. Bis XP ist es zumindest auf der Webseite angegeben, und das letzte Update stammt auch aus einer Zeit wo es Vista nicht mal gab.

Blamaster 4. Jul 2009 14:33

Re: Farbe von Bildschirminhalt ermitteln ?
 
Hi,

nein ich nutze WinXP.

Muss außerhalb der kompo noch etwas anderes installiert werden ?

mfg Yannic

Medium 4. Jul 2009 15:03

Re: Farbe von Bildschirminhalt ermitteln ?
 
Hmm, eigentlich nicht. EXE und selbst kompiliertes zeigen das selbe Symptom? Eventuell liegt es ja an dem Video. Ich hatte es wenn ich mich nicht irre mit einem einfachen MPEG1 getestet. Ich hatte auch mal was von Problemen mit DivX gelesen was das Grabbing angeht. Weil wenn auch die fertige EXE nicht klappt, muss es ja entweder am Video selbst, oder dem Codec liegen :gruebel:

Blamaster 4. Jul 2009 15:57

Re: Farbe von Bildschirminhalt ermitteln ?
 
Hm schade habe es gerade mal mit anderen Videos versucht. Manche lassen sich garnicht laden. (programm hängt sich auf)
Bei anderen die angezeigt werden bleiben die Farbfelder weiß.

Einen unterschied zwischen fertiger und selbstcompilierter exe konnte ich nicht feststellen.

Kannst du das programm evtl. auf einen Art Screenshot Methode umbauen, dann ist dabei das Abspielmedium ja egal.

mfg Yannic

Blamaster 5. Jul 2009 12:49

Re: Farbe von Bildschirminhalt ermitteln ?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hi,

ich bin jetzt auch nochmal etwas weitergekommen :)

Im Angehängten Programm gibt es 2 Optionen einmal Scan1 und Scan2. Scan 1 beinhaltet das ganze am Anfang angetestete Prinzip.

Scan 2 funktioniert nach dem Prinzip welches ich eine Seite zuvor angedacht habe.

Währe super wenn mal jemand das programm bei sich austesten könnte. Meiner meinung nach liefer die Scan 2 Methode schon ein super Ergebnis.
(Die von mir angesprochene prozentuale Berücksichtigung des Schwarz/Weiß anteils habe ich noch nicht umgestezt, scheint aber auch garnicht nötig).

Die Geschwindigkeit liegt jetzt zumindest bei mir auch in einem angenehmen Rahmen.

Hat jemand dazu vielleicht noch Verbesserungsvorschläge ?

mfg Yannic

Edit. Das Programm scannt momentan nicht die Seitenränder sondern den Monitor Mittelpunkt.

Blamaster 19. Jul 2009 13:26

Re: Farbe von Bildschirminhalt ermitteln ?
 
So,

nach einigem geteste möchte ich nun noch eine Zusatzfunktion verbauen.

Momentan Scanne ich ja die Pixel wie folgt:

Delphi-Quellcode:
for y := 0 to Screenshot.Height - 1 do
  begin
    for x := 0 to Screenshot.Width - 1 do
    begin
      Color := WinColor(Screenshot.Pixel[x, y]);
      ColorArray_r[pixelcount] := GetRValue(Color);
      ColorArray_g[pixelcount] := GetGValue(Color);
      ColorArray_b[pixelcount] := GetBValue(Color);
      inc(pixelcount);
    end;
  end;
Problem ist nun das wenn der Screenshot beispielsweise 150 x 150 px groß ist 22500 Pixel "gescannt" werden und das ist etwas zu viel.

Deswegen wollte ich nun folgendes vorgeben. 1. Größe des Screenshots 2. Anzahl der zu "scannenden" Pixel, diese sollen dann gleichmäßig über den Screenshot verteilt werden.

Nun habe ich dabei aber ein gewaltiges Schleifenproblem.
Wie kann ich eine Schleife erstellen die die eine variable Anzahl an punkten gleichmäßig in einem in der größe variablen Quadrat scannt ?

Um überhaupt erstmal weniger pixel zu scannen hatte ich folgedes versucht:

Delphi-Quellcode:
  while y <= Screenshot.Height - 1 do
  begin
    y := y + 5;
    for x := 0 to Screenshot.Width - 1 do
    begin
      inc(pixelcount);
      Color := WinColor(Screenshot.Pixel[x, y]);

      ColorArray_r[pixelcount] := GetRValue(Color);
      ColorArray_g[pixelcount] := GetGValue(Color);
      ColorArray_b[pixelcount] := GetBValue(Color);
    end;
  end;
So wollte ich jetzt nur jede 5. Reihe der y Achse scannen was allerings zu einem Exception Error führt.

Ich hoffe jemand kann behilflich sein :)

mfg Yannic


Alle Zeitangaben in WEZ +1. Es ist jetzt 06:08 Uhr.

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