2 bilder vergleichen vb.net
lima-city → Forum → Programmiersprachen → Basic
abweichung
austauschen
beispiel
bekommen
bild
code
double
fehlermeldung
http
image
methode
pixel
problem
programm
programmieren
sekunde
system
vergleich
vergleichen
versuch
-
Hi Leute,
ich möchte ein programm in vb.net programmieren dass erkennt um vie viel sich % sich ein bild von andern abweicht, damit ich dann wenn es eine bestimmte schwelle überschritten hat ein bild abspeichert. wie kann ich so etwas machen.
hoffe ihr könnt mir helfen
Beitrag geändert: 14.6.2008 16:05:53 von speckuntu -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Es kommt darauf an, inwieweit sich die beiden Bilder voneinander unterscheiden.
Wenn du z.B. 2 gleiche Fotos hast und das eine zum Beispiel am Computer nachbearbeitet hast, hast du ja 2 mal das allergleiche Bild (Auflösung, Größe, Blinkwinkel usw.) mit nur kleinen Änderungen.
Ein Byte-Vergleich ist bei Bildern nicht geeignet, da Bilder auch das gleiche darstellen können aber in verschiedenen Bildformaten gespeichert sind. Somit musst du also Pixel für Pixel vergleichen. Voraussetzung dazu ist, dass die Bilder aber die gleiche Auflösung (Größe) haben, ansonsten musst du eben ein Bild so skalieren, dass es die gleiche Größe wie das andere aufweist.
Beispiel:
Dim p1 As System.Drawing.Image = System.Drawing.Image.FromFile(\"C:\\\\b1.bmp\") Dim p2 As System.Drawing.Image = System.Drawing.Image.FromFile(\"C:\\\\b2.bmp\") Dim b1 As New System.Drawing.Bitmap(p1, p1.Size) Dim b2 As New System.Drawing.Bitmap(p2, p2.Size) Dim h, w, c As Integer For h = 1 To b1.Height - 1 For w = 1 To b1.Width - 1 If b1.GetPixel(w, h) <> b2.GetPixel(w, h) Then c += 1 End If Next Next MsgBox(c & \" Pixel sind unterschiedlich\")
Allerdings ist diese Methode sehr zeitintensiv bei sehr großen Bildern.
Deshalb wäre es vielleicht geschickter, nicht jeden Pixel zu vergleichen, sondern z.B. Rechtecke, die 10x10 Pixel groß sind.
Beitrag geändert: 14.6.2008 21:06:10 von cbhp -
noch eine anregung:
wenn du zwei bilder hast, dann kannst du z.B. alles auf Schwarz/Weiß stellen, das würde die Prozent-Medode noch vielleicht verbessern.
lg
Vali -
Schau hier mal vorbei, um Bilder auf Schwarz-Weiß bzw. Grauskala zu ändern:
http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=2455869&SiteId=1
http://www.bobpowell.net/onebit.htm
-
Ein Byte-Vergleich ist bei Bildern nicht geeignet, da Bilder auch das gleiche darstellen können aber in verschiedenen Bildformaten gespeichert sind. Somit musst du also Pixel für Pixel vergleichen. Voraussetzung dazu ist, dass die Bilder aber die gleiche Auflösung (Größe) haben, ansonsten musst du eben ein Bild so skalieren, dass es die gleiche Größe wie das andere aufweist.
Ungefähr das gleiche wollte ich vorhin auch vorschlagen, musste nur leider weg ;)
Man kann das ganze noch ein wenig Verbessern, dinem du, statt einfach nur gleiche Pixel zu zählen (i.A. reicht es, eine JPEG z.B. mit einem anderen Programm zu speichern, um sie neu zu komprimieren und damit sehr große Abweichungen zu bekommen), sondern indem du die relative Abweichung der Pixel vom Referenzbild nimmst. Angepasster Code wäre dann:
Dim p1 As System.Drawing.Image = System.Drawing.Image.FromFile(\"C:\\\\b1.bmp\") Dim p2 As System.Drawing.Image = System.Drawing.Image.FromFile(\"C:\\\\b2.bmp\") Dim b1 As New System.Drawing.Bitmap(p1, p1.Size) Dim b2 As New System.Drawing.Bitmap(p2, p2.Size) Dim devs(3,b1.width-2,b1.height-2) as Double dim sumdev as double = 0 Dim avedev as Double Dim h, w, c As Integer Dim b1col as System.Drawing.Color Dim b2col as System.Drawing.Color For h = 0 To b1.Height - 2 For w = 0 To b1.Width - 2 b1col = b1.getPixel(w + 1, h + 1) b2col = b2.getPixel(w + 1, h + 1) dev(0,w,h) = (b1col.A - b2col.A) / b1col(w,h).A dev(1,w,h) = (b1col.A - b2col.A) / b1col(w,h).A dev(2,w,h) = (b1col.A - b2col.A) / b1col(w,h).A dev(3,w,h) = (b1col.A - b2col.A) / b1col(w,h).A Next Next For each value in devs sumdev += value Next avedev = math.round(sumdev / (4*b1.height*b1.width),4) MsgBox(\"Das zweite Bild weicht um \" & (avedev * 100) & \" Prozent vom ersten Bild ab!\")
Zuerst geht dieser Code Alle Pixel durch und speichert jeweils die relative Abweichung des Alphawertes des Pixels im zweiten Bild vom Pixel im ersten Bild in einem Array. Da gleiche dann mit Rot-, Grün- und Blauanteil für jeden Pixel.
Anschließend werden alle diese Einzelabweichungen aufsummiert und durch die Anzahl der Werte geteilt, es wird also das Arithmetische Mittel der Abweichungen berechnet. Dies wird dann als Prozentuale Abweichung des zweiten Bildes vom ersten genommen.
Dabei sind ein paar dinge zu beachten:
- Diese Methode hat gegenüber der genannten den Vorteil, dass auch, wenn du z.B. das Bild nur ein wenig heller machst oder so, immer noch ein großer Grad an Übereinstimmung festgestellt wird
- Diese Methode hat geenüber der genannten den NACHTEIL, dass sie noch einmal deutlich langsamer ist, es hilft also notfalls wieder nur das aufteilen in größere Einheiten als Pixel.
- Es wird sozusagen das erste Bild als \"Referenzbild\" genommen, d.h. es wird quasi angenommendass as erste Bild das \"richtige ist\" und das zweite eine abgeänderte Version. Das ERgebnis fällt leicht unterschiedlich aus, wenn du die Rollen der Bilder vertauschst. Allerdings sollte dieser Unterschied für deine Zwecke recht marginal sein... nur in sehr seltsamen Fällen würden damit zwei Bilder als gleich gelten, ohne es zu sein, oder umgekehrt.
Ich übernehme natürlich keine Verantwortung für den geposteten Code oder die rechnerische Korrektheit (Gerade was die verschiedenen Höhen- und Breitsn des Bildes angeht, die im Code auftauchen bin ich mir nicht ganz sicher, aber entweder merkst du es ziemlich schnell an einer \"Index out of Bound Exception\", dann mal an der Stelle um eins verringern, oder es macht an einer Stelle (wo ich mir nicht sicher bin) denke ich bei den meisten Bildern keinen echten Unterschied.
Allerdings musst du bedenken, dass der Algo tatsächlich nur geht, wenn die Bilder aus dem gleichen Winkel aufgenommen etc. wurden, wenn es sich also quasi um das gleiche Bild, nur in einem Fall nachbearbeitet handelt. Ansonsten hast du keine Wahl, als den gesamt-Durchschnitt der Farbwerte zu nehmen und die zu vergleichen, wird afaik in der Kriminologie schon so gemacht, um z.B. bei Google Bilder von Personen zu finden, von denen man nur Fotos hat. Ist aber leider alles andere als Zuverlässig und halte ich für sehr gefährlich und überhaupt ungeeignet.
Beitrag geändert: 15.6.2008 0:12:35 von merovius -
jo so richtig toll geht das ganze eigenlich nur, wenn du 2 Bilder vergleichst, die aus gleichem
Winkel und bei in etwa gleicher Belichtung aufgenommen wurden...
andernfalls wirst du nicht so aussagekräftige Ergebnisse bekommen -
das ganze soll die grundlage von einem überwachungsprogramm von webcams werden dass erkännt wenn sich etwas bewegt. und bei überwachungscams die nicht schwankbar sind ist es klar dass sie bilder immer von dem selben blickwinkel aufgenommen worden sind.
lg
speckuntu
Beitrag geändert: 15.6.2008 15:13:40 von speckuntu -
das ganze soll die grundlage von einem überwachungsprogramm von webcams werden dass erkännt wenn sich etwas bewegt. und bei überwachungscams die nicht schwankbar sind ist es klar dass sie bilder immer von dem selben blickwinkel aufgenommen worden sind.
lg
speckuntu
Joa, dann sollte das hinhauen, aber die Geschwindigkeit spielt da wohl kaum mit, vermute ich mal, müsste man ausprobieren.
Aber prinzipiell kannst du jeweils ein Bild als Referenzbild nehmen, das nächste dann relativ vergleichen und ab einem Schwellenwert Abweichung dann alarm schlagen.
Allerdings bist du dann auf meine Methode angewiesen, weil i.A. auch bei einem Bild aus einem vollkommen leeren Raum zwei Aufeinander folgende Bilder nicht identisch sind, sondern überall leichte Fluktuationen haben. Mit meiner Methode sollte sich das aber ausbügeln. Nur ist sie recht langsam halt...
Übrigens: Mir ist noch etwas eingefallen. Bei dem berechnen des Durchschnitts solltest du nicht mit den echten Werten des Arrays arbeiten, sondern mit deren Beträgen, weil sich sonst, wenn ein Pixel zu hell un der andere zu dunkel ist, sich das gegenseitig aufhebt, also in der letzten Schleife
sumdev += value
ändern in
sumdev += Math.abs(value) -
ich habe mir gedacht dass ich das reverenz bild alle 0,2 sekunden aktuallisiere. und die livebilder auf jeden fall öfter als 24 mal in der sekunde. spannend wird das ganz wenn ich ich dann mehrere webcams habe die dann gleichzeitig laufen sollen.
lg
speckuntu -
ich habe mir gedacht dass ich das reverenz bild alle 0,2 sekunden aktuallisiere. und die livebilder auf jeden fall öfter als 24 mal in der sekunde. spannend wird das ganz wenn ich ich dann mehrere webcams habe die dann gleichzeitig laufen sollen.
lg
speckuntu
Joa, mit der Frequenz wirst du Probleme mit den vorgeschlagenen Methoden bekommen. 24 mal in der Sekunde kannst du vermutlich komplett vergessen.versuch doch einfach mal, unsere Vorschläge zum Laufen zu bringen und Stoppe die Zeit, die das Programm für einen Durchlauf braucht (Am besten einfach mit der System.Diagnostics.Stopwatch, mach ich immer so...). Daraus kriegst du dann eine Dimension, wie stark du das optimieren musst, eventuell wie groß deine Bildabschnitte werden müssen. -
da ich nun endlich zeit hatte an dem Programm weiter zu programmieren und ich mit vb.net noch nicht so viel erfahrung habe ich noch ein problem ich verstehe den code nicht:
dev(0,w,h) = (b1col.A - b2col.A) / b1col(w,h).A dev(1,w,h) = (b1col.A - b2col.A) / b1col(w,h).A dev(2,w,h) = (b1col.A - b2col.A) / b1col(w,h).A
genauer gesagt funktioniert er nicht. -
Hm, da war ich ein wenig laxig mitm copy-pasten, das müsste heissen:
dev(0,w,h) = (b1col.A - b2col.A) / b1col(w,h).A dev(1,w,h) = (b1col.R - b2col.R) / b1col(w,h).R dev(2,w,h) = (b1col.G - b2col.G) / b1col(w,h).G dev(3,w,h) = (b1col.B - b2col.B) / b1col(w,h).B
Aber ist übrigens viel hilfreicher, wenn du sagst WAS nicht geht. Gibt er nen Syntaxfehler aus? Oder einen Laufzeitfehler? Wenn ja, welchen? Irgendwelche Fehlermeldungen?
Hab leider noch nie mit mehrdimensionalen Arrays gearbeitet, das war ergo erst einmal nur ein Versuch, wenn du mir sagst, was die Fehlermeldung ist, kann ich das vielleicht beheben.
Beitrag geändert: 6.7.2008 22:28:04 von merovius -
ist dev eine variable? beim Code:
dev(0,w,h) = (b1col.A - b2col.A) / b1col(w,h).A dev(1,w,h) = (b1col.R - b2col.R) / b1col(w,h).R dev(2,w,h) = (b1col.G - b2col.G) / b1col(w,h).G dev(3,w,h) = (b1col.B - b2col.B) / b1col(w,h).B Next Next For Each value In devs
mag .net das \"dev\", \"value\" und das \"b1col\" nicht
lg
speckuntu
Beitrag geändert: 7.7.2008 16:26:30 von speckuntu
Beitrag geändert: 7.7.2008 16:27:12 von speckuntu -
Dim devs(3,b1.width-2,b1.height-2) as Double
austauschen mit
Dim dev(3,b1.width-2,b1.height-2) as Double
For Each value In devs
austauschen mit
For Each value as Double In devs
b1col(w, h)
jedes mal austauschen mit
b1col
Welche IDE benutzt du? Ne Halbwegs gute IDE hätte dir eigentlich mehr ausgeben müssen als blos \"mag er nicht\". ;) -
ich verwende visual studio 2008.
ich habe bei meinem projekt ein problem und zwar bekomme ich als änderungswert von den bildern immer 0 heraus. ihr könnt es unter http://speckuntu.bplaced.net/uberwachungsprogramm.rar downloaden.
lg
speckuntu -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage