Frage

Gibt es eine effiziente Möglichkeit, den Kontrast eines Bildes in C # zur Einstellung?

Ich habe dieser Artikel , die spricht sich für eine pro-Pixel-Operation zu tun. Nicht schnell.

Ich bin mit Farbmatrizen an Orten bereits und finden sie schnell zu sein. Gibt es eine Möglichkeit Kontrast mit ihnen einzustellen? (Hinweis: Dieser Typ bekommt es falsch. )

Ich verwende auch EmguCV. Ich bemerke, dass OpenCV (die Emgu Wraps) scheint eine Kontrastfunktion zu haben - ist es eine Möglichkeit, dies durch Emgu des Zugriffs auf? Im Moment alles, was ich in Emgu tun kann, ist zu normalisieren das Histogramm, die den Kontrast ändern, nicht aber mit einem gewissen Grad an Kontrolle auf meiner Seite.

got Wer irgendwelche Ideen?

War es hilfreich?

Lösung

Wenn der Code in dieser Probe für Sie arbeitet, können Sie es massiv beschleunigen (um Größenordnungen) von Bitmap.LockBits verwenden, die eine BitmapData Objekt zurückgibt, der Zugriff auf die über Zeiger Pixeldaten der Bitmap ermöglicht. Es gibt zahlreiche Beispiele auf der Bahn und auf Stackoverflow, die zeigen, wie LockBits verwenden.

Bitmap.SetPixel() und Bitmap.GetPixel() sind die langsamsten Methoden der Menschheit bekannt sind, und sie beide nutzen die Color-Klasse, die die langsamste Klasse der Menschheit bekannt ist. Sie sollten Bitmap.GetPixelAndByGodYoullBeSorryYouDid() und Bitmap.SetPixelWhileGettingCoffee als Warnung an unvorsichtige Entwickler genannt wurden.

Update: Wenn Sie vorhaben, den Code in dieser Probe, beachten Sie, dass diese Brocken zu ändern:

System.Drawing.Bitmap TempBitmap = Image;
System.Drawing.Bitmap NewBitmap = new System.Drawing.Bitmap(TempBitmap.Width,
    TempBitmap.Height);
System.Drawing.Graphics NewGraphics = 
    System.Drawing.Graphics.FromImage(NewBitmap);
NewGraphics.DrawImage(TempBitmap, new System.Drawing.Rectangle(0, 0, 
    TempBitmap.Width, TempBitmap.Height), 
    new System.Drawing.Rectangle(0, 0, TempBitmap.Width, TempBitmap.Height),
    System.Drawing.GraphicsUnit.Pixel);
NewGraphics.Dispose();

kann mit diesem ersetzt werden:

Bitmap NewBitmap = (Bitmap)Image.Clone();

Update 2: Hier ist die LockBits Version der AendereKontrast Methode (mit einigen anderen Verbesserungen in der Geschwindigkeit):

public static Bitmap AdjustContrast(Bitmap Image, float Value)
{
    Value = (100.0f + Value) / 100.0f;
    Value *= Value;
    Bitmap NewBitmap = (Bitmap)Image.Clone();
    BitmapData data = NewBitmap.LockBits(
        new Rectangle(0, 0, NewBitmap.Width, NewBitmap.Height), 
        ImageLockMode.ReadWrite,
        NewBitmap.PixelFormat);
    int Height = NewBitmap.Height;
    int Width = NewBitmap.Width;

    unsafe
    {
        for (int y = 0; y < Height; ++y)
        {
            byte* row = (byte*)data.Scan0 + (y * data.Stride);
            int columnOffset = 0;
            for (int x = 0; x < Width; ++x)
            {
                byte B = row[columnOffset];
                byte G = row[columnOffset + 1];
                byte R = row[columnOffset + 2];

                float Red = R / 255.0f;
                float Green = G / 255.0f;
                float Blue = B / 255.0f;
                Red = (((Red - 0.5f) * Value) + 0.5f) * 255.0f;
                Green = (((Green - 0.5f) * Value) + 0.5f) * 255.0f;
                Blue = (((Blue - 0.5f) * Value) + 0.5f) * 255.0f;

                int iR = (int)Red;
                iR = iR > 255 ? 255 : iR;
                iR = iR < 0 ? 0 : iR;
                int iG = (int)Green;
                iG = iG > 255 ? 255 : iG;
                iG = iG < 0 ? 0 : iG;
                int iB = (int)Blue;
                iB = iB > 255 ? 255 : iB;
                iB = iB < 0 ? 0 : iB;

                row[columnOffset] = (byte)iB;
                row[columnOffset + 1] = (byte)iG;
                row[columnOffset + 2] = (byte)iR;

                columnOffset += 4;
            }
        }
    }

    NewBitmap.UnlockBits(data);

    return NewBitmap;
}

. Hinweis: dieser Code using System.Drawing.Imaging; in Ihrer Klasse erfordert Aussagen verwenden, und es erfordert, dass das allow unsafe code Option des Projektes (auf der Build-Registerkarte Eigenschaften für das Projekt) überprüft werden

Einer der Gründe GetPixel und SetPixel sind so langsam für Pixel-für-Pixel-Operationen ist, dass der Aufwand für den Methodenaufruf selbst ein sehr großer Faktor zu werden beginnt. Normalerweise hier mein Codebeispiel wäre ein Kandidat für Refactoring in Betracht gezogen werden, da Sie Ihre eigene SetPixel und GetPixel Methoden, die eine vorhandene Bitmapdata-Objekt verwenden schreiben könnte, aber die Bearbeitungszeit für die Mathematik in den Funktionen wäre sehr klein im Vergleich zu dem Verfahren Kopf jeden Anruf. Aus diesem Grund habe ich die Clamp Anrufe in der ursprünglichen Methode ebenfalls entfernt.

Eine andere Möglichkeit, diese zu beschleunigen wäre, einfach es sich um eine „destruktiv“ Funktion zu machen, und ändern den übergebenen Bitmap Parameter stattdessen eine Kopie zu machen und die modifizierte Kopie zurück.

Andere Tipps

@MusiGenesis,

Ich wollte nur anmerken, dass ich diese Methode für einen Bildeditor verwenden ich mit dem Schreiben bin. Es funktioniert gut, aber manchmal diese Methode löst einen Access auf dieser Linie:

byte B = row[columnOffset];

Ich erkennen, dass es war, weil es keine Standardisierung von bitdepth war, also wenn ein Bild 32-Bit-Farbe war ich diesen Fehler. Also habe ich diese Zeile geändert:

BitmapData data = NewBitmap.LockBits(new Rectangle(0, 0, NewBitmap.Width, NewBitmap.Height),  ImageLockMode.ReadWrite, NewBitmap.PixelFormat);

zu:

BitmapData data = NewBitmap.LockBits(new Rectangle(0, 0, NewBitmap.Width, NewBitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppRgb); 

Hope, das hilft, wie es scheint mein Problem ausgerottet zu haben.

Danke für den Beitrag.

Jib

Ich bin ein bisschen spät, aber eine Farbmatrix-Implementierung verwenden, da diese für solche Transformationen optimiert werden und ist viel einfacher als die Manipulation der Pixel selbst: http://www.geekpedia.com/tutorial202_Using-the-ColorMatrix-in-Csharp.html

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top