2012-06-14 8 views
7

Ich entwickle Tiefenbearbeitung (Xbox Kinect, Asus Xtion, usw.) Anwendungen mit OpenNI.C# schnelles Pixel-Rendering

Ich brauche eine wirklich einfache und schnelle Möglichkeit, auf einem Windows-Formular zu zeichnen, wenn neue Tiefeninformationen vom Sensor verfügbar sind (30 oder 60 fps je nach Auflösung).

Zur Zeit mache ich ein doppelt gepuffertes Panel aus einem separaten Thread ungültig, wenn die Daten verfügbar sind, und setze dann Pixel einer Bitmap in der Paint-Methode des Panels ein, was zu einem vorhersagbar schrecklichen 5fps führt.

System.Drawing.Graphics scheint eine schnelle Möglichkeit zu fehlen, einzelne Pixel zu setzen, es sei denn jemand kann etwas anderes anweisen.

Ich muss im wahrsten Sinne des Wortes nur Pixelfarben setzen, daher möchte ich möglichst keine Hochgeschwindigkeits-Rendering-APIs von Drittanbietern verwenden und idealerweise etwas so Natives wie möglich verwenden.

Hat jemand irgendwelche Vorschläge?

+0

Wie stellen Sie die Pixel derzeit ein? – leppie

+0

Erstellt eine Bitmap mit image.SetPixel (x, y, color). Nach alldem ist das Aufrufen von graphics.drawImage (Bild usw.) –

+2

'SetPixel' sehr langsam. Sehen Sie sich den Scanline-Ansatz an. – leppie

Antwort

4

Wenn Sie Bitmaps verwenden, sollten Sie LockBits und UnlockBits verwenden, um auf die Daten im Speicher zuzugreifen. In C# können Sie durch die Verwendung von unsicheren Codeblöcken und -zeigern zusätzliche Leistung erzielen.

Siehe diesen Link für weitere Informationen: http://web.archive.org/web/20150227183132/http://bobpowell.net/lockingbits.aspx

+0

Dies war eine drastische Verbesserung. Ich konnte nicht mehr als 10 fps erreichen, wenn ich eine leere 640x480-Bitmap zeichne, also ist System.Drawing im Grunde genommen einfach nicht schnell. Diese Lösung, kombiniert mit der Skalierung des Bildes und dem Rendern einiger Pixel, um den erforderlichen FPS zu erreichen, war die Antwort. –

4

image.SetPixel() ist sehr langsam, wenn Sie viele Pixel pro Bild ersetzen und Sie viele Bilder pro Sekunde benötigen.

Es wird viel schneller sein, wenn Sie ein WriteableBitmap verwenden und CopyPixels

Auf diese Weise rufen Sie das Array mit Pixeldaten unter Verwendung von mehreren Threads und einfach blitten das Array an das Bild in einem einzigen Aufruf füllen.

EDIT

Beachten Sie, dass Writeablebitmap eine WPF-Klasse ist. Wenn Sie an WinForms gebunden sind, müssen Sie möglicherweise eine eigene Implementierung erstellen. WPF/WinForms/GDI interop: converting a WriteableBitmap to a System.Drawing.Image?

+0

Vielen Dank für Ihre Antwort, aber der von Ihnen bereitgestellte Antwort-Link verwendet .SetPixel() in der Konvertierung von WriteableBitmap zu System.Drawing.Image. –

+0

Ja, und das ist schrecklich für die Geschwindigkeit. Eine Alternative wäre, in ein Array zu schreiben und einen Encoder (PNG, BMP, ...) zu verwenden, um daraus ein Bild zu machen und es anzuzeigen. Das Hauptproblem von SetPixel ist, dass es ein einzelnes Pixel setzt. –

0

Sie mein LINQ image processing library versuchen könnte mit "Puffer-Bitmaps" zu arbeiten. Es verwendet eine sehr zugängliche Syntax, ist aber sehr leistungsfähig für große Bitmaps. Es ist unter Nuget als einzelnes Datei-Include in Ihrem Projekt verfügbar.

Hoffe, dass hilft!

Verwandte Themen