计算WPF中图像的灰度百分比?

时间:2018-03-27 15:42:20

标签: c# .net vb.net image-processing colors

我有下一个可重复使用的函数来确定图像中灰度的总百分比。它也可以(部分)用于GIF图像。

此代码存在的问题是:

我想将我的代码转换为等效(或更好)的算法,使用WPF类成员来提高其图像处理性能和功能,并且在代码转换过程中修复了我提到的可以解决的问题。

我怎么能这样做?在C#或VB.NET中,选择并不重要。

这是我目前的代码:

VB.NET

Public Shared Function GetGrayScalePercentOfImage(ByVal img As Image) As Double

    Select Case img.PixelFormat

        Case PixelFormat.Format16bppGrayScale
            Return 100.0R

        Case Else
            Dim pixelCount As Integer = (img.Width * img.Height)
            Dim bytesPerPixel As Integer = (Image.GetPixelFormatSize(img.PixelFormat) \ 8)

            If (bytesPerPixel <> 3) AndAlso (bytesPerPixel <> 4) Then
                Throw New NotImplementedException(message:="Only pixel formats that has 3 or 4 bytes-per-pixel are supported.")

            Else
                Dim GrayscalePercentList As New List(Of Double)

                Dim frameDimension As New FrameDimension(img.FrameDimensionsList(0))
                Dim frameCount As Integer = img.GetFrameCount(frameDimension)

                For frameIndex As Integer = 0 To (frameCount - 1)

                    img.SelectActiveFrame(frameDimension, frameIndex)

                    ' Lock the bitmap's bits.
                    Dim bmp As Bitmap = DirectCast(img, Bitmap)
                    Dim rect As New Rectangle(Point.Empty, bmp.Size)
                    Dim data As BitmapData = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat)

                    ' Get the address of the first line.
                    Dim ptr As IntPtr = data.Scan0

                    ' Declare an array to hold the bytes of the bitmap. 
                    Dim numBytes As Integer = (data.Stride * bmp.Height)
                    Dim rgbValues As Byte() = New Byte(numBytes - 1) {}

                    ' Copy the RGB values into the array.
                    Marshal.Copy(ptr, rgbValues, 0, numBytes)

                    ' Unlock the bitmap's bits.
                    bmp.UnlockBits(data)

                    ' Iterate the pixels.
                    Dim grayscalePixelCount As Long ' of current frame.
                    For pixelIndex As Integer = 0 To (rgbValues.Length - bytesPerPixel) Step bytesPerPixel

                        Dim c As Color = Color.FromArgb(red:=rgbValues(pixelIndex + 2),
                                                        green:=rgbValues(pixelIndex + 1),
                                                        blue:=rgbValues(pixelIndex))

                        If (c.R = c.G) AndAlso (c.G = c.B) AndAlso (c.B = c.R) Then
                            grayscalePixelCount += 1
                        End If

                    Next pixelIndex

                    Dim frameGrayscalePercent As Double = ((grayscalePixelCount / pixelCount) * 100)
                    GrayscalePercentList.Add(frameGrayscalePercent)

                    grayscalePixelCount = 0
                Next frameIndex

                Return (GrayscalePercentList.Sum() / frameCount)

            End If

    End Select

End Function

C#(使用代码转换器工具生成,我没有对其进行测试。)

public static double GetGrayScalePercentOfImage(Image img)
{

    switch (img.PixelFormat)
    {

        case PixelFormat.Format16bppGrayScale:
            return 100.0D;

        default:
            int pixelCount = (img.Width * img.Height);
            int bytesPerPixel = (Image.GetPixelFormatSize(img.PixelFormat) / 8);

            if ((bytesPerPixel != 3) && (bytesPerPixel != 4)) {
                throw new NotImplementedException(message:"Only pixel formats that has 3 or 4 bytes-per-pixel are supported.");

            } else {
                List<double> GrayscalePercentList = new List<double>();

                FrameDimension frameDimension = new FrameDimension(img.FrameDimensionsList[0]);
                int frameCount = img.GetFrameCount(frameDimension);

                long grayscalePixelCount = 0; // of current frame.

                int tempVar = frameCount - 1;
                for (int frameIndex = 0; frameIndex <= tempVar; frameIndex++) {

                    img.SelectActiveFrame(frameDimension, frameIndex);

                    // Lock the bitmap's bits.
                    Bitmap bmp = (Bitmap)img;
                    Rectangle rect = new Rectangle(Point.Empty, bmp.Size);
                    BitmapData data = bmp.LockBits(rect, ImageLockMode.ReadOnly, bmp.PixelFormat);

                    // Get the address of the first line.
                    IntPtr ptr = data.Scan0;

                    // Declare an array to hold the bytes of the bitmap. 
                    int numBytes = (data.Stride * bmp.Height);
                    byte[] rgbValues = new byte[numBytes];

                    // Copy the RGB values into the array.
                    Marshal.Copy(ptr, rgbValues, 0, numBytes);

                    // Unlock the bitmap's bits.
                    bmp.UnlockBits(data);

                    // Iterate the pixels.
                    for (int pixelIndex = 0; pixelIndex <= rgbValues.Length - bytesPerPixel; pixelIndex += bytesPerPixel) {

                        Color c = Color.FromArgb(red:rgbValues[pixelIndex + 2], green:rgbValues[pixelIndex + 1], blue:rgbValues[pixelIndex]);

                        if ((c.R == c.G) && (c.G == c.B) && (c.B == c.R)) {
                            grayscalePixelCount += 1;
                        }

                    }

                    double frameGrayscalePercent = ((grayscalePixelCount / (double)pixelCount) * 100);
                    GrayscalePercentList.Add(frameGrayscalePercent);

                    grayscalePixelCount = 0;
                }

                return (GrayscalePercentList.Sum() / frameCount);

            }
    }
}

0 个答案:

没有答案