Zwei Bilder miteinander vergleichen...(Diskussion)



  • Hallo,
    da ich jetzt ein wenig mit TBitmap experimentiert habe, werde ich den generellen Ablauf ein wenig ändern. Zum jetzigen Vorgehen: Jetzt mache ich ein Bild mit der Cam, speichere es als .bmp auf der HD ab, vergleiche das vorherige mit dem neusten Bild und lasse mir den Unterschied des RGB-Wertes anzeigen. Da die Bilder der Cam ja erst auf der HD gespeichert werden und anschl. miteinander verglichen werden, dauert mir dieses Vorgehen zu lange.

    Der neue Ansatz währe wie folgt: Es wird das aktuelle Bild der Cam in einem TBitmap-Objekt gespeichert und der RGB-Wert dieses Bildes errechnet. Diesen Wert speichere ich in einer VAR. Nun nehme ich das nächste (aktuelle) Bild der Cam und errechne abermals den RGB-Wert. Anschließend vergleiche ich den Wert aus der VAR mit dem aktuellen RGB-Wert.

    Das sollte doch vom Ablauf her schneller gehen, oder?
    Gruß
    Torsten



  • Hallo

    Deine erste Variante ist vor allem deshalb so langsam, weil du auf Festplatte speicherst. Für die reine Berechnung ist das natürlich überflüssig. Hol die Bilder von der Kamera gleich in den Arbeitsspeicher ohne Umwege über die Festplatte.

    Deine zweite Variante zeigt, das du schon selber auf die Idee gekommen bist.

    bis bald
    akari



  • Ich hätte da einen ganz anderen vorschlag der auch auf eine andere Programmiersprache abziehlt.
    Man könnte einen Videostream einrichten und das video in Maximierter From über den Bildschirm sausen lassen quasie ein livebild. So Nun kommt ein einfach gestalteter Autohotkey script zum einsatz nun Scannen wir das Bild an Bestimmten Punkten (damit es schneller geht) nach einen Farbwert mit erhöter Variation ab und wenn etwas aus den rahmen fällt wird alarm in irgenteiner form gegeben von mir aus mit einer MessageBox
    hier mal ein beispiel für einen Bildpunkt
    (Der code ist eig einfach falls dennoch niemand in versteht einfach hier in den Tread reinschreiben)

    SetBatchLines 60    <-<-Das heist er soll 60Zeilen je Sekunde abarbeiten
    loop ,              <-<-Anfang einer unendlichen Schleife
    {
    PixelSearch , Px , Py , 100 , 100 , 100 , 100 , 0xFFFFFF , 20 , fast <-<-Pixelsearch , Egal , Egal , koo,rdi,nat,en, Farbe , Farbvariation , egal
    if Errorlevel  <-<- Wenn scann nicht weis ist
    {
    MsgBox , 0 , Fehler , Ein Fremdkörper ist im Bild , -1 <-<- Mache eine MessageBox	
    }
    }
    


  • genau das ist auch mein Lösungsansatz. Ich filme erst einmal das Bild des rieselnden Zuckers ohne Fremdkörper. Dieser Farbwert (RGB-Wert) wird quasi als Referezwert betrachtet. Man muss aber dann mit sicherheit auch einen gewissen "Rauschwert/Grenzwert" dazu rechnen.
    Wenn man dann also den Rieselzucker filmt, die RGB-Werte ständig ermittelt und mit dem Referenzwert vergleicht und dann eine Verunreinigung (zB Schraube) mit erfasst wird, ändert sich der RGB-Wert ja enorm. Und dann muss das Programm Alarm schlagen.

    Soweit der Plan. Ich werde jetzt erst einmal das ständige lesen, berechnen und vergleichen des Cam-Streams umsetzen....

    Gruß Torsten



  • Hallo,
    ich habe nun einen Weg über das Clipboard gefunden. Leider hakt es an einer Stelle. Und zwar komme ich nicht weiter beim lesen einer VAR vom Typ PByteArray.

    Hier mal mein Code:

    PByteArray z1;
    Graphics::TBitmap *bmp = new Graphics::TBitmap();
    Cap->CopyToClipBoard();
    bmp->LoadFromClipboardFormat(CF_BITMAP, Clipboard()->GetAsHandle(CF_BITMAP), 0);
    
    z1=(PByteArray)bmp->ScanLine [50];
    
    Label1->Caption = z1; //Hier der Fehler ?
    
    Clipboard()->Clear();
    delete bmp;
    

    Wie und womit kann ich denn auf den Wert von z1 zugreifen???

    Danke im vorraus



  • Programmierer, die das Clipboard zur Kompensation eigener Unzulänglichkeiten mißbrauchen, gehören geteert und gefedert.



  • torsten_156 schrieb:

    Wie und womit kann ich denn auf den Wert von z1 zugreifen???

    Dein z1 ist ein Zeiger auf ein Array von Triple-Bytes einer ganzen Pixelzeile (ScanLine) des Bitmap.

    PRGBTriple z1;
       z1  = (PRGBTriple)bmp->ScanLine[50];  // 51. Zeile/Reihe des bmp
       // Beispiel Auswertung eines Pixel dieser Line auf Farbwerte R, G, B
       int r =  z1[0].rgbtRed;   // 1. Pixel Rot-Wert
       int g =  z1[0].rgbtGreen;
       int b =  z1[0].rgbtBlue;
    

    Wenn du alle Pixel dieser einen Zeile auswerten willst(oder das kompletter bmp) nimmst du eine
    Schleife/n.

    audacia schrieb:

    Programmierer, die das Clipboard zur Kompensation eigener Unzulänglichkeiten mißbrauchen, gehören geteert und gefedert.

    😃

    Auf den Clipboardspeicher würde ich auch nicht zugreifen; ich denke mal, das ist fertiger Code aus dem
    Netz. 😉

    mfg
    kpeter



  • Wie kommt man denn auf einen RGB-Wert des Bildes? Jeder Pixel hat einen eigenen RGB-Wert. Ein normales 16mio Farben Foto hat effektiv im Schnitt 120.000 verschiedene Farben. Vielleicht solltest du ersteinmal ein Einzelbild des Zuckers analysieren. Es werden hunderte Farben sein, wenn man nur das Weiß des Zuckers betrachtet. Ich denke du brauchst einen gemittelten Wert der Farbe "Zucker" und einen gemittelten Wert der Farbe "Schraube". Dann brauchst du was womit du intelligent die Farbdistanzen der Farben ermittelst. Werden hierbei gewisse Schwellen überschritten, gibt es Alarm.

    Im Übrigen muss vielleicht so etwas wie ein Elektromagnet die Schraube in Echtzeit herausfiltern, sonst muss man die gesamte Produktion anhalten, was teuer wird etc.

    MfG



  • PRGBTriple z1;
       z1  = (PRGBTriple)bmp->ScanLine[50];  // 51. Zeile/Reihe des bmp
       // Beispiel Auswertung eines Pixel dieser Line auf Farbwerte R, G, B
       int r =  z1[0].rgbtRed;   // 1. Pixel Rot-Wert
       int g =  z1[0].rgbtGreen;
       int b =  z1[0].rgbtBlue;
    

    Vielen Dank dafür!

    audacia schrieb:

    ... ich denke mal, das ist fertiger Code aus dem Netz. 😉

    mfg
    kpeter

    Eben nicht! Das einzige, was ich aus dem Netz habe ist die Klasse und deren Funktionen, die die Ansteuerung der WebCam regeln. Diese Klasse bringt die Funktion mit, das Bild in's Clipboard zu kopieren. Um im ersten Schritt erst mal die einzelnen Werte dieses Bildes zu bekommen, reicht mir das völlig!
    Wenn dieser Schritt dann erledigt ist, werde ich mich anschl. darum kümmern, den Stream direkt auszulesen.

    Schönen Gruß
    Torsten



  • Das Ganze ist aber nur eine Übungsaufgabe o.ä., oder?
    Denn für einen produktiven Einsatz in der Lebensmittelindustrie, bei dem es potentiell um Gesundheitsschäden für Endverbraucher gehen kann, scheint mir das Ganze doch etwas (nicht abwertend gemeint!) unprofessionell.
    Hast du z.B. schon mal kalkuliert, wie schnell der Zucker maximal am Objektiv vorbeiströmen darf, damit du bei den gerade 30 Bildern/s einer Webcam ganz sicher nichts verpasst?



  • Hallo Jansen,

    ich kann Dich beruhigen. Es ist nicht für die Lebensmittelindustrie sondern für die Chemische Industrie 😉
    Hier handelt es sich nicht um eine Übungsaufgabe, sondern schon um die Vorbereitung für den produktiven Einsatz. Dabei geht es auch nicht um Zucker sondern um Verschuppte Harze.
    Wenn ich mit meiner Umsetzung der Lösung und anschl. Testen in einem Technikum vorran komme, sollte es für den produktiven Einsatz in der Fabrik auch nicht bei einer WebCam und Laptop bleiben. Ich möchte erst einmal prüfen, ob meine Idee in die Tat umzusetzen ist. Und wenn ja, wird das Ergebnis einigen hohen Herren vorgestellt und wenn's positiv angekommen ist, wird auch die entsprechende Hardware angeschafft [hoffe ich].

    Schönen Gruß
    Torsten



  • Hi,

    Dann hoffe ich, dass dieses Produkt transparent ist.
    Nach Murphys Gesetz rutscht an der der Kamera/Sichtfenster gegenüberliegenden Rohrwandung eine Schraube M10 Länge 200 mm durch. Wo auch immer die herkommt...



  • Gut zu wissen, dass ich auch weiterhin bedenkenlos Zucker kaufen kann. 🙂

    torsten_156 schrieb:

    [...]wenn's positiv angekommen ist, wird auch die entsprechende Hardware angeschafft [hoffe ich]

    Dann achte jetzt schon streng darauf, in deinem Programm Bedienoberfläche, Kameraansteuerung, Bildanalyse etc. logisch voneinander zu trennen, damit du später nur die relevanten Teile ändern musst. Ausserdem schadet es sicher nicht, sich vorab schonmal über passende Hardware und deren Besonderheiten zu informieren, um dein Programm generell daraufhin vorbereiten zu können.

    kpeter schrieb:

    [...] an der der Kamera/Sichtfenster gegenüberliegenden Rohrwandung [...]

    Man sollte doch hoffen, dass das Material für die Sichtprüfung über eine Art Rieselfläche läuft, oder?



  • ...das Produkt läuft über ein Rüttelblech und fällt am Ende dieses Bleches in einen 25kg bzw. 500kg Sack. Der freie Fall dieser Schuppen soll dann durch ein Plexiglasfenster gefilmt werden. Der Hintergrund kann so auch mit einem weißen Tuch/Anstrich/Folie verkleidet werden. So würde man dann doch einen Referenzwert zum Vergleichen erhalten können.

    Gruß
    Torsten



  • Hallo zusammen,
    jetzt geht's 😋 Ich habe die Prozedur erst einmal in einen Timer gepackt, der alle 250ms startet. Es werden auch erst einmal die RGB-Werte angezeigt. Hier mal der Code:

    void __fastcall TForm1::Timer1Timer(TObject *Sender)
    {
    PRGBTriple z1;
    const int size = 120;  //max 120 Pixel, da Cam nicht größer
    int result =0;
    AnsiString sresult;
    
    Graphics::TBitmap *bmp = new Graphics::TBitmap();
    bmp->SetSize(size,size);
    Cap->CopyToClipBoard();
    bmp->LoadFromClipboardFormat(CF_BITMAP, Clipboard()->GetAsHandle(CF_BITMAP), 0);
    
    for (int x = 0; x < size; x++) {
    	z1  = (PRGBTriple)bmp->ScanLine[x];
    	// Beispiel Auswertung eines Pixel dieser Line auf Farbwerte R, G, B
    	int r =  z1[x].rgbtRed;
    	int g =  z1[x].rgbtGreen;
    	int b =  z1[x].rgbtBlue;
    	result += (r+g+b);
    	}
    
    sresult = IntToStr(result);
    PB1->Caption = sresult;
    PB1->UserValue = result;
    Clipboard()->Clear();
    delete bmp;
    
    }
    

    Von der Performance geht es noch. Jetzt geht es an's testen. Also den Zucker mal vor einem weißen Blatt Papier laufen lassen und schauen. Dann auch mal mit nem Stück Bonbonpapier dazwischen.

    Was ich noch ändern werde ist folgendes:
    - Referenzbild speichern
    - RGB-Wert mit Referenzwert vergleichen
    - die Prozedur mal in einen Thread auslagern

    Mal schauen was daraus wird...

    Schönen Gruß
    Torsten



  • Hallo,

    ist das so beabsichtigt?

    Mit deinem Code gehst du 120 mal durchs bmp, und zwar in jeder Zeile nur ein Pixel. Diagonal sozusagen.
    Und die RGB-Werte addierst du am Ende. 😕



  • Sorry torsten,

    ich schließe mich kpeter an... 😕

    und bei deinem bisherigen Kenntnisstand wirst du mindestens noch ein halbes Jahr programmieren müssen, ehe du etwas Funktionierendes vorzeigen kannst.

    Außerdem bringt dir die Addition der RGB-Werte gar nichts. Um Farbwerte effektiv vergleichen zu können, müßtest du das HSV (bzw. HSB) - Farbmodell verwenden (s. http://de.wikipedia.org/wiki/HSV-Farbraum)
    Natürlich kostet die Umrechnung dann auch wieder etwas Zeit...



  • Hallo,

    Von den Möglichkeiten, die es mit Mitteln der WinApi gibt, um an den Videostream resp.
    an die Frame-Pakete heranzukommen, bist du dabei, die ungünstigste für deinen Plan einzusetzen.

    Einen Timer brauchst du nicht. Vergiss auch die Clipboardfunktionen 😉 .

    Die FrameCallbackProc ist das Stichwort.

    Frohes Fest
    :xmas1:

    kpeter


Anmelden zum Antworten