Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Schnelle Konvertierung von Grayscale zu RGB (WPF)
robbb26
myCSharp.de - Member



Dabei seit:
Beiträge: 6

Themenstarter:

Schnelle Konvertierung von Grayscale zu RGB (WPF)

beantworten | zitieren | melden

Hallo liebe Gemeinde,

ich arbeite momentan an einem Projekt von meiner Arbeit aus, bei dem ich ein 8-Bit Graustufenbild in ein 24-Bit RGB umwandeln muss, um es "künstlich" blau oder grün einzufärben.
Da ich das Bild von der Kamera als byte-Pixel-Array zurück bekomme war mein bisheriger Ansatz ein 3x so langes byte-Array anzulegen und den Grauwert über eine Schleife an die jeweilige Stelle (grün/blau) einzutragen, daraus eine BitmapSource zu erzeugen und es anschließend als Image auf der GUI anzuzeigen.

Es geht jetzt vor allem um den Live-View, also das schnelle hintereinander grabben der Bilder. Ein Bild ist 1920x1200 Pixel x 3-Bit pro Pixel. In einer Schleife dauert das auf der Zielplattform zu lang (10fps).

Gibt es einen schnellen und ressourcensparenden Ansatz, den ich weiter verfolgen könnte?

Grüße und danke schon mal im Voraus.
private Nachricht | Beiträge des Benutzers
LaTino
myCSharp.de - Experte

Avatar #avatar-4122.png


Dabei seit:
Beiträge: 3.003
Herkunft: Thüringen

beantworten | zitieren | melden

Das erklärt noch nicht, wozu du ein 24Bit-Bild brauchst. Was hindert dich denn, mit Graustufen zu arbeiten, anstatt das umständlich umzurechnen?

LaTino
"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)
private Nachricht | Beiträge des Benutzers
robbb26
myCSharp.de - Member



Dabei seit:
Beiträge: 6

Themenstarter:

beantworten | zitieren | melden

Naja wie gesagt, das Live-Bild soll ja dann eingefärbt sein, statt in Graustufen angezeigt zu werden.
Hab im Anhang mal Beispielbilder, einmal Graustufen (so wie es von der Kamera kommt) und einmal grün gefärbt (so wie es am Ende angezeigt werden soll).
Attachments
private Nachricht | Beiträge des Benutzers
Taipi88
myCSharp.de - Member

Avatar #avatar-3220.jpg


Dabei seit:
Beiträge: 1.029
Herkunft: Mainz

beantworten | zitieren | melden

Hi,

mal für den Fall, dass du wirklich 24bpp brauchen solltest - was genau dauert denn eigentlich zu lange? Sicher die Konvertierung?

Falls dem so wäre - probier mal AForge.Imaging - damit geht GrayScale to 24bpp-RGB (ohne Coloring) so:


var filter = new GrayscaleToRGB();
var rgb = filter.Apply(img);

Alternativ kannst du auch direkt mal folgendes Beispiel anschauen:
https://gist.github.com/xinmyname/1602389

LG
private Nachricht | Beiträge des Benutzers
robbb26
myCSharp.de - Member



Dabei seit:
Beiträge: 6

Themenstarter:

beantworten | zitieren | melden

Der Tipp ist gut, aber das habe ich schon probiert
Problem dabei ist, dass die Funktion nur ein Bitmap frisst und ich von der Kamera aber ein byte[] zurück bekomme (und ich unter WPF arbeite und da ja "eigentlich" kein Bitmap verfügbar ist).

Achso und ja die Konvertierung ist der Zeitfresser
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von robbb26 am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 15.500

beantworten | zitieren | melden

Bitte verwende kein Rar/Zip-Upload bei nur zwei Bilder.
Beachte bitte [Hinweis] Wie poste ich richtig? Punkt 6.1
private Nachricht | Beiträge des Benutzers
MrSparkle
myCSharp.de - Team

Avatar #avatar-2159.gif


Dabei seit:
Beiträge: 5.649
Herkunft: Leipzig

beantworten | zitieren | melden

Hi robbb26,

bitte nimm dir erstmal die Zeit und einen Profiler, um das Problem genauer einzugrenzen, und diese Frage zu beantworten:
Zitat von Taipi88
mal für den Fall, dass du wirklich 24bpp brauchen solltest - was genau dauert denn eigentlich zu lange? Sicher die Konvertierung?

Wir wissen ja nicht, was genau bei dir zu lange dauert, und können daher auch nur raten.
Weeks of programming can save you hours of planning
private Nachricht | Beiträge des Benutzers
robbb26
myCSharp.de - Member



Dabei seit:
Beiträge: 6

Themenstarter:

beantworten | zitieren | melden

So nochmal von vorn:

Von der Kamera bekomme ich das Bild als byte-Array. IGrabResult ist ein Interface von der Kamera-DLL, das die Bilder hält.

byte[] grabResult = IGrabResult.PixelData as byte[];
grabResult ist ein 1920 * 1200 großes Array mit den Graustufen-Werten (8-Bit).

Jetzt erzeuge ich ein 3x so langes Array für 24-Bit RGB und ersetze den jeweiligen Grün- bzw. Blau-Wert durch den Graustufen-Wert aus dem alten Array.

byte[] RGB = new byte[1920 * 1200 * 3];
int StartIndex = 0;
// für Grün
for (int Index = 1; Index < RGB.Length; Index += 3)
{
RGB[Index] = grabResult[StartIndex];
StartIndex++;
}
// für Blau
for (int Index = 2; Index < RGB.Length; Index += 3)
{
RGB[Index] = grabResult[StartIndex];
StartIndex++;
}

Da diese Schleife knapp 7 Mio durchlaufen werden muss, 10 Bilder pro Sekunde von der Kamera gegrabbt werden und der Zielrechner ein relativ langsamer Atom ist, dauert der Vorgang des künstlichen Einfärbens halt sehr lange.

Gibt es Möglichkeiten diesen Vorgang zu beschleunigen?
private Nachricht | Beiträge des Benutzers
Spook
myCSharp.de - Member



Dabei seit:
Beiträge: 241
Herkunft: Esslingen a.N.

beantworten | zitieren | melden

Hallo robbb26,

ich würde dies mit einer lookup table lösen:

  [StructLayout(LayoutKind.Sequential, Pack = 1)]
    public struct RGB24
    {
        public byte B;
        public byte G;
        public byte R;

        public RGB24(byte value)
        {
            B = value;
            G = value;
            R = value;
        }
    }

    public class ImageConverter
    {
        private RGB24[] _lut;

        public ImageConverter()
        {
            _lut = new RGB24[256];
            for (int i = 0; i < _lut.Length; i++)
            {
                _lut[i] = new RGB24((byte)i);
            }
        }

        public unsafe byte[] ToRGB24(byte[] data)
        {
            byte[] result = new byte[data.Length * 3];
            fixed (byte* bptr = result)
            {
                RGB24* ptr = (RGB24*)bptr;
                for (int i = 0; i < data.Length; i++)
                {
                    ptr[i] = _lut[data[i]];
                }
            }
            return result;
        }
    }

Grüße
spooky
private Nachricht | Beiträge des Benutzers
robbb26
myCSharp.de - Member



Dabei seit:
Beiträge: 6

Themenstarter:

beantworten | zitieren | melden

Danke erstmal für deine Antwort Spook.
Bin jetzt erst dazu gekommen, dein Snippet auszuprobieren. Es funktioniert auch soweit und ist auch fast doppelt so schnell, wie meine Lösung.
ABER :D : Deine Methode schreibt in dem result-Array den Grausutufen-Wert in alle drei Kanäle (RGB)

So sollte es aussehen (beispielhaft): {0, 78, 0, 0 215, 0, 0, 124, 0, ... }
So sieht es momentan aus: {78, 78, 78, 215, 215 ,215, 124, 124, 124, ...}

Hast du dafür noch eine Lösung?
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.176

beantworten | zitieren | melden

Kannst du nicht programmieren? Tipp: RGB24-Konstruktor ändern.
private Nachricht | Beiträge des Benutzers
Spook
myCSharp.de - Member



Dabei seit:
Beiträge: 241
Herkunft: Esslingen a.N.

beantworten | zitieren | melden

Hallo robbb26,

bei mir funktioniert es (siehe screenshot).


grüße
spooky
Attachments
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4.176

beantworten | zitieren | melden

Spook: robbb26 möchte aber eben kein Graubild (also R = G = B), sondern nur ein Farbwert davon gesetzt (und die anderen beiden dann 0) ;-)
private Nachricht | Beiträge des Benutzers
Spook
myCSharp.de - Member



Dabei seit:
Beiträge: 241
Herkunft: Esslingen a.N.

beantworten | zitieren | melden

Hallo Th69,

dann ist deine Antwort natürlich richtig.

Grüße
spooky
private Nachricht | Beiträge des Benutzers
robbb26
myCSharp.de - Member



Dabei seit:
Beiträge: 6

Themenstarter:

beantworten | zitieren | melden

Danke euch beiden!
Läuft jetzt.
private Nachricht | Beiträge des Benutzers