本项目实现了一个图像去噪和人脸美颜的完整流程,利用了积分图来加速局部统计量的计算,结合了盒式滤波和平滑处理,使得图像中的噪声和瑕疵得以减轻。每个函数都有特定的用途,从图像预处理、局部统计信息计算、去噪到人脸掩膜的生成和应用。
一、基础实现方式
1.初始化读取图像
clear all; close all; clc;
img = imread('xxx.jpg'); //(xxx.jpg为美颜的目标图像)
clear all
:清除工作空间中的所有变量,close all
:关闭所有图形窗口。
clc
:清除命令窗口。imread
:读取指定路径的图像文件,并存储在变量 img
中。
2.添加高斯噪声并再次读取图像
noisyImg = imnoise(img, 'gaussian', 0, 0.01);
noisyImg = imread('xxx.jpg'); //此处图像和上部分代码相同
imnoise(img, 'gaussian', 0, 0.01)
:向图像添加高斯噪声,均值为0,方差为0.01。
noisyImg = imread(...)
:重新读取图像,覆盖了前面添加噪声的操作。
3.设置去噪参数和去噪
r = 10;
level = 5;
sigma = 10 + level^2;
dnImg = denoiseBasedLocalStat(noisyImg, r, sigma);
r = 10
:设置局部区域的半径为10
level = 5
:设置去噪级别为5。
sigma = 10 + level^2
:计算噪声的标准差参数。
dnImg = denoiseBasedLocalStat(...)
:调用函数 denoiseBasedLocalStat
进行图像去噪。
4.显示图像
figure, imshow(noisyImg);
figure, imshow(dnImg);
figure
:创建一个新的图形窗口
imshow
:显示图像。
5.生成人脸掩膜并合并图像
mask = faceMask(noisyImg, 5);
w = 0.5;
mergedImg = uint8(double(noisyImg) .* (1 - w * mask) + w * double(dnImg) .* mask);
figure, imshow(mergedImg);
mask = faceMask(noisyImg, 5)
:调用函数 faceMask
生成人脸掩膜。
w = 0.5
:设置权重参数为0.5。
mergedImg = ...
:根据掩膜将去噪图像与原始图像合并。
imshow
:显示合并后的图像。
6.去噪函数:denoiseBasedLocalStat
function dnImg = denoiseBasedLocalStat(img, r, sigma)
if size(img,3) == 1
img = double(img);
dnImg = denoiseBasedLocalStat_gray(img, r, sigma);
dnImg = uint8(dnImg);
end
if size(img,3) == 3
ycc = rgb2ycbcr(img);
y = ycc(:,:,1);
dnY = denoiseBasedLocalStat_gray(double(y), r, sigma);
ycc(:,:,1) = uint8(dnY);
dnImg = ycbcr2rgb(ycc);
end
end
该函数根据图像的颜色通道数选择处理方法
灰度图像:直接调用 denoiseBasedLocalStat_gray
进行处理。
彩色图像:转换为YCrCb颜色空间,只处理亮度通道,然后再转换回RGB
7.灰度图像去噪函数:denoiseBasedLocalStat_gray
function dnImg = denoiseBasedLocalStat_gray(img, r, sigma)
dnImg = zeros(size(img));
img = double(img);
paddedImg = padarray(img, [r, r], 'symmetric', 'both');
[Yim, YYim] = intergalMap(paddedImg);
for i = r+1:size(paddedImg,1)-r
for j = r+1:size(paddedImg,2)-r
rectSum = Yim(i+r+1,j+r+1) + Yim(i-r,j-r) - Yim(i-r,j+r+1) - Yim(i+r+1,j-r);
rectSquareSum = YYim(i+r+1,j+r+1) + YYim(i-r,j-r) - YYim(i-r,j+r+1) - YYim(i+r+1,j-r);
num = (2*r+1)^2;
avg = rectSum / num;
var = rectSquareSum / num - avg^2;
k = var / (var + sigma^2);
dnImg(i-r, j-r) = (1 - k) * avg + k * img(i-r, j-r);
end
end
end
该函数对灰度图像进行基于局部统计信息的去噪。
padarray
:对图像进行边界填充。
intergalMap
:计算积分图,用于快速计算局部区域的和与平方和。
循环部分:对每个像素计算局部均值和方差,并根据自适应滤波公式进行去噪。
8.积分图函数:intergalMap
function [Yim, YYim] = intergalMap(img)
paddedImg = padarray(img, [1 1], 0, 'pre');
Yim = zeros(size(paddedImg));
YYim = Yim;
for i = 2:size(paddedImg, 1)
for j = 2:size(paddedImg, 2)
Yim(i, j) = Yim(i, j-1) + Yim(i-1, j) - Yim(i-1, j-1) + paddedImg(i, j);
YYim(i, j) = YYim(i, j-1) + YYim(i-1, j) - YYim(i-1, j-1) + paddedImg(i, j)^2;
end
end
end
该函数生成积分图,用于快速计算任意矩形区域的和与平方和。
积分图计算:通过递推公式计算积分图,方便快速获取局部区域的和与平方和
9.人脸掩膜生成函数:faceMask
function mask = faceMask(img, r)
mask = zeros(size(img,1), size(img,2));
mask(img(:,:,1) > 20 & img(:,:,2) > 40 & img(:,:,3) > 50) = 1;
mask = myBoxFilt(mask, r);
mask = mask(:,:,ones(1,3));
end
该函数生成人脸掩膜。
根据颜色阈值生成初步掩膜:将满足条件的像素标记为1,其余为0。
myBoxFilt
:对初步掩膜进行盒式滤波。
掩膜扩展到三个通道:使掩膜适用于彩色图像的三个通道。
10.盒式滤波函数:myBoxFilt
function fImg = myBoxFilt(img, r)
paddedImg = padarray(img, [r r], 'symmetric', 'both');
[Yim, ~] = intergalMap(paddedImg);
fImg = zeros(size(img));
for i = r+1:size(paddedImg,1)-r
for j = r+1:size(paddedImg,2)-r
rectSum = Yim(i+r+1, j+r+1) + Yim(i-r, j-r) - Yim(i-r, j+r+1) - Yim(i+r+1, j-r);
avg = rectSum / (2*r+1)^2;
fImg(i-r, j-r) = avg;
end
end
end
该函数对图像进行盒式滤波。
对图像进行边界填充。
使用积分图计算局部区域的均值:通过滑动窗口计算局部均值,生成平滑后的图像。
二、什么是盒式滤波
盒式滤波(Box Filter)是一种常见的图像平滑滤波器,其原理是用一个固定大小的矩形窗口在图像上滑动,窗口内的所有像素值取平均值,然后用这个平均值替代窗口中心的像素值。盒式滤波是一种线性平滑滤波器,能够有效地减少图像中的随机噪声,虽然会导致一定程度的边缘模糊。
下面我们具体解释一下 盒式滤波函数:myBoxFil
1.图像填充
paddedImg = padarray(img, [r r], 'symmetric', 'both');
padarray
:对图像进行边界填充,填充值采用对称方式。这样做的目的是为了在计算边界像素的滤波时,不会因为缺少周围像素值而出错。填充的大小为 r
,即窗口半径。
2.生成积分图
[Yim, ~] = intergalMap(paddedImg);
调用 intergalMap
函数生成积分图。积分图用于快速计算任意矩形区域的像素和
3.初始化输出图像
fImg = zeros(size(img));
初始化一个与输入图像大小相同的矩阵 fImg
,用于存储滤波后的图像
4.滑动窗口计算局部均值
for i = r+1:size(paddedImg,1)-r
for j = r+1:size(paddedImg,2)-r
rectSum = Yim(i+r+1, j+r+1) + Yim(i-r, j-r) - Yim(i-r, j+r+1) - Yim(i+r+1, j-r);
avg = rectSum / (2*r+1)^2;
fImg(i-r, j-r) = avg;
end
end
遍历填充后的图像的每个像素(去除填充区域)。
使用积分图快速计算窗口内像素的和。公式如下:
rectSum = Yim(i+r+1, j+r+1) + Yim(i-r, j-r) - Yim(i-r, j+r+1) - Yim(i+r+1, j-r);
//Yim(i+r+1, j+r+1):右下角
//Yim(i-r, j-r):左上角
//Yim(i-r, j+r+1):右上角
//Yim(i+r+1, j-r):左下角
计算窗口内像素的平均值:
avg = rectSum / (2*r+1)^2;
将平均值赋给输出图像相应位置的像素:
fImg(i-r, j-r) = avg;
5.总结
盒式滤波的关键在于利用积分图(也称为累积分布图)快速计算局部区域的和。积分图的好处在于,无论窗口的大小如何,计算区域和的时间复杂度始终是常数时间O(1),这极大地提高了计算效率。在您的代码中,myBoxFilt
函数使用积分图实现了高效的盒式滤波,而 intergalMap
函数负责生成所需的积分图和平方积分图。
三、什么是高斯滤波和高斯噪声
既然前文提到了高斯噪声的添加,那么现在来理解一下高斯噪声和高斯滤波
1)高斯滤波
1.高斯滤波原理
高斯滤波器使用一个高斯函数的加权窗口对图像进行平滑处理。它可以有效地减少高频噪声,同时保留低频信号。
2.代码实现
function gaussianFilteredImg = gaussianFilter(img, sigma)
% 创建高斯滤波器
kernelSize = 2 * ceil(3 * sigma) + 1;
h = fspecial('gaussian', kernelSize, sigma);
% 对图像进行滤波
gaussianFilteredImg = imfilter(img, h, 'symmetric');
end
% 示例使用
img = imread('C:\Users\27660\Desktop\download.jpg');
sigma = 2;
gaussianFilteredImg = gaussianFilter(img, sigma);
figure, imshow(gaussianFilteredImg);
1)高斯噪声
1.高斯噪声定义
高斯噪声(Gaussian noise),也称为正态噪声(Normal noise),是一种常见的随机噪声,其概率密度函数遵循正态分布,即高斯分布。它常用来模拟实际图像采集过程中产生的噪声,尤其是那些由电子设备(如传感器和放大器)引起的噪声。
2.高斯噪声的特性
概率密度函数:高斯噪声的概率密度函数由均值和标准差两个参数确定,数学表达式如下:
其中,μ\muμ 是均值, σ\sigmaσ 是标准差。
零均值:在许多实际应用中,高斯噪声常假设为零均值( μ=0\mu = 0μ=0 ),这表示噪声值在正负两个方向上均匀分布。
独立性:高斯噪声通常假设为独立的,即每个像素的噪声值相互独立,不受其他像素噪声值的影响。
3.高斯噪声的生成
在图像处理中,可以通过添加高斯噪声来模拟图像的噪声污染。以下是 MATLAB 中添加高斯噪声的示例代码:
% 读取图像
img = imread('xxx.jpg');
% 将图像转换为灰度图像(可选)
grayImg = rgb2gray(img);
% 添加高斯噪声
noisyImg = imnoise(grayImg, 'gaussian', 0, 0.01);
% 显示原始图像和添加噪声后的图像
figure, imshow(grayImg), title('Original Image');
figure, imshow(noisyImg), title('Noisy Image (Gaussian Noise)');
四、其他的滤波方式
1)中值滤波 (Median Filtering)
1.原理
中值滤波使用一个窗口内像素的中值来替代中心像素值。它对椒盐噪声(即极端噪声)特别有效。
2.代码实现
function medianFilteredImg = medianFilter(img, filterSize)
% 对图像进行中值滤波
medianFilteredImg = medfilt2(img, [filterSize filterSize]);
end
% 示例使用
img = imread('C:\Users\27660\Desktop\download.jpg');
filterSize = 3;
medianFilteredImg = medianFilter(rgb2gray(img), filterSize);
figure, imshow(medianFilteredImg);
2)双边滤波 (Bilateral Filtering)
1.原理
双边滤波器结合了空域和颜色域的信息进行滤波,既能平滑图像,又能保留边缘细节。
2.代码实现
function bilateralFilteredImg = bilateralFilter(img, sigma_spatial, sigma_range)
% 双边滤波的实现
img = double(img) / 255.0;
w = 5; % 窗口半径
[X, Y] = meshgrid(-w:w, -w:w);
spatialKernel = exp(-(X.^2 + Y.^2) / (2 * sigma_spatial^2));
% 初始化输出图像
bilateralFilteredImg = zeros(size(img));
for i = 1:size(img, 1)
for j = 1:size(img, 2)
% 提取当前像素的局部区域
iMin = max(i - w, 1);
iMax = min(i + w, size(img, 1));
jMin = max(j - w, 1);
jMax = min(j + w, size(img, 2));
region = img(iMin:iMax, jMin:jMax, :);
% 计算颜色权重
colorKernel = exp(-sum((region - img(i, j, :)).^2, 3) / (2 * sigma_range^2));
% 计算总权重
combinedKernel = spatialKernel((iMin:iMax) - i + w + 1, (jMin:jMax) - j + w + 1) .* colorKernel;
% 归一化
normalizationFactor = sum(combinedKernel(:));
% 计算滤波后的值
bilateralFilteredImg(i, j, :) = sum(sum(region .* combinedKernel, 1), 2) / normalizationFactor;
end
end
bilateralFilteredImg = uint8(bilateralFilteredImg * 255);
end
% 示例使用
img = imread('xxx.jpg');
sigma_spatial = 2;
sigma_range = 0.1;
bilateralFilteredImg = bilateralFilter(img, sigma_spatial, sigma_range);
figure, imshow(bilateralFilteredImg);