2

I have two images(original and noisy). I'm calculating PSNR. I kinda did it for color RGB images, but i don't know how to do it with grayscale. As i read, MSE calculation is different. For RGB i'm doing it like you can see in following code (I'm using Visual C#):

for (int i = 0; i < bmp1.Width; i++)
            {
                for (int j = 0; j < bmp1.Height; j++)
                {
                    mseR += Math.Pow(bmp1.GetPixel(i, j).R - bmp2.GetPixel(i, j).R, 2);
                    mseG += Math.Pow(bmp1.GetPixel(i, j).G - bmp2.GetPixel(i, j).G, 2);
                    mseB += Math.Pow(bmp1.GetPixel(i, j).B - bmp2.GetPixel(i, j).B, 2);

                }
            }
      mse = (mseR + mseG + mseB) / ((bmp1.Width * bmp1.Height) * 3);

Here I am manipulating with R,G,B of pixels.But i don't know what should i take in case of grayscale images. Can I use RGB aswell, because it actually gives some results, or i should take something else?

Errorfreak
  • 79
  • 2
  • 9

1 Answers1

1

To make grayscale you can make the picture out of averages (no need to vary your implementation). I'm assuming your images are bmp1 = grayImage and bmp2 = noisy image.

for (int i = 0; i < bmp1.Width; i++)
{
    for (int j = 0; j < bmp1.Height; j++)
    {
        // As a grayscale image has rthe same color on all RGB just pick one
        int gray1 = bmp1.GetPixel(i, j).R;
        int gray2 = bmp2.GetPixel(i, j).R;
        double sum = Math.Pow(gray1 - gray2, 2)
        mseGray += sum;
    }
}
mse = (mseGray) / ((bmp1.Width * bmp1.Height) * 3);

Also getting pixels one at a time is a slow process look into using the indexes, and a optimization in the loop. It should give about a tenfold in performance.

You need to make the bitmap into an indexable img, I'm assuming its BitmapSource for this example. the interesting part is the loop and the index building and not the precode, the precode is just to make the image indexable.

var height = bmp1.Height;
var width = bmp1.Width;
var pixelBytes1 = new byte[height * width * 4];
var pixelBytes2 = new byte[height * width * 4];
bmp1.CopyPixels(pixelBytes1, stride, 0);
bmp2.CopyPixels(pixelBytes2, stride, 0);

for (int x = 0; x < width; x++)
{
    int woff = x * height;
    for (int y = 0; y < height; y++)
    {(R*0.3 + G*0.59+ B*0.11)
        int index = woff + y;
        int gray1 = bmp1[index];
        int gray2 = bmp2[index];
        double sum = Math.Pow(gray1 - gray2, 2)
        mseGray += sum;
    }
}
mse = (mseGray) / ((bmp1.Width * bmp1.Height) * 3);

EDIT:

http://www.mathworks.com/matlabcentral/answers/49906-how-to-calculate-psnr-of-compressed-images-and-how-to-compare-psnr-of-images-compressed-by-two-diff

I'm having an issue with your implementation of PSNR though im thinking its not per definition here is an example from java (very similar to C#) http://www.cyut.edu.tw/~yltang/program/Psnr.java

Thomas Andreè Wang
  • 3,379
  • 6
  • 37
  • 53
  • This answer contains a lot of valid points, but it assumes the original greyscale -> RGB conversion as used by .NET assigns equal weight to the R, G and B components. Is there any documentation on that? always assumed it it uses some luminance-preserving distribution like Y = 0.2126 R + 0.7152 G + 0.0722 B. Disregarding the origin of the RGB distribution, you could still argue luminance is the best approach to PSNR in grayscale images. – Paul-Jan Mar 08 '15 at 10:32
  • actually, the only difference is if you shift the RGB before you convert to gray. the method i applied is indeed a little naive. if you want the luminance then you want `int gray = (int)(R*0.3 + G*0.59+ B*0.11)` (edited the answer) – Thomas Andreè Wang Mar 08 '15 at 10:48
  • 1
    In hindsight my comment about the .NET grayscale -> RGB conversion is before-morning-coffee drivel indeed. I'll leave it there as a permanent token of shame. :) – Paul-Jan Mar 08 '15 at 11:12
  • So, my code sample in the top is not right? I suppose, for color images i can use your code as well, with the only difference, that with colored image you don't need to multiply R, G and B by 0.3, 0.59, 0.11? – Errorfreak Mar 08 '15 at 12:36
  • @Thomas Wait, is it for images, that were grayscale originally, or for converting color images into grayscale? Because i have first case. This question is little bit dumb and slow, but i got confused. – Errorfreak Mar 09 '15 at 09:14
  • My answer is for converting and PSNR, if you have grayscale images then you should be able to run it the same way just skip the color to gray conversion. – Thomas Andreè Wang Mar 09 '15 at 09:23
  • The link (cyut.edu.tw) is dead. – Robinson Mar 28 '22 at 13:07