索引地址:系列索引
图像噪声
图像噪声使图像在获取或是传输过程中收到随机信号干扰,妨碍人们对图像理解及分析处理的信号。很多时候将图像噪声看做多维随机过程,因而描述噪声的方法完全可以借用随机过程的描述,也就是使用随机过程的描述,也就是用它的高绿分布函数和概率密度分布函数。图像噪声的产生来自图像获取中的环境条件和传感元器件自身的质量,图像在传输过程中产生图像噪声的主要因素是所用的传输信道收到了噪声的污染。
下面简单介绍两种图像噪声,即椒盐噪声和高斯噪声。
椒盐噪声
椒盐噪声也称为脉冲噪声,是图像中经常见到的一种噪声,它是一种随机出现的白点或者黑点,可能是亮的区域有黑色像素或是在暗的区域有白色像素(或是两者皆有)。盐和胡椒噪声的成因可能是影像讯号受到突如其来的强烈干扰而产生、类比数位转换器或位元传输错误等。例如失效的感应器导致像素值为最小值,饱和的感应器导致像素值为最大值。
图像模拟添加椒盐噪声是通过随机获取像素点并设置为高亮度点和低灰度点来实现的
图像添加椒盐噪声的程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
|
#include <cstdlib> #include <iostream> #include <opencv2/opencv.hpp>
using namespace cv; using namespace std;
Mat addSaltNoise(const Mat srcImage, int n);
int main() { Mat srcImage = imread("1.jpg"); if (!srcImage.data) { cout << "读入图像有误!" << endl; return -1; } imshow("Original", srcImage); Mat dstImage = addSaltNoise(srcImage, 3000); imshow("Resutl with salt noise", dstImage); waitKey(); return 0; }
Mat addSaltNoise(const Mat srcImage, int n) { Mat dstImage = srcImage.clone(); for (int k = 0; k < n; k++) { int i = rand() % dstImage.rows; int j = rand() % dstImage.cols; if (dstImage.channels() == 1) { dstImage.at<uchar>(i, j) = 255; } else { dstImage.at<Vec3b>(i, j)[ 0 ] = 255; dstImage.at<Vec3b>(i, j)[ 1 ] = 255; dstImage.at<Vec3b>(i, j)[ 2 ] = 255; } } for (int k = 0; k < n; k++) { int i = rand() % dstImage.rows; int j = rand() % dstImage.cols; if (dstImage.channels() == 1) { dstImage.at<uchar>(i, j) = 0; } else { dstImage.at<Vec3b>(i, j)[ 0 ] = 0; dstImage.at<Vec3b>(i, j)[ 1 ] = 0; dstImage.at<Vec3b>(i, j)[ 2 ] = 0; } } return dstImage; }
|
测试效果如下:
高斯噪声
高斯噪声是指高绿密度函数服从高斯分布的一类噪声。特别的,如果一个噪声,它的幅度分布服从高斯分布,而它的功率谱密度有事均匀分布的,则称这个噪声为高斯白噪声。高斯白噪声二阶矩不相关,一阶矩为常数,是指先后信号在时间上的相关性。高斯噪声包括热噪声和三里噪声。高斯噪声万有由它的事变平均值和两瞬时的协方差函数来确定,若噪声是平稳的,则平均值与时间无关,而协方差函数则变成仅和所考虑的两瞬时之差有关的相关函数,在意义上它等同于功率谱密度。高斯早生可以用大量独立的脉冲产生,从而在任何有限时间间隔内,这些脉冲中的每一个买充值与所有脉冲值得总和相比都可忽略不计。
测试代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| #include <cmath> #include <cstdlib> #include <iostream> #include <limits> #include <opencv2/opencv.hpp>
using namespace cv; using namespace std;
double generateGaussianNoise(double m, double sigma); Mat addGaussianNoise(Mat &srcImag);
int main() { Mat srcImage = imread("1.jpg"); if (!srcImage.data) { cout << "读入图片错误!" << endl; return -1; } imshow("Original", srcImage); Mat dstImage = addGaussianNoise(srcImage); imshow("Result with gaussian noise", dstImage); waitKey(); return 0; }
double generateGaussianNoise(double mu, double sigma) { const double epsilon = numeric_limits<double>::min(); static double z0, z1; static bool flag = false; flag = !flag; if (!flag) return z1 * sigma + mu; double u1, u2; do { u1 = rand() * (1.0 / RAND_MAX); u2 = rand() * (1.0 / RAND_MAX); } while (u1 <= epsilon); z0 = sqrt(-2.0 * log(u1)) * cos(2 * CV_PI * u2); z1 = sqrt(-2.0 * log(u1)) * sin(2 * CV_PI * u2); return z0 * sigma + mu; }
Mat addGaussianNoise(Mat &srcImag) { Mat dstImage = srcImag.clone(); int channels = dstImage.channels(); int rowsNumber = dstImage.rows; int colsNumber = dstImage.cols * channels; if (dstImage.isContinuous()) { colsNumber *= rowsNumber; rowsNumber = 1; } for (int i = 0; i < rowsNumber; i++) { for (int j = 0; j < colsNumber; j++) { int val = dstImage.ptr<uchar>(i)[ j ] + generateGaussianNoise(2, 0.8) * 32; if (val < 0) val = 0; if (val > 255) val = 255; dstImage.ptr<uchar>(i)[ j ] = (uchar)val; } } return dstImage; }
|
测试结果: