OpenCV13-Image noise: salt and pepper noise and Gaussian noise

OpenCV13-Image noise: salt and pepper noise and Gaussian noise


1.Types of noise

Image noise refers to random or non-random unwanted visual disturbances in images. It can appear in digital images in various forms such as grainy noise, streaks, spots, blur, distortion, etc. Image noise may be caused by sensor noise, electromagnetic interference, transmission errors, compression algorithms, etc. during the image acquisition process.

Common types of image noise include:

  1. Gaussian noise: Gaussian noise is one of the most common types of image noise. It is caused by sensor noise and environmental interference and appears as random brightness changes in the image.
  2. Salt and pepper noise: Salt and pepper noise refers to the appearance of random black and white pixels in the image, similar to salt and pepper particles. It is usually caused by a faulty sensor or an error in signal transmission.
  3. Speckle noise: Speckle noise refers to spots with uneven brightness that appear in an image and may be caused by defects in the camera or sensor.
  4. Streak noise: Streak noise appears as horizontal or vertical stripes in the image, usually caused by power interference or instability of the camera scan clock.
  5. Compression noise: Compression noise is introduced in image compression, especially in low bitrate compression. It manifests itself as loss of image detail, blurring, or blocking artifacts.

In order to reduce or remove image noise, image processing techniques can be used, such as smoothing filtering, median filtering, frequency domain filtering, etc. These techniques improve image quality and enhance detail by selecting and adjusting parameters based on the type of noise and the needs of the specific application.

2. Salt and pepper noise

Salt and pepper noise is also called impulse noise. It will randomly change the pixel values ​​in the image. It looks like randomly sprinkling some salt and black pepper grains on the image, so it is called salt and pepper noise.

OpenCV does not provide a function specifically used to add salt and pepper noise to images, and users need to write a program to generate noise according to their needs. Considering that salt and pepper noise will be randomly generated at any position in the image, for the generation of salt and pepper noise, you need to use the function in OpenCV that can generate random numbers rand() . In order to be able to generate random numbers of different data types, this function has several evolutions:

namespace cvflann
{
    
    
    inline int rand();
    // low与high是输出随机数的最小值与最大值
    inline double rand_double(double high = 1.0, double low = 0);
    inline int rand_int(int high = RAND_MAX, int low = 0);
}

Steps to add salt and pepper noise:

1. Determine the location of salt and pepper noise. Generate two random numbers through a random function to determine the row and column of the noise point.

2. Determine the type of noise. The black and white of the noise points are also random, and a random number can be generated to determine the black and white based on parity.

3. Modify the grayscale value of the image pixel. Determine the number of channels of the image, assign a value to a single channel of a grayscale image, and assign 3 values ​​to a three-channel color image.

The result is an image containing noise.

The following is the code implementation:

#include <opencv2/core/utils/logger.hpp>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

//盐噪声函数
void saltAndPepper(cv::Mat image, int n)
{
    
    
	//using cvflann::rand();
	for (int k = 0; k < n / 2; k++)
	{
    
    
		//随机确定图像中位置
		int i, j;
		i = cvflann::rand() % image.cols;  //取余数运算,保证在图像的列数内
		j = cvflann::rand() % image.rows;  //取余数运算,保证在图像的行数内
		int write_black = cvflann::rand() % 2;  //判定为白色噪声还是黑色噪声的变量
		if (write_black == 0)  //添加白色噪声
		{
    
    
			if (image.type() == CV_8UC1)  //处理灰度图像
			{
    
    
				image.at<uchar>(j, i) = 255;  //白色噪声
			}
			else if (image.type() == CV_8UC3)  //处理彩色图像
			{
    
    
				image.at<cv::Vec3b>(j, i)[0] = 255; //cv::Vec3b为opencv定义的一个3个值的向量类型
				image.at<cv::Vec3b>(j, i)[1] = 255; //[]指定通道,B:0,G:1,R:2
				image.at<cv::Vec3b>(j, i)[2] = 255;
			}
		}
		else  //添加黑色噪声
		{
    
    
			if (image.type() == CV_8UC1)
			{
    
    
				image.at<uchar>(j, i) = 0;
			}
			else if (image.type() == CV_8UC3)
			{
    
    
				image.at<cv::Vec3b>(j, i)[0] = 0; //cv::Vec3b为opencv定义的一个3个值的向量类型
				image.at<cv::Vec3b>(j, i)[1] = 0; //[]指定通道,B:0,G:1,R:2
				image.at<cv::Vec3b>(j, i)[2] = 0;
			}
		}
	}
}

int main()
{
    
    
	cout << "OpenCV Version: " << CV_VERSION << endl;
	utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);

	Mat lena = imread("lena.png");
	Mat equalLena = imread("equalLena.png", IMREAD_ANYDEPTH);
	if (lena.empty() || equalLena.empty())
	{
    
    
		cout << "请确认图像文件名称是否正确" << endl;
		return -1;
	}
	imshow("lena原图", lena);
	imshow("equalLena原图", equalLena);
	saltAndPepper(lena, 10000);  //彩色图像添加椒盐噪声
	saltAndPepper(equalLena, 10000);  //灰度图像添加椒盐噪声
	imshow("lena添加噪声", lena);
	imshow("equalLena添加噪声", equalLena);

	int k = waitKey(0); // Wait for a keystroke in the window
	return 0;
}

3. Gaussian noise

Gaussian noise refers to a type of noise in which the probability density function of the noise distribution obeys Gaussian distribution (normal distribution). The probability density function is as follows:
p ( z ) = 1 2 π σ e − ( z − μ ) 2 2 σ 2 p(z) = \frac{1}{\sqrt{2 \ pi \sigma}} e^{\frac{-(z-\mu)^2}{2 \sigma^2}} p(z)=2πσ 1It is2σ2(zμ)2
inside, z z z represents the grayscale value of the image pixel, μ \mu μ represents the average or expected value of pixel values, σ \sigma σ represents the standard deviation of pixel values.

There is no function in OpenCV that specifically adds Gaussian noise to the image. For the process of adding salt and pepper noise to the image, you can use a function that can generate random numbers according to your needs to complete the task of adding Gaussian noise to the image. OpenCV provides the fill() function that can generate random numbers with uniform distribution or Gaussian distribution. You can use this function to generate random numbers that conform to Gaussian distribution, and then add these random numbers to the image.

void cv::RNG::fill(
    InputOutputArray mat, // 存放随机数的矩阵
    int distType,   // 均匀分布RNG::UNIFORM 高斯分布RNG::NORMAL
    InputArray a,   // 均匀分布的最小下限,高斯分布的均值
    InputArray b,   // 均匀分布的最大上限,高斯分布的标准差
    bool saturateRange = false // 预报和标志,仅用于均匀分布
);

fill()The function is a member function of the RNG class, so a class object must be created before it can be used:

cv::RNG rng;
rng.fill(mat, RNG::NORMAL, 10, 20);

Steps to add Gaussian noise to an image:

1. Create a Mat class variable with the same size, data type and number of channels as the image.

2. Call thefill() function to generate random numbers consistent with Gaussian distribution in the Mat class variable.

3. Add the original image and the random number matrix containing Gaussian distribution.

Finally, the image after adding Gaussian noise is obtained.

Here is the sample code:

#include <opencv2/core/utils/logger.hpp>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

int main()
{
    
    
	cout << "OpenCV Version: " << CV_VERSION << endl;
	utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);

	Mat lena = imread("lena.png");
	Mat equalLena = imread("equalLena.png", IMREAD_ANYDEPTH);
	if (lena.empty() || equalLena.empty())
	{
    
    
		cout << "请确认图像文件名称是否正确" << endl;
		return -1;
	}
	//生成与原图像同尺寸、数据类型和通道数的矩阵
	Mat lena_noise = Mat::zeros(lena.rows, lena.cols, lena.type());
	Mat equalLena_noise = Mat::zeros(lena.rows, lena.cols, equalLena.type());
	imshow("lena原图", lena);
	imshow("equalLena原图", equalLena);
	RNG rng;  //创建一个RNG类
	rng.fill(lena_noise, RNG::NORMAL, 10, 20);  //生成三通道的高斯分布随机数
	rng.fill(equalLena_noise, RNG::NORMAL, 15, 30);  //生成三通道的高斯分布随机数

	imshow("三通道高斯噪声", lena_noise);
	imshow("单通道高斯噪声", equalLena_noise);
	lena = lena + lena_noise;  //在彩色图像中添加高斯噪声
	equalLena = equalLena + equalLena_noise;  //在灰度图像中添加高斯噪声
	//显示添加高斯噪声后的图像
	imshow("lena添加噪声", lena);
	imshow("equalLena添加噪声", equalLena);

	int k = waitKey(0); // Wait for a keystroke in the window
	return 0;
}

Considering that the sum of grayscale values ​​will exceed 255, in fact, if the value exceeds 255, it will equal 255:

int main()
{
    
    
	cout << "OpenCV Version: " << CV_VERSION << endl;
	utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);

	Mat a = (Mat_<uchar>(2, 2) << 130, 125, 127, 129);
	Mat b = (Mat_<uchar>(2, 2) << 130, 125, 127, 129);
	Mat c = a + b;
	cout << "a: " << endl << a << endl;
	cout << "b: " << endl << b << endl;
	cout << "c: " << endl << c << endl;

	int k = waitKey(0); // Wait for a keystroke in the window
	return 0;
}
/*
a:
[130, 125;
 127, 129]
b:
[130, 125;
 127, 129]
c:
[255, 250;
 254, 255]
*/

Guess you like

Origin blog.csdn.net/ArthurHai521/article/details/133828510
Recommended