Привести изображение к оттенкам серого и получить одномерный массив зачений его пикселей

WMC

Здравствуйте. Модифицируйте пожалуйста код так, чтобы получаемое на данном этапе разработки изображение привелось к оттенкам серого. И получить одномерный массив значений яркости пикселей.
Option Strict On
Imports System.Drawing
Public Class Form1
 
    Private Sub Form1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Click
        Dim x, Y, c, r, g, b, threshold As Integer
        Dim blackPen As New Pen(Color.Black, 1)
        Dim whitePen As New Pen(Color.White, 1)
        Dim tempPen As Pen
        Dim myGraphics As Graphics = MyBase.CreateGraphics()
        Dim bmp As New Bitmap("C:\x40.png")
 
        threshold = 20
        Me.Height = bmp.Height + 5
        Me.Width = bmp.Width + 5
        For Y = 0 To bmp.Height - 1
            For x = 0 To bmp.Width - 1
 
                r = bmp.GetPixel(x, Y).R
                g = bmp.GetPixel(x, Y).G
                b = bmp.GetPixel(x, Y).B
 
                If (r - b) > threshold And (r - g) > threshold Then
 
                    tempPen = New Pen(bmp.GetPixel(x, Y), 1)
                    myGraphics.DrawEllipse(tempPen, x, Y, 1, 1)
                Else
                    myGraphics.DrawEllipse(whitePen, x, Y, 1, 1)
                End If
 
            Next
        Next
 
    End Sub
 
End Clas
4 ответа

WMC

Перевод цветного изображения в серый.
Imports System.IO
Imports System.Drawing.Imaging
'…
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Try
        Dim bmp As Bitmap = loadBitmap("tst1.jpg")
        If bmp Is Nothing Then Exit Sub
        PictureBox1.Image = bmp
        Dim myGrey As New Bitmap(getGrey(bmp))
        PictureBox2.Image = myGrey
        myGrey.Save("bmpGr.bmp", ImageFormat.Bmp)
    Catch ex As Exception
        MsgBox(ex.Message)
    End Try
End Sub
Public Function loadBitmap(ByVal nmFile As String) As Bitmap
    Dim img As Bitmap
    If File.Exists(nmFile) Then
        Using fs As New FileStream(nmFile, FileMode.Open, FileAccess.Read, FileShare.Read)
            img = New Bitmap(fs)
        End Using
    Else
        img = Nothing
    End If
    Return img
End Function
Private Function getGrey(ByVal bmp As Bitmap) As Bitmap
    Dim w As Integer = bmp.Width
    Dim h As Integer = bmp.Height
    Dim bmpRGB As Bitmap = bmp.Clone(New Rectangle(0, 0, w, h), PixelFormat.Format24bppRgb)
    Dim bmpGr As New Bitmap(w, h, PixelFormat.Format24bppRgb)
    Dim cm As ColorMatrix
    cm = New ColorMatrix(New Single()() _
                         {New Single() {0.299, 0.299, 0.299, 0, 0}, _
                          New Single() {0.587, 0.587, 0.587, 0, 0}, _
                          New Single() {0.114, 0.114, 0.114, 0, 0}, _
                          New Single() {0, 0, 0, 1, 0}, _
                          New Single() {0, 0, 0, 0, 1}})
    Dim imgattr As New ImageAttributes()
    Dim rect As New Rectangle(0, 0, w, h)
    Try
        imgattr.SetColorMatrix(cm)
        Using gr As Graphics = Graphics.FromImage(bmpGr)
            gr.DrawImage(bmpRGB, rect, 0, 0, w, h, GraphicsUnit.Pixel, imgattr)
        End Using
        Return bmpGr
    Catch ex As Exception
        MsgBox(ex.Message)
        Return Nothing
    End Try
End Function


WMC

WMC, как вариант можно ПОПИКСЕЛЬНО перекрашивать изображение в оттенки серого: (Но этот вариант работает немного медленнее, чем вариант, представленный выше):
    Public Function ToBlack_And_White(SourceImage As Image) As Image
        If SourceImage IsNot Nothing Then
            Dim Img As New Bitmap(SourceImage, SourceImage.Width, SourceImage.Height)
            Dim PixelColor As Color
            Dim PaintToGray As Byte
            For x As Integer = 0 To Img.Width - 1
                For y As Integer = 0 To Img.Height - 1
                    PixelColor = Img.GetPixel(x, y)
                    'Если пиксель не прозрачный, то перекрашиваем его в серый цвет
                    If PixelColor <> Color.FromArgb(0) Then
                        PaintToGray = 0.3 * PixelColor.R + 0.59 * PixelColor.G + 0.11 * PixelColor.B
                        PixelColor = Color.FromArgb(PaintToGray, PaintToGray, PaintToGray)
                        Img.SetPixel(x, y, PixelColor)
                    End If
                Next
            Next
            Return Img
        End If
        Return Nothing
    End Function
ну и в завершение темы ответ на второй вопрос
получить одномерный массив значений яркости пикселей
        Dim BrightnessArray As New ArrayList
 
        Using img As Bitmap = New Bitmap(PictureBox1.Image)
            For x As Integer = 0 To img.Width - 1
                For y As Integer = 0 To img.Height - 1
                    Application.DoEvents()
                    BrightnessArray.Add(x & ", " & y & "  -  " & img.GetPixel(x, y).GetBrightness)
                Next
            Next
        End Using


WMC

Из ЛС
Этот алгоритм выполняет свою задачу быстро? Как он вкратце это делает? В итоге получается "правильное" монохромное в серых оттенках?
1. Достаточно быстро, я бы даже сказал максимально быстро. 2. Вкратце не получится. Разбирайте код. 3. Так все же монохромное или в оттенках серого и что такое "правильное"? В данном случае получаем изображение в оттенках серого. Для использования в ваших задачах потребует некоторой доработки.


WMC

и что такое "правильное"?
изображение, имеющее множество значений тона, и их непрерывное, плавное изменение.