python/c++计算psnr

import cv2
import numpy as np
import math

def psnr(target, ref):
    #将图像格式转为float64
    target_data = np.array(target, dtype=np.float64)
    ref_data = np.array(ref,dtype=np.float64)
    # 直接相减,求差值
    diff = ref_data - target_data
    # 按第三个通道顺序把三维矩阵拉平
    diff = diff.flatten('C')
    # 计算MSE值
    rmse = math.sqrt(np.mean(diff ** 2.))
    # 精度
    eps = np.finfo(np.float64).eps
    if(rmse == 0):
        rmse = eps
    return 20*math.log10(255.0/rmse)

# 计算单通道图像
IMG_1 = cv2.imread("yuer.jpg",0)
IMG_2 = cv2.imread("june.jpg",0)

# 计算三通道图像(假如输入的是三通道图像的话)
# IMG_1 = cv2.imread("yuer.jpg")
# IMG_2 = cv2.imread("june.jpg")

# 这里resize是因为我使用的两张图大小不一样,所以resize到同样的大小
# 正常情况下待计算psnr的两张图一般是相同大小的,不需要resize
# 而且大小不同的两张图,resize后求得的psnr也没有啥意义
IMG_1 = np.resize(IMG_1, (100,100))
IMG_2 = np.resize(IMG_2, (100,100))

print(psnr(IMG_1,IMG_2))

python计算psnr的时候可能会出现和其他方法计算出的psnr结果不同,相差比较大,这种情况一般是因为python里面的unit8和float数据类型造成的,把图片数据先转成float类型的再计算,一般不会出错。

另外,假如两个人算的psnr不同,但误差不大不小,差个一两dB,不是特别夸张的情况下,有可能是其中一个是按三通道计算的,另一个是按照单通道计算的。

这些都是容易忽略的坑,特此记录一下。 

//输入格式是Mat类型,I1,I2代表是输入的两幅图像
double getPSNR(const Mat& I1, const Mat& I2)
{
    Mat s1;
    absdiff(I1, I2, s1);       // |I1 - I2|AbsDiff函数是 OpenCV 中计算两个数组差的绝对值的函数
    s1.convertTo(s1, CV_32F);  // 这里我们使用的CV_32F来计算,因为8位无符号char是不能进行平方计算
    s1 = s1.mul(s1);           // |I1 - I2|^2

    Scalar s = sum(s1);         //对每一个通道进行加和

    double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels

    if (sse <= 1e-10) // 对于非常小的值我们将约等于0
        return 0;
    else
    {
        double  mse = sse / (double)(I1.channels() * I1.total());//计算MSE
        double psnr = 10.0 * log10((255 * 255) / mse);
        return psnr;//返回PSNR
    }
}

int main()
{
    //先定义PSNR
    double psnr;
    //然后读取输入的两幅图像
    Mat img1 = imread("101.jpg");
    Mat img2 = imread("103.jpg");
    //调用函数
    psnr = getPSNR(img1, img2);
    cout << psnr << endl;
}

你可能感兴趣的:(Python,图像处理,python,opencv,计算机视觉)