Zwei Bilder miteinander vergleichen...(Diskussion)
-
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.
-
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
kpeterEben 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