http://www.cse.cuhk.edu.hk/leojia/papers/L0smooth_Siggraph_Asia2011.pdf
可以参考以上链接,介绍较为详细。而本文章注重的是代码的编写和gui界面的制作,可供小伙伴借鉴交流~
目录
实验目的
- 掌握平滑滤波高斯滤波的原理、方法及matlab实现。
- 分析相关系数的变化对处理结果的影响。
- 制作界面实现多方面功能。
实验内容
无GUI界面
- 选择一幅图片用于输入该实验;
- 接着在命令框输入kappa和lambda的值(该实验为了对比的效果设置了四组值);
- 在figure界面出现四组图片,第一张为原图,其余三张用于对比kappa和lambda的不同值时的不同效果;
- 效果如下
(学校选景)
有GUI界面(个人原创、易上手)
包括功能:选择图片、显示路径、选择参数值、显示原图与处理后图象、程序运行、程序结束。
- 设置Gui界面;
- 在界面对应位置选择图片并打开;
- 选择图片后按钮后面会显示路径,点击确定后,所选择的图片会显示在axes3框中;
- 填入kappa和lambda的值,并点击开始按钮;
- 得到该值下的平滑图象,可以重新设置两个参数的值并重新开始,可以又一次得到对比图,更改多次参数的值得到不同的图象处理并记录;
- 点击结束按钮则退出界面。
- 展示一下原始界面与效果图:(我觉得好玩的是后面的图象是慢慢由原图变成处理后的图象的~,可以多次选择不同的参数观察不同的处理图象,最后再点击结束)
数据处理方法
这部分可以借鉴别的博主,就不详细说了。
下面这个还挺好的感觉,不过我还没看懂,等我会了再更新。
再探基于L0测度的流场平滑_LYKymy的博客-CSDN博客
https://blog.csdn.net/LYKymy/article/details/84865854
所谓图像平滑,就是将图像中无关紧要的细节去除,而只保留显著的边缘部分。L0范数可以理解为向量中非零元素的个数。而L0 Smoothing是通过控制非零图像梯度的数目来增强图像显著边缘部分,以此达到图像的全局优化。
实验代码
原始代码
第一个m文件,放繁琐的图片处理过程;
function S = L0Smoothing(Im, lambda, kappa)
if ~exist('kappa','var')
kappa = 2.0;
end
if ~exist('lambda','var')
lambda = 2e-2;
end
%kappa=input('请输入Kappa的值');
%lambda=input('请输入lambda的值');
%lambda=lambda/100;
S = im2double(Im);
betamax = 1e5;
fx = [1, -1];
fy = [1; -1];
[N,M,D] = size(Im);
sizeI2D = [N,M];
otfFx = psf2otf(fx,sizeI2D);
otfFy = psf2otf(fy,sizeI2D);
Normin1 = fft2(S);
Denormin2 = abs(otfFx).^2 + abs(otfFy ).^2;
if D>1
Denormin2 = repmat(Denormin2,[1,1,D]);
end
beta = 2*lambda;
while beta < betamax
Denormin = 1 + beta*Denormin2;
% h-v subproblem
h = [diff(S,1,2), S(:,1,:) - S(:,end,:)];
v = [diff(S,1,1); S(1,:,:) - S(end,:,:)];
if D==1
t = (h.^2+v.^2)<lambda/beta;
else
t = sum((h.^2+v.^2),3)<lambda/beta;
t = repmat(t,[1,1,D]);
end
h(t)=0; v(t)=0;
% S subproblem
Normin2 = [h(:,end,:) - h(:, 1,:), -diff(h,1,2)];
Normin2 = Normin2 + [v(end,:,:) - v(1, :,:); -diff(v,1,1)];
FS = (Normin1 + beta*fft2(Normin2))./Denormin;
S = real(ifft2(FS));
beta = beta*kappa;
fprintf('.');
end
end
第二个m文件,选择图片,展示处理结果,可以把注释掉的打开,中间两行注释掉。分别是一张处理图象和两张处理图象的效果。别的效果可以自行改动一下。
Im = imread('美景.jpg');
% subplot(1,2,1);
% imshow(Im);
% hold on;
S = L0Smoothing(Im,0.1);
figure, imshow(S);
% subplot(1,2,2);
% imshow(S);
% hold on;
% %close all;
(更改注释前和更改注释后,自己调)
无GUI界面代码,可调参数,四张图
clc
Im = imread('美景.jpg');
% if ~exist('kappa','var')
% kappa = 2.0;
% end
% if ~exist('lambda','var')
% lambda = 2e-2;
% end
S = im2double(Im);
subplot(2,2,1)
imshow(S)
ylabel('原图')
for i=2:4
kappa=input('请输入Kappa的值')
lambda=input('请输入lambda的值');
betamax = 1e5;
fx = [1, -1];
fy = [1; -1];
[N,M,D] = size(Im);
sizeI2D = [N,M];
%把一个空间点扩散函数转换为频谱面的光学传递函数
otfFx = psf2otf(fx,sizeI2D);
otfFy = psf2otf(fy,sizeI2D);
Normin1 = fft2(S);
Denormin2 = abs(otfFx).^2 + abs(otfFy ).^2;
if D>1
Denormin2 = repmat(Denormin2,[1,1,D]);
end
%F(1)+β(F(?x)?F(?x)+F(?y)?F(?y))
beta = 2*lambda;
while beta < betamax
Denormin = 1 + beta*Denormin2;
% h-v subproblem
h = [diff(S,1,2), S(:,1,:) - S(:,end,:)];
v = [diff(S,1,1); S(1,:,:) - S(end,:,:)];
if D==1
t = (h.^2+v.^2)<lambda/beta;
else
t = sum((h.^2+v.^2),3)<lambda/beta;
t = repmat(t,[1,1,D]);
end
h(t)=0; v(t)=0;
% S subproblem
Normin2 = [h(:,end,:) - h(:, 1,:), -diff(h,1,2)];
Normin2 = Normin2 + [v(end,:,:) - v(1, :,:); -diff(v,1,1)];
FS = (Normin1 + beta*fft2(Normin2))./Denormin;
S = real(ifft2(FS));
beta = beta*kappa;
end
subplot(2,2,i)
imshow(S)
end
效果图:
有GUI界面图代码
建立GUI 2018b 主页-新建-图窗-文件-新建-GUI(G)就拖动建立下面fig;
如果建好想修改,可以在命令框输入guide选择你制作的fig得到下面这个;
function varargout = untitled(varargin)
gui_Singleton = 1;
gui_State = struct('gui_Name', mfilename, ...
'gui_Singleton', gui_Singleton, ...
'gui_OpeningFcn', @untitled_OpeningFcn, ...
'gui_OutputFcn', @untitled_OutputFcn, ...
'gui_LayoutFcn', [] , ...
'gui_Callback', []);
if nargin && ischar(varargin{1})
gui_State.gui_Callback = str2func(varargin{1});
end
if nargout
[varargout{1:nargout}] = gui_mainfcn(gui_State, varargin{:});
else
gui_mainfcn(gui_State, varargin{:});
end
% --- Executes just before untitled is made visible.
function untitled_OpeningFcn(hObject, eventdata, handles, varargin)
handles.output = hObject;
guidata(hObject, handles);
% --- Outputs from this function are returned to the command line.
function varargout = untitled_OutputFcn(hObject, eventdata, handles)
varargout{1} = handles.output;
% 选择图片
function pushbutton5_Callback(hObject,eventdata,handles)
[filename,pathname] = uigetfile({'*.jpg';'*.bmp';'*.gif';'*.png'},'选择文件');
% if isequal(filename,0) || isequal(filepath,0)
% errordlg('没有选中文件,请重新选择','出错');
% return;
% else
set(handles.edit2,'string',[pathname filename])
% end
guidata(hObject,handles) %保存和更新handles结构体
road=get(handles.edit2,'string'); %文本框中的路径赋值给road,作为传递的变量
handles.road=road;
guidata(hObject, handles)
%文本框
function edit2_Callback()
returns contents of edit2 as a double
%确定按钮
function pushbutton6_Callback(hObject, eventdata, handles)
road=handles.road;
axes(handles.axes3); %在第一个轴中显示
imshow(road);
% 开始
function pushbutton1_Callback(hObject, eventdata, handles)
road=handles.road; %记得呜呜呜
Im=imread(road);
%S = L0Smoothing(Im,0.07);
% figure, imshow(S);
% axes(handles.axes4);
% imshow(S);
S = im2double(Im);
global kappa;
global lambda;
kappa_data1 = get(handles.edit3,'String');
kappa = str2double(kappa_data1);
% kappa=edit3
% lambda=input('请输入lambda的值');
lambda_data1 = get(handles.edit4,'String');
lambda = str2double(lambda_data1);
betamax = 1e5;
fx = [1, -1];
fy = [1; -1];
[N,M,D] = size(Im);
sizeI2D = [N,M];
%把一个空间点扩散函数转换为频谱面的光学传递函数
otfFx = psf2otf(fx,sizeI2D);
otfFy = psf2otf(fy,sizeI2D);
Normin1 = fft2(S);
Denormin2 = abs(otfFx).^2 + abs(otfFy ).^2;
if D>1
Denormin2 = repmat(Denormin2,[1,1,D]);
end
%F(1)+β(F(?x)?F(?x)+F(?y)?F(?y))
beta = 2*lambda;
while beta < betamax
Denormin = 1 + beta*Denormin2;
% h-v subproblem
h = [diff(S,1,2), S(:,1,:) - S(:,end,:)];
v = [diff(S,1,1); S(1,:,:) - S(end,:,:)];
if D==1
t = (h.^2+v.^2)<lambda/beta;
else
t = sum((h.^2+v.^2),3)<lambda/beta;
t = repmat(t,[1,1,D]);
end
h(t)=0; v(t)=0;
% S subproblem
Normin2 = [h(:,end,:) - h(:, 1,:), -diff(h,1,2)];
Normin2 = Normin2 + [v(end,:,:) - v(1, :,:); -diff(v,1,1)];
FS = (Normin1 + beta*fft2(Normin2))./Denormin;
S = real(ifft2(FS));
beta = beta*kappa;
axes(handles.axes4);
imshow(S)
end
%
function pushbutton1_ButtonDownFcn(hObject, eventdata, handles)
% --------------------------------------------------------------------
function Untitled_1_Callback(hObject, eventdata, handles)
% --- Executes during object creation, after setting all properties.
function axes1_CreateFcn(hObject, eventdata, handles)
% --- Executes during object creation, after setting all properties.
function edit1_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
% --- Executes during object creation, after setting all properties.
function edit2_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
% 结束
function pushbutton2_Callback(hObject, eventdata, handles)
close all;
%kappa
function edit3_Callback(hObject, eventdata, handles)
% Hints: get(hObject,'String') returns contents of edit3 as text
% str2double(get(hObject,'String')) returns contents of edit3 as a double
% --- Executes during object creation, after setting all properties.
function edit3_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
function edit4_Callback(hObject, eventdata, handles)
% --- Executes during object creation, after setting all properties.
function edit4_CreateFcn(hObject, eventdata, handles)
if ispc && isequal(get(hObject,'BackgroundColor'), get(0,'defaultUicontrolBackgroundColor'))
set(hObject,'BackgroundColor','white');
end
% --- Executes when figure1 is resized.
function figure1_SizeChangedFcn(hObject, eventdata, handles)
就上面酱紫了。
关键环节
做好本实验需要把握的关键环节
- 不同参数Kappa和lambda的值的选择
- 对L0S图象平滑原理的理解与数学公式的运用
- 图象的对比结果显示
- 在gui界面中多个变量需要设置为全局变量
- 在gui界面的制作中要注意多路径的赋值与变量的传递
先酱紫了,有问题希望小伙伴指正呦!