PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Suche schnellen Algorythmus um ein Bild zu filtern.



19.12.2004, 23:02
Tag alle zusammen

Kennt jemand eine schnelle Funktion um ein Bild zu filtern?

Ich beginn am Besten mal von Forne:

Mein Bruder und ich werkeln gerade einwenig an einem Bildverarbeitungssystem.

Als Kammera wird eine noname Funk-Webcam verwendet und programmiert wird das Ganze mit Visual Studio.Net 2003 MFC C++.

Der Rechner mit dem das Ganze zur Zeit getestet wird ist ein 1GHz Atlon mit 256MB Ram und einer 64MB Grafikkarte.

Das aktuelle Betriebssystem ist W2k.
Es kann aber bei Resourcenproblemen zu Win98 gewechselt werden.

Die Erkennung von Farben (rot, grün oder Blau), Bewegungen (Veränderungen von Pixxeln in einem Bereich) und Umrisse(apruppte veränderung von Helligkeit u. Farbe.) klappt schon einigermaßen mit der hochauflösenden Digitalkamera bei einem 240x320 Pixxel-Bild.
(Natürlich immer nur eine Methode. Für alle Erkennungsmethoden gleichzeitig ist der Rechner zu schwach auf der Brust.)

Bei der Webcam macht uns die Bildqualität Probleme.
Da ist dass Bild so "krieselig" dass die Bildergennung bei 120x160 mehr schlecht als recht funktioniert.

Bei dieser geringen Bildgröße gibts vorallem bei der Konurerkennung Probleme.

Wir habens schon damit versucht dass wir immer mehrere Bilder genommen haben und den Durchschnittswert der Pixxeln errechnet haben.
Dass hat aber 2 grundlegende Nachteile.

Für die Konturerkennung wird dass Bild zu unscharf und die Filterung benötigt bis zu 20 Sekunden.

Dass ist für eine dynamische Auswertung viel zu langsam.
(Vorallem weil während der Bilderfassung die Kammera absolut still stehen muss. Minimal 5 und maximal 10 Sekunden lang.)

:-k Kennt jemand eine schnellere Methode ein Bild zu filtern?
(Meinem Bruder und mir ist noch nichts besseres eingefallen.)

Zur Zeit wird noch mit dem RGB-System gearbeitet.
Ich bin aber am Überlegen ob wir nicht das HSL-System (Helligkeit,Sättigung und das Dritte weis ich gerade nicht auswendig)verwenden sollen.

mfg Bastlwastl

Bastlwastl
19.12.2004, 23:06
Dass ist mein Beitrag.

Aus irgend einem Grund bin ich kurz vorm Posten ausgeloggt worden.

mfg Bastlwastl

Felix G
20.12.2004, 01:26
In der Astrofotographie wird ein Teil des Rauschens mit Hilfe eines sog. Darkframes entfernt.

Ein Darkframe ist, wie der Name schon sagt, ein Bild das bei völliger Dunkelheit aufgenommen wurde (Kamera mit irgendwas abdecken)
Wenn man dieses Bild dann immer von den Rohbildern abzieht, sind zumindest schonmal die Fehler weg, die bei allen Bildern gleich sind.

wieviel das in diesem Fall bringt weiss ich nicht, aber versuchen könnt ihrs ja mal.

Bastlwastl
20.12.2004, 12:19
Ich hab mich mit einem Bildverarbeitungsspezialisten (Dr. Prof. irgenwas.) unterhalten.

Der hat gesagt dass ich schon die schnellste Methode verwende und dass die Langen Berechnungszeit am Programm bzw dem Programmaufbau liegt.

Gibt es eine bessere Möglichkeit als diese Methode um die Filterung durchzuführen?


int r1, r2, g1, g2, b1,b2;//RGB Farben.
CImage cImage1,cImage2; //Temporäre Variablen für die zu bearbeitenden Einzelbilder.
COLORREF farbe1,farbe2; //Variable für den Farbwert.
.
.
.
for (int y=0; y<iHoch; y++)//iHoch ist die Höhe des Bildes aus dem Videostream
{
for (int x=0; x<iBreit; x++,p=p+3)//iBreit ist die Breite des Bildes aus dem Videostream
{
farbe1 = cImage1.GetPixel(x,y);
farbe2 = cImage2.GetPixel(x,y);
r1 = cImage1.GetRValue(farbe1);
g1 = cImage1.GetGValue(farbe1);
b1 = cImage1.GetBValue(farbe1);

r2 = cImage2.GetRValue(farbe2);
g2 = cImage2.GetGValue(farbe2);
b2 = cImage2.GetBValue(farbe2);

r1 = (r1 + r2) / 2;
g1 = (g1 + g2) / 2;
b1 = (b1 + b1) / 2;

cImage1.SetPixelRGB(x, y, r1, g1, b1);
}
}


( Codetag eingefügt, Kjion )

uwe.arzt
20.12.2004, 14:43
Hallo,

bei Visual C++ ist die Optimierung nicht die beste... Probier mal den Intel C++ Compiler aus. Je nach eingestellter Optimierungsstufe kann es auch was bringen, wenn du statt der Division eine Shift-Operation verwendest.

Den meisten Gewinnn wirst du aber erzielen durch:

1. Verwenden von MMX/SSE (da gehen die ganzen 3 Operationen dann in einer) :)
2. Eine optimiertere Klasse für das Bild als CImage (ohne diese Klasse genau zu kennen, aber die meisten MFC-Klasssen sind nicht gerade für Bildverarbeitung optimiert) ;)

Und lass mal dein Programm mal mit einem Profiler laufen... Evtl. verbraucht es auch an anderen Stellen Zeit (z.B. extrahieren der Frames aus dem Videostream, ...)

:q! Uwe


BTW: HSI: Hue, Saturation, Intensity

Bastlwastl
20.12.2004, 15:08
Danke für deine Tipps.

Beim Extrahieren der Frames aus dem Videostream geht eigentlich nicht viel Zeit verloren, denn bei der Bildverarbeitung (Suchen nach Farbe, Form o. Bewegung) passiert dass so schnell dass man die Bearbeitungsschritte fast nicht bemerkt.

Der Tipp mit dem CImage war gut.
Ich hab da den Blödsinn gemacht dass ich das Bild vom Puffer geholt (RGB), dann in die CImage Variable geschrieben , dann die RGB-Werte herrausgeholt und bearbeitet, in die Variable zurückgeschrieben und in den Buffer zurückgeschrieben hab.

:-k Im Nachhinein weis ich jetzt auch nicht mehr wie ich einen solchen Schwachsinn machen konnte. :-k

Ich werd schreiben ob es sich viel verbesset wenn ich den Fehler behebe.

mfg Bastlwastl.

PasstScho
20.12.2004, 15:40
Hi,
Ich hab früher auch öfters was mit Graphik gemacht.
Das schlechteste dabei ist, fremde Bild-Klassen zu benutzen.
z.b.:
farbe1 = cImage1.GetPixel(x,y);

Ich kenn mich mit CImage nicht aus, aber ich vermute, dass es "COLORREF GetPixel(HDC hdc, int XPos, int nYPos);"
benutzt.
Was nun colorref genau macht ist nicht dokumentiert, aber vielleicht ruft es noch diverse andere Functionen auf, die was auch immer sinnloses machen.
Das ist vieeel zu langsam!
Benutze möglichst eigene Image Klassen(eine Klasse die die rgb Daten roh, in einem langen array verarbeitet ist so ziemlich am schnellsten, als einfache Softwarelösung).
Dann könntest du statt getpixel etwas in der Art verwenden:
BYTE *array=LoadMyPic....;
r=array[x*3+(y*3*pixwidth)+2];
// in bitmaps werden die Farbdaten als BGR gespeichert
g=array[x*3+(y*3*pixwidth)+1];
b=array[x*3+(y*3*pixwidth)+0];

.... Das war jetzt nur ein Vorschlag, wie du es wirklich machst ist natürlich dir überlassen. Das war jetzt eine simple Verbesserung, aber wenn du das noch schneller willst, musst du dich damit wohl genauer auseinandersetzen...
MfG Alex

Bastlwastl
22.12.2004, 10:35
\:D/ Ich habs hinbekommen!!!! \:D/

Ich hab einfach den ganzen Müll mit der Umwandlung in ein BMP-Bild und der Rückumwandlung rausgeschmissen und bearbeite direkt den Buffer.

Man merkt nur im 640x480 Anzeigemodus dass das Filtern ein wenig bremst.

Da aber bei dieser Bildgröße der Rechenaufwand für die Bildverarbeitung zu groß ist, fällt das nicht ins Gewicht.

Jetzt müssen mein Bruder und ich nur noch entscheiden was das Programm mit dem bearbeiteten Bild anfangen soll.

Aber da fällt uns sicher auch noch was ein.

mfg Bastlwastl

FuRanKu
11.01.2005, 14:57
Hallo Bastlwastl,

da ich ja jetzt endlich registriert bin, werde ich nun auch mal öfters meinen Senf dazugeben O:)

Hier gibts gute ne Dokumentation zu verschiedenen Bildverarbeitungsalgorythmen (mit Java-Applets!).

:arrow: http://homepages.inf.ed.ac.uk/rbf/HIPR2/guidecon.htm

Vielleicht hilft Dir das bei kommenden Problemen weiter.

Ciao FuRanKu