2015-03-08 3 views
1

У меня есть два изображения (оригинальные и шумные). Я расчитываю PSNR. Я сделал это для цветных RGB-изображений, но я не знаю, как это сделать с оттенками серого. Поскольку я читаю, расчет MSE отличается. Для RGB я делаю это, как вы можете увидеть в следующий код (я использую Visual C#):Расчет MSE для изображений в оттенках серого

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); 

Здесь я манипулируя с R, G, B из pixels.But я не знаю, что я должен взять в случае изображений в оттенках серого. Могу ли я использовать RGB, потому что он действительно дает некоторые результаты, или я должен взять что-то еще?

ответ

1

Чтобы сделать оттенки серого, вы можете сделать изображение из средних (не нужно изменять вашу реализацию). Я предполагаю, что ваши изображения: bmp1 = grayImage и bmp2 = шумное изображение.

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); 

Также получение пикселей один в то время, это медленный процесс, изучить с помощью индексов, а также оптимизацию в цикле. Это должно в десять раз повысить производительность.

Вам нужно сделать растровое изображение в индексируемом img, я предполагаю его BitmapSource для этого примера. интересная часть - это цикл и построение индекса, а не предел, прекод - просто сделать изображение индексируемым.

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

У меня возникли проблемы с вашей реализации PSNR, хотя им думать его не по определению здесь пример из Java (очень похож на C#) http://www.cyut.edu.tw/~yltang/program/Psnr.java

+0

Этот ответ содержит много действительных точек, но предполагает, что исходное преобразование оттенков серого -> RGB, используемое .NET, присваивает равный вес компонентам R, G и B. Есть ли какие-либо документы по этому поводу? всегда считал, что он использует некоторое распределение, сохраняющее яркость, как Y = 0.2126 R + 0.7152 G + 0.0722 B. Без учета происхождения распределения RGB вы все же можете утверждать, что яркость - лучший подход к PSNR в изображениях в оттенках серого. –

+0

Фактически, единственное различие заключается в том, что вы перемещаете RGB перед преобразованием в серый. метод, который я применил, действительно немного наивен. если вам нужна яркость, тогда вы хотите «int gray = (int) (R * 0.3 + G * 0.59 + B * 0.11)» (отредактирован ответ) –

+1

Оглядываясь назад, мой комментарий о преобразовании .NET grayscale -> RGB - действительно, ковер. Я оставлю его там как постоянный знак стыда. :) –

Смежные вопросы