基于APP Designer完成MATLAB大作业之简易版美图秀秀设计
目录
一、基础功能
二、添加效果
三、调色
四、美颜
五、贴图
六、相框
一、基础功能
1 导入图片
function ButtonImport(app, event)
[filename,pathname]=uigetfile({'*.*';'*.jpg';'*.tif';'*.png';'*.bmp'},'导入图片');%选择图片的格式
if isequal(pathname,0)
errordlg('未选择文件','错误');%创建错误对话框
return
else
file=[pathname filename];
I=imread(file);
app.OriginalImage=file;% app.OriginalImage为全局变量,存储原始图像
app.ChangedImage=I;% app.ChangedImage为全局变量,存储最近改变的图像
app.EffectImage=I;% app.EffectImage为全局变量,与app.ChangedImage作用相似,作为某些功能的读入图像
end
imshow(I,'Parent',app.UIAxes);
end
效果:
2 保存图片
function ButtonSave(app, event)
[filename,pathname]=uiputfile({'*.*';'*.jpg';'*.tif';'*.png';'*.bmp'},'保存图片');%选择图片的格式
if isequal(pathname,0)
msgbox("保存失败!");
else
I=fullfile(pathname,filename);% 构建完整文件名
imwrite(app.ChangedImage,I);
msgbox("保存成功!");
end
end
效果:
3 重置
function ButtonReset(app, event)
app.ChangedImage=imread(app.OriginalImage);%app.OriginalImage为全局变量,存储原始图像
imshow(app.ChangedImage,'Parent',app.UIAxes);
app.Slider.Value=0;% 令布局中的滑块归为默认位置
app.Slider_2.Value=0;
app.Slider_3.Value=0;
app.Slider_5.Value=0;
app.Slider_6.Value=0;
end
4 退出
function ButtonExit(app, event)
exit=questdlg('是否退出程序?','关闭','Yes','No','No');%创建问题对话框,是否关闭程序,默认为No
switch exit
case 'Yes'
delete(app.UIFigure);%删除APP中的UI图窗
return
case 'No'
return
end
end
效果:
5 旋转
function ButtonRotate(app, event)
I=app.ChangedImage;
R=imrotate(I,-90);% 顺时针旋转90度
app.ChangedImage=R;
imshow(app.ChangedImage,'Parent',app.UIAxes);
app.EffectImage=R;
end
效果:
6 裁剪
function ButtonCrop(app, event)
I=app.ChangedImage;
imshow(I);% 弹出裁剪弹窗
[x,y]=ginput(2);% 识别坐标区区域
close;
I2=imcrop(I,[x(1),y(1),abs(x(1)-x(2)),abs(y(1)-y(2))]);
imshow(I2,'Parent',app.UIAxes)
app.ChangedImage=I2;
app.EffectImage=I2;
end
效果:
7 水平翻转
function ButtonH_flip(app, event)
I=app.ChangedImage;
F=fliplr(I);
imshow(F,'Parent',app.UIAxes);
app.ChangedImage=F;
app.EffectImage=F;
end
效果:
8 垂直翻转
function ButtonV_flip(app, event)
I=app.ChangedImage;
F=flipud(I);
imshow(F,'Parent',app.UIAxes);
app.ChangedImage=F;
app.EffectImage=F;
end
效果:
二、添加效果
1 灰度化
function ButtonGray(app, event)
I=app.EffectImage;
I=im2gray(I);
imshow(I,'Parent',app.UIAxes);
app.ChangedImage=I;
end
效果:
2 黑白
function ButtonBW(app, event)
I=app.EffectImage;
I=rgb2gray(I);
I=im2bw(I);
imshow(I,'Parent',app.UIAxes);
app.ChangedImage=I;
end
效果:
3 底片
function Button_DP(app, event)
I=app.EffectImage;
I=255-I;
I=im2gray(I);
imshow(I,'Parent',app.UIAxes);
app.ChangedImage=I;
end
效果:
4 素描
function ButtonSketch(app, event)
I=app.EffectImage;
% 灰度化
I_gray=im2gray(I);
% 反色
J=255-I_gray;
% 创建8x8高斯滤波器
g=fspecial('gaussian',[8 8],8);
% 用滤波器g对图像J进行滤波
K=imfilter(J,g);
[m,n]=size(I_gray);
for i=1:m
for j=1:n
% 为模糊后的图像添加减淡效果
img(i,j)=uint8(min(uint16(I_gray(i,j))+(uint16(I_gray(i,j))*uint16(K(i,j)))/(255-uint16(K(i,j))),255));% 减淡公式
end
end
imshow(img,'Parent',app.UIAxes);
app.ChangedImage=img;
end
效果:
5 增强
function ButtonStrengthen(app, event)
I=app.EffectImage;
J=histeq(I);% 直方图均衡化
imshow(J,'Parent',app.UIAxes);
app.ChangedImage=J;
end
效果:
6 模糊
function ButtonBlurred(app, event)
I=app.EffectImage;
% 创建运动模糊滤波器
PSF=fspecial('motion',25,11);
% 对原图滤波,模糊图像
Blurred=imfilter(I,PSF,'conv','circular');
imshow(Blurred,'Parent',app.UIAxes);
app.ChangedImage=Blurred;
end
效果:
7 锐化
function ButtonSharpen(app, event)
I=app.EffectImage;
I2=im2gray(I);
edge=uint8(zeros(size(I2)));
h=size(I2,1);
w=size(I2,2);
for i=1:h-1
for j=1:w-1
edge(i,j)=uint8(abs(I2(i,j)-I2(i+1,j+1))+abs(I2(i+1,j)-I2(i,j+1)));% Robert算子
end
end
J=edge+I;
imshow(J,'Parent',app.UIAxes);%显示图像edge
app.ChangedImage=J;
end
效果:
8 浮雕
function ButtonRelief(app, event)
I=app.EffectImage;
[m,n,d]=size(I)
for k=1:d
for i=2:m-1
for j=2:n-1
% 浮雕算法卷积公式
I2(i,j,k)=I(i+1,j+1,k)-I(i-1,j-1,k)+128;
if I2(i,j,k)>255
I2(i,j,k)=255;
else if I2(i,j,k)<0
I2(i,j,k)=0;
else I2(i,j,k)=I2(i,j,k);
end
end
end
end
end
imshow(I2,'Parent',app.UIAxes);
app.ChangedImage=I2;
end
效果:
9 油画
function ButtonOilPaint(app, event)
I=app.EffectImage;
SE=strel('ball',3,3);
P=imerode(I,SE);
imshow(P,'Parent',app.UIAxes);
app.ChangedImage=P;
end
效果:
10 马赛克
function Button_MSK(app, event)
%原图的路径
f = app.EffectImage;
imshow(f);
% 用imrect框出某一部分
t=imrect;
% 其中pos的返回值中有四个参数,[xmin,ymin,width,height],
pos=getPosition(t);
% 选取位置结束后关闭窗口
close;
a=int16(pos(1,1));% x
b=int16(pos(1,2));% y
c=int16(pos(1,3));% width
d=int16(pos(1,4));% height
% 用imcrop截图
g=imcrop(f,pos);
gr = g(:,:,1);
[h w] = size(gr);
% 截图区域
img = g;
%设置马赛克区域n*n像素块大小,一个区域内为同一个颜色值
n = 20;
nh = floor(h/n)*n;%将不一定是n的整数倍的图像大小化为整数倍
nw = floor(w/n)*n;
%对三个通道进行循环处理
%对框处区域做单独均值滤波处理
for t = 1:3
% 1为起始值,n为步长,nh为终止值
for j = 1:n:nh
% 1为起始值,n为步长,nw为终止值
for i = 1:n:nw
img(j:j+n-1, i:i+n-1, t) =mean(mean(g(j:j+n-1, i:i+n-1, t)));%对列进行取均值处理,mean为求数组的均值
end
img(j:j+n-1,nw:w , t ) = mean(mean(g(j:j+n-1,nw:w , t)));%处理最后的列
end
for i = 1:n:nw
img(nh:h, i:i+n-1, t) = mean(mean(g(nh:h, i:i+n-1, t)));%处理最后的行
end
img(nh:h, nw:w, t) = mean(mean(g(nh:h, nw:w , t)));%处理最后的角
end
% 将马赛克区域放回到原图像当中
f(b:b+d,a:a+c,1:3)=img(:,:,1:3);
imshow(f,'Parent',app.UIAxes);
app.ChangedImage=f;
end
效果:
三、调色
1 色调
function SliderValueChangingSD(app, event)
changingValue = event.Value;
I=app.ChangedImage;
hsv=rgb2hsv(I);
hsv(:,:,1)=(changingValue+1)*hsv(:,:,1);
hsv(:,:,2)=hsv(:,:,2);
hsv(:,:,3)=hsv(:,:,3);
img=hsv2rgb(hsv);
imshow(img,'Parent',app.UIAxes);
app.HSV2=img;
end
效果:
2 饱和度
function Slider_2ValueChangingBHD(app, event)
changingValue = event.Value;
I=app.HSV2;
hsv=rgb2hsv(I);
hsv(:,:,2)=(changingValue+1)*hsv(:,:,2);
hsv(:,:,1)=hsv(:,:,1);
hsv(:,:,3)=hsv(:,:,3);
img=hsv2rgb(hsv);
imshow(img,'Parent',app.UIAxes);
app.HSV1=img;
end
效果:
3 明度
function Slider_3ValueChangingLD(app, event)
changingValue = event.Value;
I=app.HSV1;
hsv=rgb2hsv(I);
hsv(:,:,3)=(changingValue+1)*hsv(:,:,3);
hsv(:,:,1)=hsv(:,:,1);
hsv(:,:,2)=hsv(:,:,2);
img=hsv2rgb(hsv);
imshow(img,'Parent',app.UIAxes);
app.ChangedImage=img;
end
效果:
四、美颜
1 美白
function Slider_5ValueChangingBeauty(app, event)
changingValue = event.Value;
I=app.EffectImage;
I1=rgb2ycbcr(I);%将图片的RGB值转换成YCbCr值
YY=I1(:,:,1);%YY为亮度信号
Cb=I1(:,:,2);%Cb为蓝色色度分量
Cr=I1(:,:,3);%Cy为红色色度分量
[x y z]=size(I1);%获取图像大小
tst=zeros(x,y);%建立大小为xy的零矩阵
Mb=mean(mean(Cb));%返回Cb矩阵的包含每列均值的行向量的均值
Mr=mean(mean(Cr));%返回Cy矩阵的包含每列均值的行向量的均值
% 计算Cb、Cr的均方差
Tb=Cb-Mb;
Tr=Cr-Mr;
Db=sum(sum((Tb).*(Tb)))/(x*y);
Dr=sum(sum((Tr).*(Tr)))/(x*y);
% 根据阀值的要求提取出near-white区域的像素点
cnt=1;
for i=1:x
for j=1:y
b1=Cb(i,j)-(Mb+Db*sign(Mb));%sign为符号函数
b2=Cr(i,j)-(Mr+Dr*sign(Mr));
if (b1<abs(1.5*Db)&&b2<abs(1.5*Dr))
J(cnt)=YY(i,j);
tst(i,j)=YY(i,j);
cnt=cnt+1;
end
end
end
cnt=cnt-1;
K=sort(J,'descend');%将提取出的像素点按降序排列
nn=round(cnt/(changingValue+6.05));%参考白点
H(1:nn)=K(1:nn);%提取出near-white区域中的参考白点
% 提取出参考白点的RGB三信道的值
mn=min(H);
for i=1:x
for j=1:y
if tst(i,j)<mn
tst(i,j)=0;
else
tst(i,j)=1;
end
end
end
R=I(:,:,1);
G=I(:,:,2);
B=I(:,:,3);
R=double(R).*tst;
G=double(G).*tst;
B=double(B).*tst;
% 计算参考白点的RGB的均值
Rav=mean(mean(R));
Gav=mean(mean(G));
Bav=mean(mean(B));
Ymax=double(max(max(YY)))*0.15;%计算图片亮度的最大值
% 计算出RGB三信道的增益
Rgain=Ymax/Rav;
Ggain=Ymax/Gav;
Bgain=Ymax/Bav;
% 通过增益调整图片的RGB三信道
I(:,:,1)=I(:,:,1)*Rgain;
I(:,:,2)=I(:,:,2)*Ggain;
I(:,:,3)=I(:,:,3)*Bgain;
imshow(I,'Parent',app.UIAxes);
app.ChangedImage=I;
end
效果:
2 磨皮
function Slider_6ValueChangingBuffing(app, event)
changingValue = event.Value;
img0=app.EffectImage;
tempsize = 5;%控制高斯滤波器大小的参数
sigma1 = 5;%控制高斯滤波器的标准差,越大,平滑程度越好
sigma2=changingValue+0.01;%控制灰度的敏感性,灰度差越大,权重越小
% padarray用于填充高斯滤波器数组,便于卷积操作,否则图片边界易出现黑边
img = double(padarray(img0,[tempsize,tempsize],0))/255;% 在每个维度都添加tempsize个0
%通道提取
imgr = img(:,:,1);
imgg = img(:,:,2);
imgb = img(:,:,3);
[m,n] = size(imgr);
img(:,:,1) = B_filter(imgr,tempsize,sigma1,sigma2);
img(:,:,2) = B_filter(imgg,tempsize,sigma1,sigma2);
img(:,:,3) = B_filter(imgb,tempsize,sigma1,sigma2);
img=img(tempsize+1:m-tempsize,tempsize+1:n-tempsize,:);%只显示彩色区域,取出黑边
imshow(img,'Parent',app.UIAxes)
app.ChangedImage=img;
function out = B_filter(Img,tempsize,sigma0,sigma1)
%高斯滤波器模板定义
gauss = fspecial('gaussian',2*tempsize+1,sigma0);%创建旋转对称的高斯低通滤波器
[m,n] = size(Img);
for i = 1+ tempsize : m - tempsize
for j = 1+ tempsize : n - tempsize
%提取处理区域得到梯度敏感矩阵
temp = abs(Img(i - tempsize:i + tempsize,j - tempsize:j + tempsize) - Img(i,j));
temp = exp(-temp.^2/(2*sigma1^2));
%得到双边滤波器并将权值和化为一
filter = gauss.*temp;% 双边滤波权值
filter = filter/sum(filter(:));% 权值归一化
%卷积
Img(i,j) = sum(sum((Img(i - tempsize:i + tempsize,j - tempsize:j + tempsize).*filter)));% 得到滤波后的图像
end
end
out = Img;
end
end
效果:
五、贴图
function ImageClickedCat1(app, event)
rgb=app.EffectImage;
I = rgb2gray(rgb);
[n1,n2] = size(I);
h = ones(9)/81;
I = uint8(conv2(I,h));% 均值滤波,将矩阵I、h进行卷积
BW = imbinarize(I);% 将原图像二值化
B = ones(21);% 结构元素,构造一个21x21的全1矩阵
BW = BW-imerode(BW,B);% 用模板B对二值化图像进行腐蚀,再用二值化图像减去腐蚀图像得到图像边界
BW = bwmorph(BW,'thicken');% 针对二值图像的形态学运算,通过向对象外部添加像素来加厚对象,直到先前未连通的对象实现8连通为止
BW = not(bwareaopen(not(BW), 300));% 面积开运算,not为逻辑求反,bwareaopen从二值图像 BW 中删除少于300个像素的所有连通分量(对象),并生成另一个二值图像BW,填洞
%进行形态学运算
B = strel('line',50,90);% 构建形态结构元素B
BW = imdilate(BW,B);% 膨胀运算
BW = imerode(BW,B);% 腐蚀运算
B = strel('line',10,0);% 构建形态结构元素B
BW = imerode(BW,B);% 腐蚀运算
%细分
div = 10;
r = floor(n1/div);% 分成10块行,floor将每个元素四舍五入到小于或等于该元素的最接近整数
c = floor(n2/div);
x1 = 1;% 对应行初始化
x2 = r;
s = r*c;% 块面积
%判断人脸是否处于图片四周,如果不是就全部弄黑,二值化操作
for i=1:div
y1 = 1;%对应列初始化
y2 = c;
for j=1:div
loc = find(BW(x1:x2,y1:y2)==0);% 统计这一块黑色像素的位置
num = length(loc);% 返回loc中最大数组维度的长度
rate = num*100/s;% 统计黑色像素占比
if (y2<=0.2*div*c||y2>=0.8*div*c)||(x1<=r||x2>=r*div)
if rate <=100
BW(x1:x2,y1:y2) = 0;
end
%imshow(BW)
else
if rate <=25
BW(x1:x2,y1:y2) = 1;
end
%imshow(BW)
end% 下一列
y1 = y1 + c;
y2 = y2 + c;
end% 下一行
x1 = x1 + r;
x2 = x2 + r;
end
L = bwlabel(BW,8);% 利用bwlabel函数对8连通域区间进行标号,返回与BW同样大小的标记了的矩阵
BB = regionprops(L,'BoundingBox');% 得到矩形框,框柱每一个连通域,返回框的参数值
BB = cell2mat(struct2cell(BB));% 先将结构体转换为元胞数组,再将元胞数组转化为普通数组
[s1,s2] = size(BB);% 获取数组BB的大小
BB = reshape(BB,4,s1*s2/4)';% 将数组重构为一个4xs1*s2/4的矩阵;
pickshape = BB(:,3)./BB(:,4);
shapeind = BB(0.3<pickshape&pickshape<3,:);% 筛选掉尺寸比例不合格
[~,arealind] = max(shapeind(:,3).*shapeind(:,4));
[fore_img,map,alpha]=imread('mm2.png');% 读入当前选择的贴图
angle_eyes=0;
%取矩形框的中心点,确定贴图的位置
pos_x=shapeind(arealind,1)+shapeind(arealind,3)/2;
pos_y=shapeind(arealind,2)+shapeind(arealind,3)/2;
size_ear=1.5*shapeind(arealind,3);% 将贴图放大一定倍数
image = stick_picture(rgb,fore_img,pos_x,pos_y,size_ear,angle_eyes,alpha);% 调用贴图函数
imshow(image,'Parent',app.UIAxes);
app.ChangedImage=image;
%贴图的函数
function back_img = stick_picture(back_img,fore_img,pos_x,pos_y,fore_size,angle,alpha)
%调整贴图图像大小,返回图像fore_img,其行数和列数由二元素向量 [numrows numcols] 指定。
scale_img = imresize(fore_img, [uint16(fore_size),uint16(fore_size)]);
alpha = imresize(alpha, [uint16(fore_size),uint16(fore_size)]);
%angle为旋转度数,'crop',使输出图像 J 与输入图像 I 大小相同,裁剪旋转后的图像以适应边界框。
scale_img = imrotate(scale_img, angle, 'crop');
alpha = imrotate(alpha, angle, 'crop');
%获取调整大小后的贴图图像大小
scale_size = size(scale_img);
h = scale_size(1);
w = scale_size(2);
%获取背景图片大小
hh = size(back_img,1);
ww = size(back_img,2);
delt_h = uint16(pos_y - h/2);
delt_w = uint16(pos_x - w/2);
for i = 1:h
for j = 1:w
if alpha(i,j)~=0 && i+delt_h<=hh && i+delt_h>0 && j+delt_w<=ww && j+delt_w>0 % 透明度检查和越界检查
back_img(i+delt_h,j+delt_w,1) = (uint16(alpha(i,j)) * uint16(scale_img(i,j,1)) + uint16(255-alpha(i,j)) * uint16( back_img(i+delt_h,j+delt_w,1) ) )/255;
back_img(i+delt_h,j+delt_w,2) = (uint16(alpha(i,j)) * uint16(scale_img(i,j,2)) + uint16(255-alpha(i,j)) * uint16( back_img(i+delt_h,j+delt_w,2) ) )/255;
back_img(i+delt_h,j+delt_w,3) = (uint16(alpha(i,j)) * uint16(scale_img(i,j,3)) + uint16(255-alpha(i,j)) * uint16( back_img(i+delt_h,j+delt_w,3) ) )/255;
end
end
end
end
end
效果:
六、相框
function Image5Clicked_XK1(app, event)% 与贴图功能中的贴图函数几乎相同,稍加改动
I=app.EffectImage;
[fore_img,map,alpha]=imread('xk4.png');
% 获取原图的行列数,便于在函数中获取行列值,将贴图大小与图片大小统一
[m,n,h]=size(I);
angle=0;
pos_x=0;
pos_y=n/2;
img = stick_picture(I,fore_img,pos_x,pos_y,m,n,angle,alpha);
imshow(img,'Parent',app.UIAxes);
app.ChangedImage=img;
% 贴图的函数
function back_img = stick_picture(back_img,fore_img,pos_x,pos_y,m,n,angle,alpha)
% 调整贴图图像大小,返回图像fore_img,其行数和列数由二元素向量 [numrows numcols] 指定。
scale_img = imresize(fore_img, [m,n]);
alpha = imresize(alpha, [m,n]);
% angle为旋转度数,'crop',使输出图像 J 与输入图像 I 大小相同,裁剪旋转后的图像以适应边界框。
scale_img = imrotate(scale_img, angle, 'crop');
alpha = imrotate(alpha, angle, 'crop');
% 获取调整大小后的贴图图像大小
scale_size_ = size(scale_img);
h = scale_size_(1);
w = scale_size_(2);
% 获取背景图片大小
hh = size(back_img,1);
ww = size(back_img,2);
delt_h = uint16(pos_y - h/2);
delt_w = uint16(pos_x - w/2);
for i = 1:h
for j = 1:w
if alpha(i,j)~=0 && i+delt_h<=hh && i+delt_h>0 && j+delt_w<=ww && j+delt_w>0 % 透明度检查和越界检查
% 贴图与原图按一定比例加权
back_img(i+delt_h,j+delt_w,1) = (uint16(alpha(i,j)) * uint16(scale_img(i,j,1)) + uint16(255-alpha(i,j)) * uint16( back_img(i+delt_h,j+delt_w,1) ) )/255;
back_img(i+delt_h,j+delt_w,2) = (uint16(alpha(i,j)) * uint16(scale_img(i,j,2)) + uint16(255-alpha(i,j)) * uint16( back_img(i+delt_h,j+delt_w,2) ) )/255;
back_img(i+delt_h,j+delt_w,3) = (uint16(alpha(i,j)) * uint16(scale_img(i,j,3)) + uint16(255-alpha(i,j)) * uint16( back_img(i+delt_h,j+delt_w,3) ) )/255;
end
end
end
end
end
效果:
文章来源:https://www.toymoban.com/news/detail-518694.html
文章来源地址https://www.toymoban.com/news/detail-518694.html
到了这里,关于MATLAB大作业——美图秀秀的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!