Zwei Bilder miteinander vergleichen...(Diskussion)



  • Hallo,
    ich habe da folgende Idee im Kopf und möchte mit Euch gern einige Denkansätze diskutieren. Folgende Situation:
    Man stelle sich vor, dass ein bestimmtes Medium (nehmen wir mal Zucker) an einer Scheibe vorbei rieselt. Diesen rieselnden Zucker möchte ich mit einer WebCam filmen. Wenn nun im Zucker eine Schraube mit vorbei rieselt, sollte das Programm Alarm geben.

    Mein erster Lösungsansatz: Ich filme den Zucker und mache ein Bild davon. Dieses Bild nehme ich als Referezbild. Wenn nun das Programm den Rieselzucker filmt, sollte so oft wie möglich ein Bild mit der WebCam geschossen werden und dieses Bild mit dem Referezbild verglichen werden. Wenn es da keinen großen Unterschied gibt, passiert nichts weiter.
    Wenn nun in diesem Rieselzucker aber eine Schraube oder ähnliches mit durch das Bild huscht und die Cam dieses Bild mit dem Referezbild vergleicht, ergibt sich da ja ein gewisser Unterschied. Wenn dieser Unterschied nun definiert wird und beim Abgleich der Bilder einen bestimmten Wert übersteigt, gibt das Programm Alarm.

    Soweit so gut, aber wie könnte man dieses Projekt nun umsetzen? Das Ansteuern einer WebCam incl. Bild machen/speichern ist kein Problem. Aber der Rest...

    Wie sieht es denn da z.B. mit der Performance des Programms aus? Kann ich denn 25 Bilder/sec machen und vergleichen? Schafft das ein normaler PC? usw...

    Freue mich schon auf diese Diskussion..

    Gruß Torsten



  • zAlso ungefähr mit http://lichttools.sourceforge.net/images/screen-java-windows.png vergleichen.
    Fällt der Kram langsam genug, daß es weniger als eine 25-stel Sekunde dauert, daß der Kram durch das Bild fällt? Kannste ja messen oder einfach ausrechnen.
    Rein theoretisch würde ich eher an eine Zeilenkamera denken. Aber egal, die sind zu teuer.
    Es gibt bei vielen Webcams so ne Zusatzsoftware, die Alarmanlage spielt und ungefähr das macht, was Du wünscht. Aber bei mir waren das immer nur 5 Bilder pro Sekunde oder um den Dreh.
    Aber Du hast Glück, denke ich. Du mußt ja nur den Zucker vor einem weißen Hintergrund rieseln lassen, nötigenfalls bautechnisch was dran drehen, und den Schrauben sagen, daß sie nicht so weiß wie Zucker sein dürfen. Schrauben erkennt man dann einfach an Pixels, die dunkler als xc0c0c0 (oder so) sind. Und dann rechnest Du aus, welche Auflösung du brauchst, um auch die kleinste anzunehmende Schraube satt auf vier Pixel zu bekommen. Wenn dazu 160x120 reicht, geht auch die schlechteste Kamera ab wie Schmidts Katze.
    Das da will zum Beispiel 30Hz bei 640x480 machen.
    Aber die Bilder könnten als MJPEG reinsausen, wie packt man das aus? Ich kann mir nicht vorstellen, daß 30 Bilderchen pro Sekunde ein Problem für einen PC sind.
    Würde es sich lohnen, zusätzlich einen zweiten PC und eine Infrarotkamera zu nehmen (also eine Webcam, der man das IR-Filterscheibchen rausoperiert hat)?



  • ...du meinst also, die gemachten Bilder Pixel für Pixel auslesen und mit dem Wert "weiß" vergleichen. Da eine Schraube ja nicht weiß ist, müsste beim Vergleich des Pixels auf weiß ja ein Unterschied entstehen, oder?



  • torsten_156 schrieb:

    ...du meinst also, die gemachten Bilder Pixel für Pixel auslesen und mit dem Wert "weiß" vergleichen. Da eine Schraube ja nicht weiß ist, müsste beim Vergleich des Pixels auf weiß ja ein Unterschied entstehen, oder?

    zRichtig.



  • Aber gibt es außer der Optik nicht bessere Methoden? Vielleicht den Zucker auf ein schräges Prallblech fallen lassen, und wenn es vernehmlich "Plonk" macht, war da eine Schraube. Na, ich denke für große Schrauben gibt es unzählige Methoden, ein fetter Magnet, Gegenwind, Sieb usw.
    Für kleiste Schrauben und allgemein gemeine Metallspäne fällt mir nur ein, den Kram durch eine Spule fallen lassen und schauen, wie sich der Wechselstrom ändert. Gibt es sogar zum Beispiel hier http://www.bauert.ch/html/schuttgut.html fertig zusammengelötet, kostet aber bestimmt vieltausend Geld. Aber warum nicht selber basteln? Das scheint mir kein Hexenwerk zu sein.



  • OT

    volkard schrieb:

    zRichtig.

    Das hat dir offensichtlich gefallen. 😉



  • Hallo zusammen,
    so, jetzt habe ich mal ein wenig probiert. Ich vergleiche zwei Bilder pixelweise und errechne jeweils den r+g+b-Wert jeden Bildes. Anschließend lasse ich mir die Differenz anzeigen. Guckst Du...

    //solange wie breit
    while(x != maxW){
    		r = GetRValue(Image1->Canvas->Pixels[x][y]);
    		g = GetGValue(Image1->Canvas->Pixels[x][y]);
    		b = GetBValue(Image1->Canvas->Pixels[x][y]);
    		Pic1Value += (r+g+b);
    		Label1->Caption = IntToStr(Pic1Value);
    
    		r = GetRValue(Image2->Canvas->Pixels[x][y]);
    		g = GetGValue(Image2->Canvas->Pixels[x][y]);
    		b = GetBValue(Image2->Canvas->Pixels[x][y]);
    		Pic2Value += (r+g+b);
    		Label2->Caption = IntToStr(Pic2Value);
    
    		x++;
    
    				//solange hoch ist
    				while(y != maxH && x==maxW){
    				y++;
    				x=0;
    				ProgressBar1->Position = y;
    				ProgressBar2->Position = y;
    				break;
    				}
    		}
    //berechne Unterschied
    int difference = 0;
    difference = Pic1Value - Pic2Value;
    Label4->Caption = IntToStr(difference);
    

    Jetzt habe ich leider das Problem, dass dieser Prozess bei einer Bildgröße von 340x280 Pixel so ca. 5sec. dauert. Diese Performance reicht mir nicht! Ich will schneller 😃

    Was kann ich da machen???

    Gruß Torsten



  • Das Stichwort hierbei ist "ScanLine" der Bitmap. Damit liest du eine ganze Pixelzeile des Bildes ein und kannst dann in einer Schleife da durch rasen!

    Das Problem ist denke ich das wenn du ein und das selbe Zuckerkörnchen 10 mal aufnimmst, wahrscheinlich 7 verschiedene Farbwerte dafür bekommst. Das liegt zum einen am Licht zur Zeit der Aufnahme, und anderen äusseren Faktoren. Zum anderen daran was der Sensor der Kamera daraus macht, und dass ist nicht immer die gleiche Farbe.

    Man könnte sich einer Farbpalette mit weniger Farben bedienen, sagen wir 16 Farben für weiss. Es gibt dann API-Funktionen die dir zu einem Color-Wert einen am besten passenden Color-Wert aus dieser Palette liefern. Aber dann hast du immer noch verschiedene "weiss". Man müsste dann evtl einen Algorithmus schreiben, der verschiedene Farbdistanzen berücksichtig etc.

    Die Arbeit mit Farbpaletten ist schon uralt, wird aber noch unterstützt von Windows.

    MfG



  • In inneren Schleifen wilsst Du Ausgaben machen.
    Label2->Caption = IntToStr(Pic2Value);
    Das killt die Performache.
    Gib nur am Ende des Bildes aus, ob die Schraube drin war.
    Wenn Du echt 340x280=95200 mal eine Caption geändert hast in nur 5 Sekunden, dann chapeau an Deinen Rechner.



  • Hallo,

    int02h schrieb:

    Das Stichwort hierbei ist "ScanLine" der Bitmap...

    Ich wollte nun "ScanLine" verwenden und musste lesen, dass diese Funktion wohl nur bei einem TBitmap geht. Da ich den C++Builder2010 nutze habe ich diese Komponente nicht gefunden?!

    Und nu???



  • TBitmap ist eine Klasse, keine Komponente

    Graphics::TBitmap* tbmp = new Graphics::TBitmap();
    


  • ok, ich habe leider nur null Idee, wie ich nun ScanLine auf dieses Objekt anwenden kann 😕

    Schönen Gruß
    Torsten



  • Hallo

    TBitmap hat die Eigenschaft ScanLine, die wie ein Array von Zeilen funktioniert. Steht alles in der Builder-Hilfe.

    bis bald
    akari



  • Wenn deine Vorrichtung im großen Stil eingesetzt werden soll, dann würde ich beides nehmen. Die optische Auswertung und ein starkes Magnet. Wenn jemand eine Schraube oder Stück Glas abbekommt, dann bist du als Entwickler dran.



  • 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.


Anmelden zum Antworten