在OpenCV联合C++中给一张图片添加高斯噪声(Gaussian Noise),可以通过生成随机数并在图像的每个像素上加上这些随机数来实现。高斯噪声是一种统计分布服从正态分布的噪声,通常用于模拟自然界的许多物理现象。
示例代码
以下是一个使用OpenCV和C++给一张图片添加高斯噪声的示例代码:
#include "pch.h"
#include <opencv2/opencv.hpp>
#include <iostream>
#include <random>
using namespace cv;
using namespace std;
// 添加高斯噪声的函数
void addGaussianNoise(cv::Mat &image, double mean = 0, double stddev = 10)
{
// 创建随机数生成器
std::random_device rd;
std::default_random_engine gen(rd());
std::normal_distribution<double> dist(mean, stddev);
// 获取图像的行数和列数
int rows = image.rows;
int cols = image.cols;
// 遍历图像中的每一个像素
for (int i = 0; i < rows; ++i)
{
for (int j = 0; j < cols; ++j)
{
// 生成一个高斯分布的随机数
double noise = dist(gen);
// 加上噪声
//image.at<uchar>(i, j) = std::min(std::max(image.at<uchar>(i, j) + noise, 0), 255);
//image.at<uchar>(i, j) = saturate_cast<uchar>(image.at<uchar>(i, j) + noise);
//std::min(255, std::max(0, static_cast<int>(alpha1 * pixelValue + beta1)));
image.at<uchar>(i, j) = std::min(255, std::max(0, static_cast<int>(image.at<uchar>(i, j) + noise)));
/static_cast<int> 的添加
//image.at<uchar>(i, j) = saturate_cast<uchar>(image.at<uchar>(i, j) + noise);
}
}
}
int main()
{
// 读取图像
cv::Mat img = cv::imread("03.jpeg", cv::IMREAD_GRAYSCALE);
if (img.empty())
{
std::cerr << "Error loading image." << std::endl;
return -1;
}
// 显示原始图像
cv::namedWindow("Original Image", cv::WINDOW_NORMAL);
cv::imshow("Original Image", img);
// 添加高斯噪声
addGaussianNoise(img, 0, 10); // 平均值为0,标准差为10
// 显示添加噪声后的图像
cv::namedWindow("Noisy Image", cv::WINDOW_NORMAL);
cv::imshow("Noisy Image", img);
cv::imwrite("Dst2.jpg", img);//写入照片
cv::waitKey(0);
return 0;
}
代码解释
1. 读取图像:使用 cv::imread 函数读取原始图像,并将其转换为灰度图像。
2. 添加高斯噪声:定义一个 addGaussianNoise 函数,该函数接受一个图像矩阵 image、均值 mean 和标准差 stddev。均值 mean 通常设置为0,标准差 stddev 控制噪声的强度。
3. 随机数生成器:使用 <random> 头文件中的 std::random_device 和 std::default_random_engine 生成随机数,std::normal_distribution 生成符合正态分布的随机数。
4. 遍历图像:遍历图像的每一个像素点,根据生成的高斯分布随机数给像素值加上噪声。
5. 限制像素值范围:确保像素值在0到255之间,避免超出8位灰度图像的范围。
6. 显示图像:使用 cv::imshow 函数显示原始图像和添加噪声后的图像。
参数调整
•均值 mean:通常设置为0,表示噪声的平均值为0,即噪声在正负方向上是对称的。
•标准差 stddev:标准差越大,噪声的强度越高,图像越模糊。
注意事项
•噪声强度:标准差 stddev 控制噪声的强度,可以根据需要调整该参数。
•数据类型:在加噪声时,需要注意像素值的数据类型。在上面的示例中,我们使用了 uchar 类型,因此需要确保像素值在0到255之间。
•性能优化:如果图像较大,遍历每一个像素可能会比较耗时,可以考虑使用OpenCV提供的并行处理方法,如 cv::parallel_for_ 等。
通过上述方法,你可以很容易地在OpenCV和C++中给一张图片添加高斯噪声。这对于模拟真实世界中的噪声情况非常有用,尤其是在图像处理和计算机视觉的研究和应用中。
运行结果
除噪方法
在OpenCV联合C++中去除一张图片上的高斯噪声,可以采用多种滤波方法。高斯噪声通常表现为像素值的随机波动,因此需要选择一种能够有效平滑图像的滤波方法。以下是一些常用的滤波方法及其适用性:
1. 高斯滤波(Gaussian Filtering)
高斯滤波是最常用来去除高斯噪声的方法之一。它通过应用一个高斯核来平滑图像,从而降低噪声的影响。高斯滤波在保留图像边缘的同时,能够很好地平滑图像。
示例代码
#include "pch.h"
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
// 读取图像
cv::Mat img = cv::imread("06.jpg", cv::IMREAD_GRAYSCALE);
if (img.empty())
{
std::cerr << "Error loading image." << std::endl;
return -1;
}
// 显示原始噪声图像
cv::namedWindow("Noisy Image", cv::WINDOW_NORMAL);
cv::imshow("Noisy Image", img);
// 应用高斯滤波
cv::Mat denoisedImg;
cv::GaussianBlur(img, denoisedImg, cv::Size(3, 3), 0); // ksize 为 3x3 的高斯滤波
// 显示去噪后的图像
cv::namedWindow("Denoised Image", cv::WINDOW_NORMAL);
cv::imshow("Denoised Image", denoisedImg);
cv::waitKey(0);
return 0;
}
运行结果
2. 均值滤波(Mean Filtering)
均值滤波也是一种去除高斯噪声的方法,它通过计算每个像素点邻域内的平均值来替代中心像素值。均值滤波可以有效去除噪声,但可能会使图像变得模糊。
示例代码
#include "pch.h"
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
// 读取图像
cv::Mat img = cv::imread("06.jpg", cv::IMREAD_GRAYSCALE);
if (img.empty())
{
std::cerr << "Error loading image." << std::endl;
return -1;
}
// 显示原始噪声图像
cv::namedWindow("Noisy Image", cv::WINDOW_NORMAL);
cv::imshow("Noisy Image", img);
// 应用均值滤波
cv::Mat denoisedImg;
cv::blur(img, denoisedImg, cv::Size(3, 3)); // ksize 为 3x3 的均值滤波
// 显示去噪后的图像
cv::namedWindow("Denoised Image", cv::WINDOW_NORMAL);
cv::imshow("Denoised Image", denoisedImg);
cv::waitKey(0);
return 0;
}
运行结果
3. 双边滤波(Bilateral Filtering)
双边滤波是一种非局部均值滤波方法,它在平滑图像的同时能够较好地保留边缘。双边滤波不仅考虑空间邻域,还考虑像素值的相似性,因此在去除高斯噪声的同时,可以较好地保留图像细节。
示例代码
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
// 读取图像
cv::Mat img = cv::imread("path/to/noisy_image.jpg", cv::IMREAD_GRAYSCALE);
if (img.empty())
{
std::cerr << "Error loading image." << std::endl;
return -1;
}
// 显示原始噪声图像
cv::namedWindow("Noisy Image", cv::WINDOW_NORMAL);
cv::imshow("Noisy Image", img);
// 应用双边滤波
cv::Mat denoisedImg;
cv::bilateralFilter(img, denoisedImg, 9, 75, 75); // d=9, sigmaColor=75, sigmaSpace=75
// 显示去噪后的图像
cv::namedWindow("Denoised Image", cv::WINDOW_NORMAL);
cv::imshow("Denoised Image", denoisedImg);
cv::waitKey(0);
return 0;
}
运行结果
4.中值滤波
示例代码
#include "pch.h"
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
// 读取图像
cv::Mat img = cv::imread("06.jpg", cv::IMREAD_GRAYSCALE);
if (img.empty())
{
std::cerr << "Error loading image." << std::endl;
return -1;
}
// 显示原始噪声图像
cv::namedWindow("Noisy Image", cv::WINDOW_NORMAL);
cv::imshow("Noisy Image", img);
// 应用中值滤波
cv::Mat denoisedImg;
cv::medianBlur(img, denoisedImg, 3); // ksize 为 3 的中值滤波
// 显示去噪后的图像
cv::namedWindow("Denoised Image", cv::WINDOW_NORMAL);
cv::imshow("Denoised Image", denoisedImg);
cv::waitKey(0);
return 0;
}
运行结果
5. 非局部均值去噪(Non-Local Means Denoising)
非局部均值去噪是一种高级去噪方法,它通过查找图像中的相似区域来进行去噪。这种方法可以在保持图像细节的同时去除噪声,尤其适用于高斯噪声。
示例代码
#include <opencv2/opencv.hpp>
#include <iostream>
int main()
{
// 读取图像
cv::Mat img = cv::imread("path/to/noisy_image.jpg", cv::IMREAD_GRAYSCALE);
if (img.empty())
{
std::cerr << "Error loading image." << std::endl;
return -1;
}
// 显示原始噪声图像
cv::namedWindow("Noisy Image", cv::WINDOW_NORMAL);
cv::imshow("Noisy Image", img);
// 应用非局部均值去噪
cv::Mat denoisedImg;
cv::fastNlMeansDenoising(img, denoisedImg, 10, 7, 21); // h=10, templateWindowSize=7, searchWindowSize=21
// 显示去噪后的图像
cv::namedWindow("Denoised Image", cv::WINDOW_NORMAL);
cv::imshow("Denoised Image", denoisedImg);
cv::waitKey(0);
return 0;
}
运行结果
总结
•高斯滤波:适用于去除高斯噪声,能够较好地平滑图像,但可能使图像略微模糊。
•均值滤波:简单易用,但会使图像更加模糊。
•双边滤波:在平滑图像的同时能够较好地保留边缘,适用于需要保持图像细节的情况。
•非局部均值去噪:高级去噪方法,能够在保持图像细节的同时去除噪声,尤其适用于高斯噪声。
根据具体的应用需求和图像特点,可以选择最适合的方法。如果需要去除高斯噪声同时尽量保留图像细节,可以优先考虑高斯滤波和双边滤波。如果需要更高级的去噪效果,可以考虑非局部均值去噪。