有没有更快的方法将位图像素转换为灰度?

4
目前,我在使用SetPixel()方法来更改位图中每个像素的颜色。对于小尺寸的图片,这种方法效果良好,但是当我在大图像上测试时,处理时间会比较长。由于我之前没有在VB.Net中处理图像,所以可能忽略了一些明显的问题。我正在编写一个将图像转换为灰度的程序。这确实可以产生正确的结果,但速度较慢,并且在此期间UI会冻结,因此我希望尽可能提高转换速度。以下是我的当前代码:
Dim tmpImg As New Bitmap(img) '"img" is a reference to the original image 
For x As Integer = 0 To tmpImg.Width - 1
    For y As Integer = 0 To tmpImg.Height - 1
        Dim clr As Byte
        With tmpImg.GetPixel(x, y)
            clr = ConvertToGrey(.R, .G, .B)
        End With
        tmpImg.SetPixel(x, y, Color.FromArgb(clr, clr, clr))
    Next
Next

Private Function ConvertToGrey(ByVal R As Byte, ByVal G As Byte, ByVal B As Byte) As Byte
    Return (0.2126 * R) + (0.7152 * B) + (0.0722 * G)
End Function

使用ColorMatrix或类似AForge的库可能会更快。 - Ňɏssa Pøngjǣrdenlarp
@Plutonix 谢谢,我会研究ColorMatrix,但我不太愿意使用库。 - Piratica
可能是Can I convert bitmaps with OpenMP in C#?的重复问题。 - Hans Passant
这个问题似乎不适合在这里讨论,因为它涉及到优化工作中的代码。请尝试访问http://codereview.stackexchange.com。 - Jongware
1个回答

5

“快”是一个相对的概念,但这个程序可以在10-12毫秒(显然取决于系统)内将一张480x270的图片转换为灰度图像,这个速度似乎并不算太慢。我非常确信它会比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

这些值是从.299、.587、.114四舍五入得来的。


对于一张1280*720的图像,处理时间大约为80毫秒。考虑到它所做的事情,我对此没有任何问题。 - Ňɏssa Pøngjǣrdenlarp
谢谢,我以前从未听说过ColorMatrix,但是研究它后发现它非常复杂。然而结果非常出色,我在一张3008 x 2000的图片上只用了1028毫秒(约1秒),而之前同样的图片需要297273毫秒(4分钟57秒)。显然这是一个巨大的改进,我将继续阅读这篇文章直到理解为止。 - Piratica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接