Entwickler-Ecke

Multimedia / Grafik - Farbe in einem Bild finden


René R.Fo. - Do 24.12.09 22:27
Titel: Farbe in einem Bild finden
Hallo
Kurze Frage
Ich entschuldige mich im voraus schon wenn es so ein Thema schon gab (habe kein ähnliches gefunden)
oder wenn der Titel falsch ist (habe keine bessere Überschrift gefunden)

Ich habe eine WebCam deren Bild ich auf einem Button(1) Wieder gebe mit folgendem Code:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
const
  WM_CAP_DRIVER_CONNECT = WM_USER + 10;
  WM_CAP_EDIT_COPY = WM_USER + 30;
  WM_CAP_SET_PREVIEW = WM_USER + 50;
  WM_CAP_SET_OVERLAY = WM_USER + 51;
  WM_CAP_SET_PREVIEWRATE = WM_USER + 52;


  WM_CAP_DLG_VIDEOFORMAT          = WM_USER+41;
  WM_CAP_DLG_VIDEOSOURCE          = WM_USER+42;
  WM_CAP_DLG_VIDEOCOMPRESSION     = WM_USER+46;

function capCreateCaptureWindow(lpszWindowName: LPCSTR;
  dwStyle: DWORD;
  x, y,
  nWidth,
  nHeight: integer;
  hwndParent: HWND;
  nID: integer): HWND; stdcall;
  external 'AVICAP32.DLL' name 'capCreateCaptureWindowA';

procedure TForm1.Button1Click(Sender: TObject);
var handle:THandle;
begin
  handle := capCreateCaptureWindow('Video',ws_child+ws_visible, 0,
  0320240, Button1.Handle, 1);
  SendMessage(handle, WM_CAP_DRIVER_CONNECT, 00);  
  SendMessage(handle, WM_CAP_SET_PREVIEWRATE, 300);
  sendMessage(handle, WM_CAP_SET_OVERLAY, 10);
  SendMessage(handle, wm_cap_set_preview, 10);
  Application.ProcessMessages;
end;

Dies ist eigentlich auch schon mein gesamter Code.

Nun möchte ich überprüfen wo sich dort Ein grüner "Punkt" befindet, der Punkt ist ca. Datumgroß.
Ich habe allerdinks keine Ahnung wie das gehen soll.

Wenn es möglich ist mit einem Timer.
Ich verwende D7 und D5


Noob23 - Fr 25.12.09 09:01

Hallo,
so wie ich dich versanden habe willst du in einem gewissen Intervall überprüfen ob sich ein 'grüner Punk' vor deiner Webcam befindet. Ja das sollte gehen, allerdings kann ich mir unter 'Datumgroß' nichts vorstellen.

Eine eifache Lösung wäre, wie du schon gesagt hast, mit einem Timer einen temporären Snapshot in ein Timage zu machen und diesen dann nach deinem Punkt mit "if image1.Canvas.Pixels[x,y] = farbe then ..." abzusuchen.

Wenn dein Punkt größer ist, reicht es alle 3,4 Pixel weit nach dem Farbton zu suchen und falls gefunden noch die umliegenden zu überprüfen.

Da es aber höchstwarscheinlich ist, dass die Farbe nicht immer den gleichen Wert hat (Lichteinfall usw.), würde ich empfehlen, dass du einen Farbbereich anstatt nur einen Farbton nimmst.

Grüße
Noob23


René R.Fo. - Fr 25.12.09 11:07

user profile iconNoob23 hat folgendes geschrieben Zum zitierten Posting springen:
allerdings kann ich mir unter 'Datumgroß' nichts vorstellen.

Sorry das sollte Daumengroß heißen

Das geht leider nicht was du vorgeschlagen hast, denn das streitet sich mit meinem bisherigen Code
Ich habe bisher einen Button benutzt, der unterstützt kein Canvas und ein Imager unterstützt kein Handle und ein Panel wieder kein Canvas genauso wie ein Animate.

Ein Form unterstützt beides aber das Bild lässt sich nicht bewegen d.h. es ist immer oben links in der ecke und das finde ich blöd
gibt es fileicht noch eine andere Komponente mit der ich das machen kann???

user profile iconNoob23 hat folgendes geschrieben Zum zitierten Posting springen:
Da es aber höchstwarscheinlich ist, dass die Farbe nicht immer den gleichen Wert hat (Lichteinfall usw.), würde ich empfehlen, dass du einen Farbbereich anstatt nur einen Farbton nimmst.

Ok ich habe da was gefunden weis aber nicht wie ich das übernehmen soll:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
type
  TForm1 = class(TForm)
    SBarRed: TScrollBar;
    SBarGreen: TScrollBar;
    SBarBlue: TScrollBar;
    LblRed: TLabel;
    LblGreen: TLabel;
    LblBlue: TLabel;
    PnlRed: TPanel;
    PnlGreen: TPanel;
    PnlBlue: TPanel;
    PnlMix: TPanel;
    Lable1: TLabel;
    procedure SBarRedChange(Sender: TObject);

  procedure TForm1.SBarRedChange(Sender: TObject);
  begin
  PnlMix.Color := 65536*SBarBlue.Position + 256*SBarGreen.Position + SBarRed.Position;
  PnlRed.Color := SBarRed.Position;
  PnlGreen.Color := 256*SBarGreen.Position;
  PnlBlue.Color := 65536*SBarBlue.Position;
  end;


Noob23 - Fr 25.12.09 14:48

user profile iconRené R.Fo. hat folgendes geschrieben Zum zitierten Posting springen:

Ein Form unterstützt beides aber das Bild lässt sich nicht bewegen d.h. es ist immer oben links in der ecke und das finde ich blöd gibt es fileicht noch eine andere Komponente mit der ich das machen kann???

Nein so stimmt das nicht, du kannst wenn du die rot-makierten Stellen anpasst dein Bild im Form verschieben:

handle := capCreateCaptureWindow('Video',ws_child+ws_visible, 0,0, 320, 240, Button1.Handle, 1);

Zu deinem neuen Quelltext kann ich leider nichts sagen (hab das damals anders gelöst)...
wenns damit nicht klappen sollte, such ich mal meine alten Programme raus.

Grüße
Noob23


René R.Fo. - Fr 25.12.09 15:03

Zitat:
Zu deinem neuen Quelltext kann ich leider nichts sagen (hab das damals anders gelöst)...
wenns damit nicht klappen sollte, such ich mal meine alten Programme raus.
Ja wäre nett wenn du das machen würdest denn es
klappt überhaupt nicht

DANKE es klappt mit dem verschieben


Noob23 - Fr 25.12.09 15:21

Hab damals ein Abbild des ganzen Desktops gemacht und anschließend ausgewertet:

Delphi-Quelltext
1:
2:
3:
4:
5:
  var c:TCanvas;

  c := TCanvas.create;
  c.handle := GetWindowDC(GetDesktopWindow);
  result := GetGValue(getpixel(c.handle,x,y));


elegant ist alles andere...
gibt sicher eine bessere Lösung für dein Problem.


Delete - Fr 25.12.09 15:37

Habe ich das richtig verstanden, du stellst das Bild auf einer Schaltfläche dar? Ein Image hat kein Handle, aber der Canvas des Images sollte ein Handle bzw. Gerätekontext haben, den man nutzen kann.


René R.Fo. - Fr 25.12.09 16:24

user profile iconLuckie hat folgendes geschrieben Zum zitierten Posting springen:
Habe ich das richtig verstanden, du stellst das Bild auf einer Schaltfläche dar? Ein Image hat kein Handle, aber der Canvas des Images sollte ein Handle bzw. Gerätekontext haben, den man nutzen kann.

Ja hast du richtich verstanden aber klappt Leider nicht. Es startet zwar aber es passiert einfach nichts.
Noob23 mit deinem Code kann ich leider nichts anfangen ich weiß nicht wie und wo ich denn einsetzen soll.


FinnO - Fr 25.12.09 16:28

Delphi Treff hat ein entsprechendes Bitmaptutorial, in dem Scanline erklärt wird. Damit solltest du weitekommen, wenn du den Punkt finden willst. Tracken ist dann nocheinmal etwas anspruchsvoller.


René R.Fo. - Fr 25.12.09 16:52

user profile iconFinnO hat folgendes geschrieben Zum zitierten Posting springen:
Delphi Treff hat ein entsprechendes Bitmaptutorial, in dem Scanline erklärt wird. Damit solltest du weitekommen, wenn du den Punkt finden willst. Tracken ist dann nocheinmal etwas anspruchsvoller.

Wie soll ich das finden ohne IE-Seite?


René R.Fo. - Di 29.12.09 15:12

Ok ich glaube ich habe die IE-Seiten [http://www.delphi-treff.de/tutorials/grafik-und-spiele/bitmaps/] die du meintest aber ich kann damit leider nicht wirklich etwas anfangen denn da geht es ja darum Standbilder zu Bearbeiten.
Gibt es sonst noch Möglichkeiten??? :?: :?: :?:


René R.Fo. - So 17.01.10 12:02

Schade das keiner eine Möglichkeit kennt :(
Noob23 zu deiner 1. Antwort wollte ich gerne wissen, wie ich denn diesen Farbereich schaffen soll, habe keinerlei Ahnung davon.
Das mit dem bild im Image geht jetzt, habe also die Möglichkeit mit Canvas zu arbeiten.
Vielleicht kann mir ja jetz jemand damit helfen.


Flamefire - So 17.01.10 13:38

Ist doch einfach: Scanline!
Wie schon erwähnt nimmst du in einem Timer o.ä. eine Snapshot des aktuellen Bildes.
Mit deinen Worten: Du kopierst den aktuellen Frame des Videos in ein Standbild.
Und das kannst du dann entsprechend auswerten.

Und Farbbereich: Sagen wir du willst: #00FF00 (RGB-->00=Rot FF=Grün 00=Blau)
Jetzt wird es das pure Grün nicht geben, also akzeptierst du in jedem Bestandteil eine Abweichung von z.b. 55
also würde auch #55FF00 noch erkannt werden, oder #34DF21
Rest ist Fleißarbeit-->Google zur Not


FinnO - So 17.01.10 16:41

na ja, man könnte die Toleranz einfacher behandeln indem man auf

R < Toleranz
G > 255 - Toleranz
B < Toleranz

überprüft...

oder halt in HSV-Umrechnen


Reinhard Kern - Mo 18.01.10 11:59

user profile iconRené R.Fo. hat folgendes geschrieben Zum zitierten Posting springen:
Ok ich glaube ich habe die IE-Seiten [http://www.delphi-treff.de/tutorials/grafik-und-spiele/bitmaps/] die du meintest aber ich kann damit leider nicht wirklich etwas anfangen denn da geht es ja darum Standbilder zu Bearbeiten.


Hallo,

was denn sonst? Selbst wenn du dir eine professionelle Bildverarbeitung kaufst, die macht auch nichts anderes als ein Bild in den Speicher zu laden (und damit einzufrieren) und dann zu untersuchen. Und dann das nächste aktuelle usw.

Gruss Reinhard


ffgorcky - Mo 18.01.10 15:10

Entschuldigung, ich weiß jetzt leider nicht, ob Du eventuell das selbe möchtest, wie user profile iconviolinenspieler1000 im Thread
Delphi-Forum.de » Algorithmen, Optimierung und Assembler » roten Punkt finden [http://www.delphi-forum.de/viewtopic.php?t=93373&start=0&postorder=asc&highlight=pixel+farbe+bild]

- Also wenn ich das Problem richtig verstanden habe, dann möchtet Ihr beide doch das Bild nach einem Pixel mit einer bestimmten Farbe (also in Deinem Fall Grün, im anderen Rot) durchsuchen.

Ich weiß jetzt leider auch nicht, wie man denn so ein Bild per Schleife pixelweise durchläuft und dabei nach einer bestimmten Farbe (für reines Rot meine ich z.B. 255/0/0) ausschau hält.


FinnO - Mo 18.01.10 17:53

wurde Scanline nicht schon n-Mal erwähnt? Google hilft.


René R.Fo. - Fr 05.02.10 14:45

ffgorcky
DANKE das war ein volltreffer thx