Fast is a relative term, but this will convert a 480x270 image to greyscale in 10-12 ms (obviously system dependent) which does not seem unduly long. I'm quite sure it will be faster than SetPixel.
Private Function GrayedImage(orgBMP As Bitmap) As Bitmap
Dim grayscale As New Imaging.ColorMatrix(New Single()() _
{New Single() {0.3, 0.3, 0.3, 0, 0},
New Single() {0.59, 0.59, 0.59, 0, 0},
New Single() {0.11, 0.11, 0.11, 0, 0},
New Single() {0, 0, 0, 1, 0},
New Single() {0, 0, 0, 0, 1}})
Dim bmpTemp As New Bitmap(orgBMP)
Dim grayattr As New Imaging.ImageAttributes()
grayattr.SetColorMatrix(grayscale)
Using g As Graphics = Graphics.FromImage(bmpTemp)
g.DrawImage(bmpTemp, New Rectangle(0, 0, bmpTemp.Width, bmpTemp.Height),
0, 0, bmpTemp.Width, bmpTemp.Height,
GraphicsUnit.Pixel, grayattr)
End Using
Return bmpTemp
End Function
Values are rounded from .299, .587, .114