噪声图像
图像中噪声的由来多种多样,本文主要介绍高斯白噪声(噪声服从正太分布,功率谱均匀)和开关不正常使用时产生的椒盐噪声的处理。
高斯噪声
高斯噪声在日常生活中存在比较普遍,下面我将为图像添加高斯噪声。
// 生成高斯噪声
double generateGaussianNoise(double mu, double sigma)
{
static double V1, V2, S;
static int phase = 0;
double X;
double U1, U2;
if (phase == 0) {
do {
U1 = (double)rand() / RAND_MAX;
U2 = (double)rand() / RAND_MAX;
V1 = 2 * U1 - 1;
V2 = 2 * U2 - 1;
S = V1 * V1 + V2 * V2;
} while (S >= 1 || S == 0);
X = V1 * sqrt(-2 * log(S) / S);
}
else {
X = V2 * sqrt(-2 * log(S) / S);
}
phase = 1 - phase;
return mu + sigma * X;
}
//为图像添加高斯噪声
cv::Mat addGaussianNoise(cv::Mat &srcImag, double mu = 0, double sigma = 5)
{
cv::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(mu, sigma);
if (val < 0)
val = 0;
if (val > 255)
val = 255;
dstImage.ptr<uchar>(i)[j] = (uchar)val;
}
}
return dstImage;
}
椒盐噪声
椒盐噪声可认为是胡椒噪声和盐粒噪声的混合版本。
// 添加椒盐噪声op=0, 添加盐粒噪声op=1, 添加胡椒噪声op=2
cv::Mat addSaltNoise(const cv::Mat src, int n, int op)
{
cv::Mat dst = src.clone();
if (op == 0 || op == 1)
{
for (int k = 0; k < n; k++)
{
int i = rand() % dst.rows;
int j = rand() % dst.cols;
// 通道判定
if (dst.channels() == 1)
{
dst.at<uchar>(i, j) = 255; // 添加盐噪声
}
else
{
dst.at<cv::Vec3b>(i, j)[0] = 255;
dst.at<cv::Vec3b>(i, j)[1] = 255;
dst.at<cv::Vec3b>(i, j)[2] = 255;
}
}
}
if (op == 0 || op == 2)
{
for (int k = 0; k < n; k++)
{
int i = rand() % dst.rows;
int j = rand() % dst.cols;
// 通道判定
if (dst.channels() == 1)
{
dst.at<uchar>(i, j) = 0; // 添加椒噪声
}
else
{
dst.at<cv::Vec3b>(i, j)[0] = 0;
dst.at<cv::Vec3b>(i, j)[1] = 0;
dst.at<cv::Vec3b>(i, j)[2] = 0;
}
}
}
return dst;
}
算术均值滤波、几何均值滤波、谐波均值滤波、逆谐波滤波
算数均值滤波是求区域内的均值,而几何均值滤波是求区域内的乘积后的开方。前者处理过后图像对比后者更模糊,但两者的平滑作用基本相同。谐波均值滤波对盐粒噪声和高斯噪声的去噪比较有效,而逆谐波滤波对胡椒噪声的去噪效果较好,但这两者都不能处理椒盐噪声,因为它们分别只能处理一种极值点情况。
// 任务一
void test1(int op)
{
// 1.1.打开原始图像
cv::Mat src = open_image(op, "原始图像");
// 1.2.添加1000个椒盐噪声
cv::Mat dst1 = addSaltNoise(src, 10000, 0);
someFilter(src, dst1, "椒盐噪声");
// 2 添加胡椒噪声
cv::Mat dst2 = addSaltNoise(src, 10000, 2);
someFilter(src, dst2, "胡椒噪声");
// 3 添加盐粒噪声
cv::Mat dst3 = addSaltNoise(src, 10000, 1);
someFilter(src, dst3, "盐粒噪声");
// 4. 添加高斯噪声
cv::Mat dst4 = addGaussianNoise(src);
someFilter(src, dst4, "高斯噪声");
}
// 滤波(算术,几何, 谐波, 逆谐波)
void someFilter(cv::Mat src, cv::Mat dst, string name)
{
// 1 算术滤波
cv::Mat filter1 = inverseHarm(dst, 0);
// 2.几何滤波
cv::Mat filter2 = gmMeanFilter(dst, 7);
// 3.谐波滤波
cv::Mat filter3 = inverseHarm(dst, -1);
// 4.逆谐波滤波
cv::Mat filter4 = inverseHarm(dst, 1.5);
// 5.显示图像
show_img(src, "原始图像");
show_img(dst, name);
show_img(filter1, "算术滤波");
show_img(filter2, "几何滤波");
show_img(filter3, "谐波均值滤波");
show_img(filter4, "逆谐波滤