
Когда мне на учебе дали задание написать две метрики для оценки различия двух картинок, в частности качества видоизмененной от исходной, меня это конечно все это немного смутило. Знания в программировании были, мягко говоря, не очень большими, как-никак был только на первом курсе. Благо, какую библиотеку выбрать сказали заранее, так что с этим труда не возникло. А вот как ее использовать это было уже на порядок сложнее, все, что я в основном смог нарыть в интернете, было на английском, хоть я его и знаю на уровне, что могу читать тех. литературу, вследствие огромности самой библиотеки, подходило мало. Отлично, что удалось, какие функции и как использовать, я смог потом уточнить у преподавателя. А требовалось только понять как обращаться к самой картинке, в частности к отдельным пикселям изображения. Кого заинтересовало, добро пожаловать под кат.
PSNR/SSIM
Начнем с того, что же это такое PSNR и SSIM. Как нам подсказывает википедия. PSNR — peak signal-to-noise ratio, наиболее часто используется для измерения уровня искажений при сжатии изображений. А найдем мы ее так. При этом все будет зависеть от битности изображения.

Где MSE среднеквадратичное отклонение

SSIM же считается более сложно, и был создан для более точного определения различности двух изображений, если так можно выразиться. Особенностью является, что он всегда лежит в промежутке от -1 до 1, причем при его значении равном 1, означает, что мы имеем две одинаковые картинки. Общая формула имеет вид

Тут









Код
Каюсь, стиль программирования у меня наверняка не очень хорош, но не судите меня строго, у меня ведь не так много опыта и обещаю все время улучшать его. В рамках данной статьи я ограничусь разбором только SSIM метрики. Для начала надо будет иметь под рукой Visual Studio`у. Тут мне достаточно просто удалось понять, как же добавить в проект изначально выбранную библиотеку. Нужно добавить заголовочные файлы, ну и сами файлы в ново созданный проект. Более подробно это написано тут.
Для объяснения моего написанного кода, я сделаю ставку на её комментирование по ходу. Код не слишком длинен, так что его можно будет понять. Ну что ж, приступим.
Указатели на картинки мы получим так.
IplImage* img1 = cvvLoadImage("before.bmp");
IplImage* img2 = cvvLoadImage("after.bmp");
Битность можно определить
img->depth
То есть достаточно просто.Для нахождения искомых величин я написал парочку своих функций. Для нахождения

(img->width)*(img->height)
double avg(IplImage* img){
unsigned char* ptr;
int x,y,b=0,g=0,r=0,col=0;
for(x=0;x<=img->width;x++){
for(y=0;y<=img->height;y++){
ptr=(uchar*)(img->imageData+y*img->widthStep); //подсчитаем среднее значение для каждого компонента цветов
b=ptr[3*x];
g=ptr[3*x+1]; // вот так мы как раз обращаемся к различным компонентам цветов
r=ptr[3*x+2]; // b - blue, r - red, g - green
col+=b+g+r;
}}
return col/3.00;
}
Среднеквадратичное отклонение так, тут нам придется помимо всего прочего передавать и ранее полученные средние значения.
double var(IplImage* img, double mu){ //variance
unsigned char* ptr;
int x,y,b=0,g=0,r=0;
double col=0;
for(x=0;x<=img->width;x++){
for(y=0;y<=img->height;y++){
ptr=(uchar*)(img->imageData+y*img->widthStep);
b=ptr[3*x];
col+=(abs(1.0*b-mu))*(abs(1.0*b-mu));
g=ptr[3*x+1];
col+=(abs(1.0*g-mu))*(abs(1.0*g-mu));
r=ptr[3*x+2];
col+=(abs(1.0*r-mu))*(abs(1.0*r-mu));
}}
return col;
}
А ковариацию вот так вот:
double cov(IplImage* img1,IplImage* img2,double mu1,double mu2){ //covariance
unsigned char* ptr;
int x,y,b1=0,g1=0,r1=0,b2=0,g2=0,r2=0;
double col=0;
for(x=0;x<=img1->width;x++){
for(y=0;y<=img1->height;y++){
ptr=(uchar*)(img1->imageData+y*img1->widthStep);
b1=ptr[3*x];
g1=ptr[3*x+1];
r1=ptr[3*x+2];
ptr=(uchar*)(img2->imageData+y*img2->widthStep);
b2=ptr[3*x];
g2=ptr[3*x+1];
r2=ptr[3*x+2];
col+=(b1-mu1)*(b2-mu2)+(g1-mu1)*(g2-mu2)+(r1-mu2)*(r2-mu2);
}}
return col;
}
По сути нам только остается подставить полученные значения в выше стоящую формулу. Так же не надо забывать освобождать память.
cvReleaseImage(&img1);
cvReleaseImage(&img2);
P.S.
Скачать саму библиотеку вы сможете тут. Много чего интересного про OpenCV здесь (спасибо ZlodeiBaal). Так же в дальнейшем мне бы хотелось бы написать статью, похожей на эту, но уже про работу с видео и использованием уже других библиотек.У кого возникли вопросы или заметили ошибки, или просто хотите похвалить автора, пишите, обязательно отвечу.