张家口人才网:opencv-9-图像噪声以及评估指标 PSNR 与SSIM

admin 5个月前 (05-01) 科技 41 0

最先之前

我们在将 opencv 的图像显示在了 qt 的label 上, 我们能够将图显示在label 上, 用于显示我们的算法,
我们在 opencv 上一篇文章中先容了 opencv 的核操作, 我们这里就要进入一个很主要的章节了,图像滤波操作, 也是图像核操作应用的一个很主要的章节,

那我们就从降噪的角度完整的讲一下, 并通过 opencv 核的方式举行图像算法操作, 【手艺综述】一文道尽传统图像降噪方式 这篇文章写的还算对照完整, 也是传统的算法的一个综述历程,

目录

目录
  • 最先之前
  • 目录
  • 前言
  • 图像降噪理论基础
    • 图像噪声的发生
    • 图像噪声的模子
  • 图像降噪操作
    • 噪声添加
    • 噪声量化方式
    • opencv 盘算 PSNR 和 SSIM
    • 算法噪声数据
      • 椒盐噪声测试
      • 高斯噪声测试
  • 总结
  • 参考

前言

数字成像历程中由于电噪声以及其他因素, 导致我们获取到的图像存在噪声,噪声出现在输入部门, 在后续的每个步骤都市受到影响, 以是在数字图像处置的前面必须要举行的一个步骤就是 图像降噪

每个做信号处置的都市接触到一类问题 , 信号降噪, 让人最头疼的一门课,真是谢谢先生给过, 然则后面自己用到的时刻反而感受真的好用, 原来是这样, 然后就逐步学会了怎么使用吧..(感受照样弱鸡)
知乎可复现的图像降噪算法总结这篇文章列出了一个能够复现的图像降噪操作算法列表, 近年来实现了的算法可以见reproducible-image-denoising-state-of-the-art, 之后使用响应的文章举行算法实现吧.( 又立了一个 flag )

图像降噪理论基础

图像降噪主要的目的是在举行去除图像噪声的同时保留尽可能多的主要特征, 对于人眼来说, 区分噪声还算对照容易, 然则对于盘算机来说,输入的都是数据, 我怎么区分哪个是噪声, 哪个不是噪声呢, 这里就要引入噪声的理论基础了

图像噪声的发生

我们在之前的章节先容了图像的程序系统, 现实上在成像历程中可能由于点噪声, 量化历程等造成噪声,
现实上的噪声主要分为三种:

  1. 加性噪声: 与输入无关, \(f(x,y) = g(x,y) +n(x,y)\)
  2. 乘性噪声: 与输入信号有关, \(f(x,y) = g(x,y) + n(x,y) \cdot g(x,y)\)
  3. 量化噪声: 与输入无关, 在图像量化历程噪声的量化误差导致的噪声,

现实上后两种很难解决, 现在处置的都是以 加性噪声为主, 属于随机的噪声信号, 凭据统计学的看法, 噪声在无限长时间窗内的噪声和为0, 在第一类中的 \(n(x,y)\) 随着时间存在正负信号的不确定转变.

上图所示虚线代表真实信号,红蓝线示意的就是随机噪声信号,所有的随机噪声信号求和后效果为0。

这里关于噪声的说明可以参考图像去噪算法简介

噪声在理论上可以界说为“不能展望,只能用概率统计方式来熟悉的随机误差”。因此将图像噪声看成是多维随机历程是合适的,因而形貌噪声的方式完全可以借用随机历程的形貌,即用其概率漫衍函数和概率密度漫衍函数。但在许多情形下,这样的形貌方式是很庞大的,甚至是不能能的。而现实应用往往也不必要。通常是用其数字特征,即均值方差,相关函数等。由于这些数字特征都可以从某些方面反映出噪声的特征。

我以为图像噪声的成因分类与常见图像去噪算法简介这篇文章关于噪声的分类部门讲的还对照细, 可以参考

图像噪声的模子

由于我们以为噪声在时间尺度的随机性, 然则我们可以使用噪声的概率漫衍与概率密度函数举行形貌, 那么我们就能将噪声凭据其漫衍特点举行分类,
我们稍微先容一下常见的噪声模子吧

噪声模子主要可以分为:

  • 高斯噪声,高斯噪声模子经常被用于实践中。
  • 脉冲噪声(椒盐噪声),图像上一个个点,也可称为散粒和尖峰噪声。
  • 伽马噪声
  • 瑞利噪声
  • 指数漫衍噪声
  • 均匀漫衍噪声

这里能查到的资料许多, 可以看我们的参考部门, 内容都一样, 再写只是浪费时间和精神, 有兴趣的可以自己翻阅

图像降噪操作

实在吧, 我就不应该讲那么多, 直接最先图像处置部门就行了, 为了最先举行图像处置, 我们要先举行一点小事情, 我们要按造以下步骤举行降噪算法的对照,

  1. 选择尺度图像--- lena.png
  2. 添加噪声
  3. 量化噪声
  4. 降噪操作
  5. 量化效果值
  6. 对照效果

在我们举行算法比对之前, 我们选择的是 lena 的图像, 加入随机噪声, 然后盘算出来 一个噪声的比例, 举行降噪操作, 再次盘算以下噪声参数, 看下效果值.

若是是举行算法对照的时刻, 最好选择现有的降噪的数据集举行对照, 好比, Kodak , BSD

噪声添加

我们以为噪声是随机的, 我们天生随机数加在原始图像上便能够获得噪声图像, opencv 没有提供响应的实现, 然则知道原理了, 写起来都对照简单, 我对照喜欢
图像处置基础(1):噪声的添加和过滤 使用的方式, 他使用的是 梅森旋转算法 来实现的伪随机算法,

实在吧这里我也不懂, 然则随机数能用就行了, 我又不是数学家, 然后看到了 谈谈梅森旋转:算法及其爆破

这里就不重复造轮子了, 直接复制他给出的代码就好,

// 添加椒盐噪声 // 天生 随机 num 个 白点
void addSaltNoise(Mat &m, int num)
{
	// 随机数发生器
	std::random_device rd; //种子
	std::mt19937 gen(rd()); // 随机数引擎

	auto cols = m.cols * m.channels();

	for (int i = 0; i < num; i++)
	{
		auto row = static_cast<int>(gen() % m.rows);
		auto col = static_cast<int>(gen() % cols);

		auto p = m.ptr<uchar>(row);
		p[col++] = 255;
		p[col++] = 255;
		p[col] = 255;
	}
}

// 添加Gussia噪声
// 使用指针接见
void addGaussianNoise(Mat &m, int mu, int sigma)
{
	// 发生高斯漫衍随机数发生器
	std::random_device rd;
	std::mt19937 gen(rd());

	std::normal_distribution<> d(mu, sigma);

	auto rows = m.rows; // 行数
	auto cols = m.cols * m.channels(); // 列数

	for (int i = 0; i < rows; i++)
	{
		auto p = m.ptr<uchar>(i); // 取得行首指针
		for (int j = 0; j < cols; j++)
		{
			auto tmp = p[j] + d(gen);
			tmp = tmp > 255 ? 255 : tmp;
			tmp = tmp < 0 ? 0 : tmp;
			p[j] = tmp;
		}
	}
}

噪声量化方式

这里实在涉及到图像质量评估的领域,可以参考图像质量评价概述(评估指标、传统检测方式)先容的方式, 存在太多的盘算方式,

我们必须选择一个量化噪声的方式举行图像质量的评估, 一样平常举行噪声评估手段就是噪声比(Signal to Noise Ratio,SNR),峰值信噪比(Peak Signal to Noise Ratio, PSNR) , 均方差值(Mean Square Error, MSE), 结构相似性(Structural SIMilarity, SSIM),

我们一个一个来看, 均方差值是用于对照两幅图像 K, I 的均方差值

\[MSE=\frac{1}{mn}\sum_{i=0}^{n-1}\sum_{j=0}^{m-1}\parallel K(i,j)-I(i,j)\parallel^{2} \]

峰值信噪比PSNR权衡图像失真或是噪声水平的客观尺度。2个图像之间PSNR值越大,则越相似。普遍基准为30dB,30dB以下的图像劣化较为显著。界说为,

\[PSNR=10log_{10}(\frac{MAX^{2}}{MSE}) \]

其中\(MAX^2\) 为图片可能的最大像素值。若是每个像素都由 8 位二进制来示意,那么就为 255。

SNR用于形貌信号与噪声的比值

\[SNR (dB)=10 log_{10} \left[ \frac{\sum_{x=0}^{m-1} \sum_{y=0}^{n-1}(f(x, y))^{2}}{\sum_{x=0}^{m-1} \sum_{y=0}^{n-1}(f(x, y)-\hat{f}(x, y))^{2}}\right] \]

SSIM 形貌两个图像的相似性, 通过三个举行对照, 亮度,对比度和结构, 参考图像质量评价指标之 PSNR 和 SSIM

\[l(x, y)=\frac{2 \mu_{x} \mu_{y}+c_{1}}{\mu_{x}^{2}+\mu_{y}^{2}+c_{1}} c(x, y)=\frac{2 \sigma_{x} \sigma_{y}+c_{2}}{\sigma_{x}^{2}+\sigma_{y}^{2}+c_{2}} s(x, y)=\frac{\sigma_{x y}+c_{3}}{\sigma_{x} \sigma_{y}+c_{3}} \]

\[\operatorname{SSIM}(x, y)=\frac{\left(2 \mu_{x} \mu_{y}+c_{1}\right)\left(2 \sigma_{x y}+c_{2}\right)}{\left(\mu_{x}^{2}+\mu_{y}^{2}+c_{1}\right)\left(\sigma_{x}^{2}+\sigma_{y}^{2}+c_{2}\right)} \]

一样平常取\(c_3 = \frac{c_2}{2}\)
\(u_x\)\(x\) 的均值
\(u_y\)\(y\) 的均值
\(\sigma_x^2\)\(x\) 的方差
\(\sigma_y^2\)\(y\) 的方差
\(\sigma_{xy}\)\(x\)\(y\) 的协方差
\(c_1 = (k_1 L)^2, c_2=(k_2 L)^2\) 为两个常数,避免去零
\(L\) 为像素值的局限,\((0,255)\)
\(k_1 = 0.01, k_2 = 0.03\) 为默认值
默认参数\(\alpha = 1, \beta = 1, \gamma = 1\)

opencv 盘算 PSNR 和 SSIM

原本不想写这么多的, 然则 opencv 给出了一个例程Similarity check (PNSR and SSIM) on the GPU, 提供了盘算的方式, 自己不用去写了, 岂不是很爽, 以是上面就详细先容了各个方式的使用.
官方给出了通俗版本以及 GPU 加速的版本, 我们暂时只使用基础的版本就好,
PSNR返回一个浮点数,若是两个输入在30到50之间相似(越高越好)。
SSIM返回图像的MSSIM。这也是一个介于零和一之间的浮点数(越高越好),然则每个通道都有一个浮点数。因此,我们返回一个Scalar OpenCV数据结构:

double getPSNR(const Mat& I1, const Mat& I2)
{
    Mat s1;
    absdiff(I1, I2, s1);       // |I1 - I2|
    s1.convertTo(s1, CV_32F);  // cannot make a square on 8 bits
    s1 = s1.mul(s1);           // |I1 - I2|^2
    Scalar s = sum(s1);         // sum elements per channel
    double sse = s.val[0] + s.val[1] + s.val[2]; // sum channels
    if( sse <= 1e-10) // for small values return zero
        return 0;
    else
    {
        double  mse =sse /(double)(I1.channels() * I1.total());
        double psnr = 10.0*log10((255*255)/mse);
        return psnr;
    }
}
Scalar getMSSIM( const Mat& i1, const Mat& i2)
{
    const double C1 = 6.5025, C2 = 58.5225;
    /***************************** INITS **********************************/
    int d     = CV_32F;
    Mat I1, I2;
    i1.convertTo(I1, d);           // cannot calculate on one byte large values
    i2.convertTo(I2, d);
    Mat I2_2   = I2.mul(I2);        // I2^2
    Mat I1_2   = I1.mul(I1);        // I1^2
    Mat I1_I2  = I1.mul(I2);        // I1 * I2
    /*************************** END INITS **********************************/
    Mat mu1, mu2;   // PRELIMINARY COMPUTING
    GaussianBlur(I1, mu1, Size(11, 11), 1.5);
    GaussianBlur(I2, mu2, Size(11, 11), 1.5);
    Mat mu1_2   =   mu1.mul(mu1);
    Mat mu2_2   =   mu2.mul(mu2);
    Mat mu1_mu2 =   mu1.mul(mu2);
    Mat sigma1_2, sigma2_2, sigma12;
    GaussianBlur(I1_2, sigma1_2, Size(11, 11), 1.5);
    sigma1_2 -= mu1_2;
    GaussianBlur(I2_2, sigma2_2, Size(11, 11), 1.5);
    sigma2_2 -= mu2_2;
    GaussianBlur(I1_I2, sigma12, Size(11, 11), 1.5);
    sigma12 -= mu1_mu2;
    Mat t1, t2, t3;
    t1 = 2 * mu1_mu2 + C1;
    t2 = 2 * sigma12 + C2;
    t3 = t1.mul(t2);              // t3 = ((2*mu1_mu2 + C1).*(2*sigma12 + C2))
    t1 = mu1_2 + mu2_2 + C1;
    t2 = sigma1_2 + sigma2_2 + C2;
    t1 = t1.mul(t2);               // t1 =((mu1_2 + mu2_2 + C1).*(sigma1_2 + sigma2_2 + C2))
    Mat ssim_map;
    divide(t3, t1, ssim_map);      // ssim_map =  t3./t1;
    Scalar mssim = mean( ssim_map ); // mssim = average of ssim map
    return mssim;
}

算法噪声数据

我们完成了噪声添加以及噪声的量化, 我们来试一下, 给图像随机添加一定的噪声, 然后看下响应的参数转变情形对比来看就好

椒盐噪声测试

我们先来测试椒盐噪声 划分盘算没有噪声的图, 以及添加了 1000个 和10000个噪声的数据效果, 并将后面两个显示出来


void MainWindow::testFunc1(void)
{
    // 添加椒盐噪声 并盘算 PSNR和 SSIM
    cv::Mat salt_img;
    double psnr = 0;
    cv::Scalar mssim;

    QString res_temp = "Salt-%1 : psnr:%2, mssim: B:%3 G:%4 R:%5 ";
    QString res_str;

    // 盘算三组图像的参数 0, 1000, 10000

    // 复制原始图像, 添加噪声, 盘算 psnr和ssim  显示在 ui上
    salt_img = gSrcImg.clone();
    addSaltNoise(salt_img,0);

    psnr = getPSNR(gSrcImg, salt_img);
    mssim = getMSSIM(gSrcImg,salt_img);
    res_str = res_temp.arg(0)
                        .arg(psnr)
                        .arg(mssim.val[0])
                        .arg(mssim.val[1])
                        .arg(mssim.val[2]);
    ui->pt_log->appendPlainText(res_str);

    salt_img = gSrcImg.clone();
    addSaltNoise(salt_img,1000);

    psnr = getPSNR(gSrcImg, salt_img);
    mssim = getMSSIM(gSrcImg,salt_img);
    res_str = res_temp.arg(1000)
                        .arg(psnr)
                        .arg(mssim.val[0])
                        .arg(mssim.val[1])
                        .arg(mssim.val[2]);
    ui->pt_log->appendPlainText(res_str);

    // 左侧显示 1000 噪声 右侧显示 10000 噪声
    ShowMatOnQtLabel(salt_img,ui->lb_src);

    salt_img = gSrcImg.clone();
    addSaltNoise(salt_img,10000);

    psnr = getPSNR(gSrcImg, salt_img);
    mssim = getMSSIM(gSrcImg,salt_img);
    res_str = res_temp.arg(10000)
                        .arg(psnr)
                        .arg(mssim.val[0])
                        .arg(mssim.val[1])
                        .arg(mssim.val[2]);
    ui->pt_log->appendPlainText(res_str);

    ShowMatOnQtLabel(salt_img,ui->lb_dst);
}

我们可以直接盘算获得椒盐噪声 psnr 和 ssim 都是越大越好的, 可以显著的看到图像质量退化

Salt-0 : psnr:0, mssim: B:1 G:1 R:1 
Salt-1000 : psnr:27.7528, mssim: B:0.865341 G:0.870555 R:0.914122 
Salt-10000 : psnr:17.8062, mssim: B:0.311999 G:0.327485 R:0.493874 

高斯噪声测试

高斯噪声我们测试了四组 划分使用参数(0,1) (0,10)(10,1)(10,10) 作为高斯参数, 最终获得后面的图, 然后盘算获得的效果, 我们做的效果对照简单, 可以参考数字图像处置——添加高斯噪声&椒盐噪声, 给出了许多的图, 可以参考学


void MainWindow::testFunc2(void)
{
    // 添加高斯噪声 并盘算 PSNR和 SSIM
    cv::Mat guass_img;
    double psnr = 0;
    cv::Scalar mssim;

    QString res_temp = "gauss-%1- %2 : psnr:%3, mssim: B:%4 G:%5 R:%6 ";
    QString res_str;

    // 盘算三组图像的参数 (0,1) (0,10), (10,1), (10,10)

    // 复制原始图像, 添加噪声, 盘算 psnr和ssim  显示在 ui上
    guass_img = gSrcImg.clone();
    addGaussianNoise(guass_img,0,1);

    psnr = getPSNR(gSrcImg, guass_img);
    mssim = getMSSIM(gSrcImg,guass_img);
    res_str = res_temp.arg(0)
                        .arg(1)
                        .arg(psnr)
                        .arg(mssim.val[0])
                        .arg(mssim.val[1])
                        .arg(mssim.val[2]);
    ui->pt_log->appendPlainText(res_str);
    guass_img = gSrcImg.clone();
    addGaussianNoise(guass_img,0,10);

    psnr = getPSNR(gSrcImg, guass_img);
    mssim = getMSSIM(gSrcImg,guass_img);
    res_str = res_temp.arg(0)
                        .arg(10)
                        .arg(psnr)
                        .arg(mssim.val[0])
                        .arg(mssim.val[1])
                        .arg(mssim.val[2]);
    ui->pt_log->appendPlainText(res_str);

    guass_img = gSrcImg.clone();
    addGaussianNoise(guass_img,10,1);

    psnr = getPSNR(gSrcImg, guass_img);
    mssim = getMSSIM(gSrcImg,guass_img);
    res_str = res_temp.arg(10)
                        .arg(1)
                        .arg(psnr)
                        .arg(mssim.val[0])
                        .arg(mssim.val[1])
                        .arg(mssim.val[2]);
    ui->pt_log->appendPlainText(res_str);

    guass_img = gSrcImg.clone();
    addGaussianNoise(guass_img,10,10);

    psnr = getPSNR(gSrcImg, guass_img);
    mssim = getMSSIM(gSrcImg,guass_img);
    res_str = res_temp.arg(10)
                        .arg(10)
                        .arg(psnr)
                        .arg(mssim.val[0])
                        .arg(mssim.val[1])
                        .arg(mssim.val[2]);
    ui->pt_log->appendPlainText(res_str);
}

gauss-0- 1 : psnr:46.8791, mssim: B:0.991811 G:0.991622 R:0.992751 
gauss-0- 10 : psnr:28.1229, mssim: B:0.614219 G:0.608773 R:0.648285 
gauss-10- 1 : psnr:28.5293, mssim: B:0.978448 G:0.980308 R:0.987926 
gauss-10- 10 : psnr:25.3511, mssim: B:0.605665 G:0.600491 R:0.646768 

总结

原本想把滤波一起做了的, 然则越写越, 就不做太多的处置了, 我们算是先容了噪声的泉源, 噪声的模子, 以及个噪声的量化方式,
然后先容了图像添加噪声的方式 我们划分给图像添加椒盐噪声与高斯噪声, 然后划分量化了噪声的效果值, 举行对比展示,

示例的图不是许多, 程序是在代码库里面的, 可以直接去自己实现, 然后举行 举行更多图的展示

参考

  1. 《高斯噪声_百度百科》. 见于 2020年4月30日. https://baike.baidu.com/item/高斯噪声.
  2. 知乎专栏. 《【手艺综述】一文道尽传统图像降噪方式》. 见于 2020年4月29日. https://zhuanlan.zhihu.com/p/51403693.
  3. 知乎专栏. 《可复现的图像降噪算法总结》. 见于 2020年4月29日. https://zhuanlan.zhihu.com/p/32502816.
  4. 《梅森旋转算法》. 收入 维基百科,自由的百科全书, 2019年11月4日. https://zh.wikipedia.org/w/index.php?title=梅森旋转算法&oldid=56745942.
  5. 《实现灰度图像峰值信噪比盘算_人工智能_松子茶的专栏-CSDN博客》. 见于 2020年4月30日. https://blog.csdn.net/songzitea/article/details/17529445.
  6. 《数字图像处置-噪声 - Mohanson》. 见于 2020年4月30日. http://accu.cc/content/pil/noise/.
  7. 《图像处置基础(1):噪声的添加和过滤 - Brook_icv - 博客园》. 见于 2020年4月30日. https://www.cnblogs.com/wangguchangqing/p/6372025.html.
  8. 《图像处置PSNR及其盘算(OpenCV和matlab实现)_人工智能_无机械不学习-加大码的分享-CSDN博客》. 见于 2020年4月30日. https://blog.csdn.net/laoxuan2011/article/details/51519062.
  9. 《图像的 SNR 和 PSNR 的盘算 - rldts - 博客园》. 见于 2020年4月30日. https://www.cnblogs.com/qrlozte/p/5340216.html.
  10. 《图像去噪算法简介 - InfantSorrow - 博客园》. 见于 2020年4月29日. https://www.cnblogs.com/CCBB/archive/2011/01/06/1929033.html.
  11. 《图像噪声的成因分类与常见图像去噪算法简介_Java_qq_27606639的博客-CSDN博客》. 见于 2020年4月30日. https://blog.csdn.net/qq_27606639/article/details/80912071.
  12. 《图像质量评估指标 SSIM / PSNR / MSE_人工智能_兔角与禅-CSDN博客》. 见于 2020年4月30日. https://blog.csdn.net/edogawachia/article/details/78756680.
  13. 《图像质量评价概述(评估指标、传统检测方式)_人工智能_qq_23304241的博客-CSDN博客》. 见于 2020年4月30日. https://blog.csdn.net/qq_23304241/article/details/80953613.
  14. 《影像降噪》. 收入 维基百科,自由的百科全书, 2018年9月20日. https://zh.wikipedia.org/w/index.php?title=影像降噪&oldid=51354600.
,

诚信娱乐

诚信娱乐(现:阳光在线官网)现已开放诚信在线手机版、诚信在线电脑客户端下载。诚信在线娱乐游戏公平、公开、公正,用实力赢取信誉。

皇冠体育声明:该文看法仅代表作者自己,与本平台无关。转载请注明:张家口人才网:opencv-9-图像噪声以及评估指标 PSNR 与SSIM

标签列表

    文章归档

    站点信息

    • 文章总数:485
    • 页面总数:0
    • 分类总数:8
    • 标签总数:904
    • 评论总数:78
    • 浏览总数:8005