从vb.net中的Image控件内显示的图片中获取平均RGB值

时间:2015-04-24 02:29:15

标签: wpf vb.net visual-studio-2013

我想从Image控件内显示的图像中获取R,G和B的平均值。此图像的来源是使用this dll从网络摄像头捕获的帧。

即使我找到了一些应该能够执行此操作的功能,但它们可能是for C# using pointers and unsafe codefor Windows Forms,而且我无法让它们与Image一起使用控制。

我应该如何继续计算,或者至少将Image.Source转换为Bitmap才能使用WinForms链接中的函数?

2 个答案:

答案 0 :(得分:3)

这是一个简单,纯粹的WPF解决方案,它直接访问BitmapSource的像素缓冲区。它适用于Bgr24Bgr32Bgra32Pbgra32格式。如果Pbgra32,所有Alpha值都应为255,否则您可能需要将每个像素(预乘)颜色值除以alpha / 255

public Color GetAverageColor(BitmapSource bitmap)
{
    var format = bitmap.Format;

    if (format != PixelFormats.Bgr24 &&
        format != PixelFormats.Bgr32 &&
        format != PixelFormats.Bgra32 &&
        format != PixelFormats.Pbgra32)
    {
        throw new InvalidOperationException("BitmapSource must have Bgr24, Bgr32, Bgra32 or Pbgra32 format");
    }

    var width = bitmap.PixelWidth;
    var height = bitmap.PixelHeight;
    var numPixels = width * height;
    var bytesPerPixel = format.BitsPerPixel / 8;
    var pixelBuffer = new byte[numPixels * bytesPerPixel];

    bitmap.CopyPixels(pixelBuffer, width * bytesPerPixel, 0);

    long blue = 0;
    long green = 0;
    long red = 0;

    for (int i = 0; i < pixelBuffer.Length; i += bytesPerPixel)
    {
        blue += pixelBuffer[i];
        green += pixelBuffer[i + 1];
        red += pixelBuffer[i + 2];
    }

    return Color.FromRgb((byte)(red / numPixels), (byte)(green / numPixels), (byte)(blue / numPixels));
}

由于Image控件的Source属性属于ImageSource类型,因此必须先将其强制转换为BitmapSource,然后再将其传递给方法:

var bitmap = (BitmapSource)image.Source; 
var color = GetAverageColor(bitmap);

答案 1 :(得分:1)

已编辑以支持WPF图像控制(仍需要参考System.Drawing)。

Public Function GetWPFImageAverageRGB(wpfImage As System.Windows.Controls.Image) As System.Drawing.Color
    Using ms = New IO.MemoryStream()
        Dim encoder = New JpegBitmapEncoder()
        encoder.Frames.Add(BitmapFrame.Create(CType(wpfImage.Source, BitmapImage)))
        encoder.Save(ms)

        Using bmp = CType(System.Drawing.Bitmap.FromStream(ms), System.Drawing.Bitmap)
            Dim reds As Long
            Dim greens As Long
            Dim blues As Long

            For x = 0 To bmp.Width - 1
                For y = 0 To bmp.Height - 1
                    With bmp.GetPixel(x, y)
                        reds += .R
                        greens += .G
                        blues += .B
                    End With
                Next
            Next

            Dim count = bmp.Height * bmp.Width

            Return System.Drawing.Color.FromArgb(CInt(reds / count), CInt(greens / count), CInt(blues / count))
        End Using
    End Using
End Function

用法:

With GetWPFImageAverageRGB(image) 'image is a System.Windows.Controls.image
   Console.WriteLine("Average: R={0}, G={1}, B={2}", .R, .G, .B)
   Console.ReadKey()
End With