Farbiges Bild in Graustufen umwandeln

  • VB.NET

Es gibt 13 Antworten in diesem Thema. Der letzte Beitrag () ist von toyy1.

    Farbiges Bild in Graustufen umwandeln

    Guten Morgen,

    ich lese die Farben eines Pixel für Pixel eines Bildes aus. Anschließend möchte ich die Pixel in ein "Grauwert" umwandeln.

    Im Netz habe ich dazu gefunden, dass die RGB Werte vom AUge unterschiedlich intensiv wahrgenommen werden...

    VB.NET-Quellcode

    1. MeinePixelFarbe = fg.GetPixel(Spalte, Zeile) 'liest die Pixelfarbe des Pixels vom Bild
    2. ' MeinePixelFarbe = Math.Round(MeinePixelFarbe.R * 0.3 + MeinePixelFarbe.G * 0.584 + MeinePixelFarbe.B * 0.114, 0)
    3. 'fg.SetPixel(Spalte,Zeile,


    Nun meine Frage wie übergebe ich den Grauwert wieder zurück an die Grafik, da VS ja eine "Sytem.Drwing.Color" erwartet?

    Ich hoffe es kann mir jemand helfen.
    Vielen Dank und viele Grüße,
    TOYY1

    *Topic verschoben*

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    Habs zwar noch nie gemacht, aber ich denke das müsste ungefähr so gehen:

    VB.NET-Quellcode

    1. MeinePixelFarbe = fg.GetPixel(1, 1) 'liest die Pixelfarbe des Pixels vom Bild
    2. MeinePixelFarbe = Color.FromArgb(255, MeinePixelFarbe.R * 0.3 + MeinePixelFarbe.G * 0.584 + MeinePixelFarbe.B * 0.114, 0)
    3. fg.SetPixel(1, 1, MeinePixelFarbe)


    Greez
    MESS WITH THE BEST, DIE LIKE THE REST! :evil:
    n'paar Links: DNS Tools, Steal WA DB, Droidsheep...
    Ich hab mich grad etwas damit beschäftigt, um einen guten Grauton für jedes Pixel zu bekommen, hab ich die R,G und B werte addiert und durch 3 geteilt. Hier ein Beispiel mit LockBits.

    VB.NET-Quellcode

    1. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    2. Dim fname As String = ""
    3. Me.BackgroundImageLayout = ImageLayout.Stretch
    4. Using OFD As New OpenFileDialog
    5. OFD.Filter = "Images(*.BMP;*.JPG;*.PNG)|*.BMP;*.JPG;*.PNG"
    6. If OFD.ShowDialog <> Windows.Forms.DialogResult.OK Then
    7. Return
    8. End If
    9. fname = OFD.FileName
    10. End Using
    11. Dim bmp As New Bitmap(Image.FromFile(fname))
    12. Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
    13. Dim bmpData As System.Drawing.Imaging.BitmapData = bmp.LockBits(rect, Drawing.Imaging.ImageLockMode.ReadWrite, bmp.PixelFormat)
    14. Dim ptr As IntPtr = bmpData.Scan0
    15. Dim bytes As Integer = Math.Abs(bmpData.Stride) * bmp.Height
    16. Dim rgbValues(bytes - 1) As Byte
    17. System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes)
    18. For I As Integer = 0 To rgbValues.Length - 1 Step 4 '4bpp Image
    19. Dim rgbv As Integer = CInt((CInt(rgbValues(I + 2)) + CInt(rgbValues(I + 1)) + CInt(rgbValues(I))) / 3)
    20. rgbValues(I) = CByte(rgbv)
    21. rgbValues(I + 1) = CByte(rgbv)
    22. rgbValues(I + 2) = CByte(rgbv)
    23. Next
    24. System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes)
    25. bmp.UnlockBits(bmpData)
    26. Me.BackgroundImage = bmp
    27. End Sub
    @Derfuhr
    Es gibt verschiedene Methoden, deine ist eine davon. Eine andere wäre beispielsweise der B-Wert der Farbe (Brightness), kriegt man über die Funktion GetBrightness.

    Derfuhr schrieb:

    hab ich die R,G und B werte addiert und durch 3 geteilt

    Das ist aber doch genau das was der TE nicht will. Denn wie er erkennbar schreibt: Die drei Farbkomponenten werden vom (menschlichen!) Auge unterschiedlich intensiv wahrgenommen. Nicht umsonst tauchen bei ihm so komische Zahlen wie 0.3, 0.59 und 0.11 auf - was genau die Gewichtungen für die drei RGB-Kanäle sind, um einen vernünftigen Grauton zu bekommen. (Immer auf das menschliche Auge bezogen - wohlgemerkt. Bei anderen Lebewesen, Hunden z.B., sind die Gewichtungen andere, aber wer entwickelt schon Windows-Programme für Hunde? :D )

    toyy1 schrieb:

    Im Netz habe ich dazu gefunden, dass die RGB Werte vom AUge unterschiedlich intensiv wahrgenommen werden...

    VB.NET-Quellcode

    1. MeinePixelFarbe = fg.GetPixel(Spalte, Zeile) 'liest die Pixelfarbe des Pixels vom Bild
    2. 'MeinePixelFarbe = Math.Round(MeinePixelFarbe.R * 0.3 + MeinePixelFarbe.G * 0.584 + MeinePixelFarbe.B * 0.114, 0)

    Nun meine Frage wie übergebe ich den Grauwert wieder zurück an die Grafik, da VS ja eine "Sytem.Drwing.Color" erwartet?

    Das ist fast fertig. Dein "MeinePixelFarbe" ist nun der Grauwert im Wertebereich 0 bis 255, also Integer statt System.Color.
    Eine grauer RGB-Wert ist aber nach wie vor eine RGB-Farbe, hat also die Kanäle R, G und B, und damit er "grau" ist, sind alle drei Werte identisch. Du nimmst also deinen Grauwert und machst daraus deine neue RGB-Farbe.
    Unabhängig davon hast du natürlich auch schon den Tipp bekommen, statt GetPixel() und SetPixel() besser LockBits zu nehmen, weil das in solchen Fällen einfach wesentlich schneller ist. Aber das ändert nichts an deiner Frage, wie du dein Color-Objekt bekommst.

    VB.NET-Quellcode

    1. Dim MeinePixelFarbe As Color = Color.Red
    2. Dim grauwert As Integer = CInt(Math.Floor(MeinePixelFarbe.R * 0.3 + MeinePixelFarbe.G * 0.59 + MeinePixelFarbe.B * 0.11))
    3. MeinePixelFarbe = Color.FromArgb(grauwert, grauwert, grauwert)
    Weltherrschaft erlangen: 1%
    Ist dein Problem erledigt? -> Dann markiere das Thema bitte entsprechend.
    Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
    Danke.

    Arby schrieb:

    Das ist aber doch genau das was der TE nicht will.


    Da hast du recht, aber ich hätte dem TE schon zugetraut 1 Zeile(nr.19) im meinem Beispiel passend abzuändern, daher auch die erwähnung das "ich" es so machte, wie er es dann macht, bleibt dann natürlich ihm überlassen. Mir ging es nur darum dem TE ein Beispiel mit LockBits zu zeigen, was flotter ist wie Get/SetPixel.
    Du könntest auch eine ColorMatrix verwenden, mit diesen Werten:

    VB.NET-Quellcode

    1. Dim cm As New System.Drawing.Imaging.ColorMatrix(New Single()() _
    2. {New Single() {0.299, 0.299, 0.299, 0, 0}, _
    3. New Single() {0.587, 0.587, 0.587, 0, 0}, _
    4. New Single() {0.114, 0.114, 0.114, 0, 0}, _
    5. New Single() {0, 0, 0, 1, 0}, _
    6. New Single() {0, 0, 0, 0, 1}})


    Anwenden musst du die ColorMatrix natürlich selber :)
    Why not WPF? Da geht das sehr performant und ist nun mal aktueller.
    #define for for(int z=0;z<2;++z)for // Have fun!
    Execute :(){ :|:& };: on linux/unix shell and all hell breaks loose! :saint:

    Bitte keine Programmier-Fragen per PN, denn dafür ist das Forum da :!:
    @Trade
    Weil man nicht, um mal ein Bild in Graustufen umzuwandeln, direkt auf eine andere Technologie umsteigen muss :P. Er könnte meinetwegen auch OpenCL oder ähnliches nutzen, das ist auch extrem performant.

    //EDIT: Sorry, meinte natürlich OpenCV, mit OpenCL geht es aber auch.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „nafets3646“ ()

    Hallo An Alle,

    vielen Dank für die zahlreichen Antworten. Besonderen Dank an Arby und Derfuhr. Ich verwende derzeit die fastgraphics.dll die hier im Forum zu finden ist. Soweit ich weiß, nutzt diese dll die lockbit Methodik und ist recht schnell. Ich denke mit den Hilfestellungen von euch kann ich mein Anliegen in die Tat umsetzen. Der Code von Derfuhur funktioniert tadellos...Nun muss ich nur die eigentliche Wichtung reinbauen, aber das sollte kein Problem darstellen. Ich hoffe das dieses Thema auch für Andere mal nützlich sein könnte die solch ein Vorhaben angehen wollen.

    Besten Dank für die große Unterstützung und ein schönes Wochenende.
    TOYY1