Article directory
One: frequency domain high-pass filtering
Frequency-domain high-pass filtering : It is an image processing technology based on frequency-domain representation, which is used to enhance or highlight the high-frequency components in the image. It enhances the edges and details of the image by converting the image to the frequency domain and applying a high-pass filter to suppress or attenuate low-frequency components
In the frequency domain, various types of high-pass filters can be designed to achieve different frequency responses
(1) Ideal high-pass filter
Ideal high-pass filter : By applying a cutoff frequency in the frequency domain, the components below the cutoff frequency are completely suppressed, while the components above the cutoff frequency are retained. This filter has a steep cutoff characteristic, but introduces ringing
H ( u , v ) = { 0 D ( u , v ) ≤ D 0 1 D ( u , v ) > D 0 H(u, v)=\left\{\begin{array}{ll}0 & D(u, v) \leq D_{0} \\1 & D(u, v)>D_{0}\end{array}\right. H(u,v)={ 01D(u,v)≤D0D(u,v)>D0
(2) Butterworth high-pass filter
Butterworth High Pass Filter : Provides smoother frequency transitions without ringing. It can adjust the cut-off frequency and the slope of the roll-off characteristic according to the design parameters
H ( u , v ) = 1 1 + [ D 0 / D ( u , v ) ] 2 n H(u, v)=\frac{1}{1+\left[D_{0} / D(u, v)\right]^{2 n}} H(u,v)=1+[D0/D(u,v)]2 n1
(3) Exponential high-pass filter
Exponential high-pass filter : Based on the characteristics of the exponential function, the low-frequency signal is suppressed in the frequency domain, thereby extracting the high-frequency details of the image
H ( u , v ) = exp { − [ D 0 D ( u , v ) ] u } H(u, v)=\exp \left\{-\left[\frac{D_{0}}{D(u, v)}\right]^{u}\right\} H(u,v)=exp{ −[D(u,v)D0]u}
(4) Ladder high-pass filter
Ladder High-Pass Filter : Unlike other high-pass filters, the frequency response of the Ladder High-Pass Filter gradually attenuates low-frequency signals and preserves high-frequency signals in the shape of a trapezoid
H ( u , v ) = { 0 D ( u , v ) < D 0 1 D 1 − D 0 [ D ( u , v ) − D 0 ] D 0 ≤ D ( u , v ) ≤ D 1 1 D ( u , v ) > D 1 H(u, v)=\left\{\begin{array}{cc}0 & D(u, v)<D_{0} \\\frac{1}{D_{1}-D_{0}}\left[D(u, v)-D_{0}\right] & D_{0} \leq D(u, v) \leq D_{1} \\1 & D(u, v)>D_{1}\end{array}\right. H(u,v)=⎩ ⎨ ⎧0D1−D01[D(u,v)−D0]1D(u,v)<D0D0≤D(u,v)≤D1D(u,v)>D1
Two: Comprehensive case - portrait beautification
(1) Design ideas
Requirements : Make the skin as smooth and fair as possible. Use the basic processing methods learned to meet the requirements of the topic
Operation :
- Image smoothing to remove blemishes
- Skin region segmentation based on skin color model;
- Blend the background part of the original image with the smooth skin image;
- Moderately sharpen the fused image
(2) Design of each module
main program
Smoothing: bilateral filtering
Skin Region Segmentation
Image fusion : extract the skin color area from the bilaterally filtered image, extract the background area from the original image, and fuse the two images
Image sharpening : p adopts Laplacian sharpening, and the sharpening intensity is reduced to 1/3
(3) Program
matlab implementation :
clear,clc,close all;
ImageOrigin=im2double(imread('face8.jpg'));
figure,imshow(ImageOrigin),title('原图');
DBImage=DBfilt(ImageOrigin);
SkinImage1=FirstFilter(ImageOrigin); %%初步过滤
SkinArea=SecondFilter(SkinImage1); %%YCgCr空间范围肤色检测
SkinFuse=Fuse(ImageOrigin,DBImage,SkinArea);
SkinBeautify=Sharp(SkinFuse);
function Out=DBfilt(In)
[height,width,c] = size(In);
win=15; % 定义双边滤波窗口宽度
sigma_s=6; sigma_r=0.1; % 双边滤波的两个标准差参数
[X,Y] = meshgrid(-win:win,-win:win);
Gs = exp(-(X.^2+Y.^2)/(2*sigma_s^2));%计算邻域内的空间权值
Out=zeros(height,width,c);
for k=1:c
for j=1:height
for i=1:width
temp=In(max(j-win,1):min(j+win,height),max(i-win,1):min(i+win,width),k);
Gr = exp(-(temp-In(j,i,k)).^2/(2*sigma_r^2));%计算灰度邻近权值
% W为空间权值Gs和灰度权值Gr的乘积
W = Gr.*Gs((max(j-win,1):min(j+win,height))-j+win+1,(max(i-win,1):min(i+win,width))-i+win+1);
Out(j,i,k)=sum(W(:).*temp(:))/sum(W(:));
end
end
end
figure,imshow(Out),title('双边滤波');
end
function Out=FirstFilter(In)
Out=In;
[height,width,c] = size(In);
IR=In(:,:,1); IG=In(:,:,2);IB=In(:,:,3);
for j=1:height
for i=1:width
if (IR(j,i)<160/255 && IG(j,i)<160/255 && IB(j,i)<160) && (IR(j,i)>IG(j,i) && IG(j,i)>IB(j,i))
Out(j,i,:)=0;
end
if IR(j,i)+IG(j,i)>500/255
Out(j,i,:)=0;
end
if IR(j,i)<70/255 && IG(j,i)<40/255 && IB(j,i)<20/255
Out(j,i,:)=0;
end
end
end
figure,imshow(Out);title('非肤色初步过滤');
end
function Out=SecondFilter(In)
IR=In(:,:,1); IG=In(:,:,2);IB=In(:,:,3);
[height,width,c] = size(In);
Out=zeros(height,width);
for i=1:width
for j=1:height
R=IR(j,i); G=IG(j,i); B=IB(j,i);
Cg=(-81.085)*R+(112)*G+(-30.915)*B+128;
Cr=(112)*R+(-93.786)*G+(-18.214)*B+128;
if Cg>=85 && Cg<=135 && Cr>=-Cg+260 && Cr<=-Cg+280
Out(j,i)=1;
end
end
end
Out=medfilt2(Out,[3 3]);
figure,imshow(Out),title('YCgCr空间范围肤色检测');
end
function Out=Fuse(ImageOrigin,DBImage,SkinArea)
Skin=zeros(size(ImageOrigin));
Skin(:,:,1)=SkinArea;
Skin(:,:,2)=SkinArea;
Skin(:,:,3)=SkinArea;
Out=DBImage.*Skin+double(ImageOrigin).*(1-Skin);
figure,imshow(Out);title('肤色与背景图像融合');
end
function Out=Sharp(In)
H=[0 -1 0;-1 4 -1;0 -1 0]; %Laplacian锐化模板
Out(:,:,:)=imfilter(In(:,:,:),H);
Out=Out/3+In;
% imwrite(Out,'man4.jpg');
figure,imshow(Out),title('Laplacia锐化图像');
end
Python implementation :
import cv2
import numpy as np
import matplotlib.pyplot as plt
def DBfilt(image):
height, width, c = image.shape
win = 15
sigma_s = 6
sigma_r = 0.1
X, Y = np.meshgrid(np.arange(-win, win + 1), np.arange(-win, win + 1))
Gs = np.exp(-(X**2 + Y**2) / (2 * sigma_s**2))
output = np.zeros((height, width, c))
for k in range(c):
for j in range(height):
for i in range(width):
temp = image[max(j - win, 0):min(j + win, height), max(i - win, 0):min(i + win, width), k]
Gr = np.exp(-(temp - image[j, i, k])**2 / (2 * sigma_r**2))
W = Gr * Gs[max(j - win, 0):min(j + win, height) - j + win + 1,
max(i - win, 0):min(i + win, width) - i + win + 1]
output[j, i, k] = np.sum(W * temp) / np.sum(W)
return output
def FirstFilter(image):
output = np.copy(image)
height, width, _ = image.shape
IR = image[:, :, 2]
IG = image[:, :, 1]
IB = image[:, :, 0]
for j in range(height):
for i in range(width):
if (IR[j, i] < 160/255 and IG[j, i] < 160/255 and IB[j, i] < 160/255) and \
(IR[j, i] > IG[j, i] and IG[j, i] > IB[j, i]):
output[j, i, :] = 0
if IR[j, i] + IG[j, i] > 500/255:
output[j, i, :] = 0
if IR[j, i] < 70/255 and IG[j, i] < 40/255 and IB[j, i] < 20/255:
output[j, i, :] = 0
return output
def SecondFilter(image):
height, width, _ = image.shape
IR = image[:, :, 2]
IG = image[:, :, 1]
IB = image[:, :, 0]
output = np.zeros((height, width))
for i in range(width):
for j in range(height):
R = IR[j, i]
G = IG[j, i]
B = IB[j, i]
Cg = (-81.085) * R + (112) * G + (-30.915) * B + 128
Cr = (112) * R + (-93.786) * G + (-18.214) * B + 128
if Cg >= 85 and Cg <= 135 and Cr >= -Cg + 260 and Cr <= -Cg + 280:
output[j, i] = 1
output = cv2.medianBlur(output.astype(np.float32), 3)
return output
def Fuse(image, db_image, skin_area):
skin = np.zeros(image.shape)
skin[:, :, 0] = skin_area
skin[:, :, 1] = skin_area
skin[:, :, 2] = skin_area
output = db_image * skin + image * (1 - skin)
return output
def Sharp(image):
kernel = np.array([[0, -1, 0], [-1, 4, -1], [0, -1, 0]], dtype=np.float32)
output = cv2.filter2D(image, -1, kernel)
output = output / 3 + image
return output
# 读取图像
image_origin = cv2.imread('face8.jpg')
image_origin = cv2.cvtColor(image_origin, cv2.COLOR_BGR2RGB)
# 显示原图
plt.figure()
plt.imshow(image_origin)
plt.title('原图')
plt.axis('off')
# 双边滤波
db_image = DBfilt(image_origin)
# 初步过滤
skin_image1 = FirstFilter(image_origin)
plt.figure()
plt.imshow(skin_image1)
plt.title('非肤色初步过滤')
plt.axis('off')
# YCgCr空间范围肤色检测
skin_area = SecondFilter(skin_image1)
plt.figure()
plt.imshow(skin_area, cmap='gray')
plt.title('YCgCr空间范围肤色检测')
plt.axis('off')
# 肤色与背景图像融合
skin_fuse = Fuse(image_origin, db_image, skin_area)
plt.figure()
plt.imshow(skin_fuse)
plt.title('肤色与背景图像融合')
plt.axis('off')
# Laplacian锐化图像
skin_beautify = Sharp(skin_fuse)
plt.figure()
plt.imshow(skin_beautify)
plt.title('Laplacia锐化图像')
plt.axis('off')
plt.show()