教你使用MATLAB制作水波倒影特效
Posted slandarer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了教你使用MATLAB制作水波倒影特效相关的知识,希望对你有一定的参考价值。
注: 本文算法参考大佬 grafx 的这篇博客:
图像处理算法之水面倒影特效
由于本文使用MATLAB复现,因此很多语法上会显得比较简洁,同时本博文对原大佬文章部分内容进行了改写,详见本文:
0效果展示
1图像翻转及白化
导入图像: 这部分其实没啥好说的:
% 图片导入
oriPic=imread('test.jpg');
[Row,Col,~]=size(oriPic);
翻转及白化图像:
翻转就是单纯的将行索引倒过来;
白化就是将当前像素的颜色按比例和白色取个带权均值,行索引越大白色权重也越大,图像也就越白。
% 图片翻转及白化 ==========================================================
whiteMat=((1:Row)./Row./1.2)'*ones(1,Col); % 白化比例矩阵
flipPic=zeros(Row,Col,3); % 翻转后矩阵初始化
for i=1:3
tempChannel=double(oriPic(:,:,i)); % 获得通道图
tempChannel=tempChannel(end:-1:1,:); % 翻转
tempChannel=tempChannel.*(1-whiteMat)+255.*whiteMat; % 白化
flipPic(:,:,i)=tempChannel;
end
当然如果我们将这一行:
tempChannel=tempChannel.*(1-whiteMat)+255.*whiteMat;
改写为:
tempChannel=tempChannel.*(1-whiteMat)+0.*whiteMat;
就变成了一个黑化的过程:
当然你也可以尝试其他颜色,例如将整段改写为:
Color=[255,0,0];
colorMat=((1:Row)./Row./1.2)'*ones(1,Col); % 比例矩阵
flipPic=zeros(Row,Col,3); % 翻转后矩阵初始化
for i=1:3
tempChannel=double(oriPic(:,:,i)); % 获得通道图
tempChannel=tempChannel(end:-1:1,:); % 翻转
tempChannel=tempChannel.*(1-colorMat)+Color(i).*colorMat; % 渐变
flipPic(:,:,i)=tempChannel;
end
imshow(uint8(flipPic))
2波纹图像构造
生成噪声并模糊
noiseMat=ones(Row,Col);
noiseMat=imnoise(noiseMat,'gaussian',0,5); % 噪声添加
gaussOpt=fspecial('gaussian',[3 3],1);
noiseMat=imfilter(noiseMat,gaussOpt);
噪声图:
模糊后噪声图:
浮雕特效
实际上浮雕特效就是用以下类似形式的矩阵对图像进行卷积,卷积结果在加上RGB范围的均值,[0,1]区间就加0.5,[0,255]区间就加128:
[
1
0
0
0
0
0
0
0
−
1
]
[
2
0
2
0
0
0
−
2
0
−
2
]
\\begin{bmatrix} 1 & 0 & 0 \\\\ 0 & 0 & 0 \\\\ 0 & 0 & -1 \\end{bmatrix} \\begin{bmatrix} 2 & 0 & 2 \\\\ 0 & 0 & 0 \\\\ -2 & 0 & -2 \\end{bmatrix}
⎣⎡10000000−1⎦⎤⎣⎡20−200020−2⎦⎤
数值和位置不重要,重要的是相对位置互为相反数,浮雕过程描述如下:
H=[cos(pi+pi/4),0,cos(pi-pi/4);
cos(pi+2*pi/4),0,cos(pi-2*pi/4);
cos(pi+3*pi/4),0,cos(pi-3*pi/4)];
noiseMat=imfilter(noiseMat,H,'conv')+0.5;
noiseMat=noiseMat.*255;
noiseMat(noiseMat<0)=0;
透视变换
就是近大远小,这里为了方便起见只在横向方向上做了近大远小的拉伸,竖直方向进行了等比例拉伸,因而不是严格意义上的透视变换:
如图所示实际操作就是把左侧蓝色区域拉伸成右侧蓝色区域,并只选取红框内部分,代码如下:
% 图像透视变换 ============================================================
exNoiseMat=zeros(Row,Col);
% 横向拉伸上下边倍数
K1=10;K2=4;
for i=1:Row
for j=1:Col
k=K2+i*(K1-K2)/Row;
nJ=(j-(1+Col)/2)/k+(1+Col)/2;
if floor(nJ)==ceil(nJ)
nJ=round(nJ);
exNoiseMat(i,j)=noiseMat(i,nJ);
else
nJ1=floor(nJ);nJ2=ceil(nJ);
exNoiseMat(i,j)=noiseMat(i,nJ1)*(nJ2-nJ)+noiseMat(i,nJ2)*(nJ-nJ1);
end
end
end
% 竖向拉伸3倍并只取一部分
exNoiseMat=imresize(exNoiseMat,[3*Row,Col]);
exNoiseMat=exNoiseMat(end-Row+1:end,:);
exNoiseMat=uint8(exNoiseMat);
注: 如果原图像尺寸过大,水波就会过于密集,这时候可以适当调整放缩倍数或者将原图像重调大小到小一点的尺寸。
例如大波浪代码:
% 图像透视变换 ============================================================
exNoiseMat=zeros(Row,Col);
K1=40;K2=10;
for i=1:Row
for j=1:Col
k=K2+i*(K1-K2)/Row;
nJ=(j-(1+Col)/2)/k+(1+Col)/2;
if floor(nJ)==ceil(nJ)
nJ=round(nJ);
exNoiseMat(i,j)=noiseMat(i,nJ);
else
nJ1=floor(nJ);nJ2=ceil(nJ);
exNoiseMat(i,j)=noiseMat(i,nJ1)*(nJ2-nJ)+noiseMat(i,nJ2)*(nJ-nJ1);
end
end
end
exNoiseMat=imresize(exNoiseMat,[8*Row,Col]);
exNoiseMat=exNoiseMat(end-Row+1:end,:);
exNoiseMat=uint8(exNoiseMat);
小波浪和大波浪:
3扭曲置换
这个。。。老朋友了,具体原理还是看这一篇叭:MATLAB 制作抖音同款含褶皱面料图
% 扭曲置换 ================================================================
forePic=flipPic;
bkgPic=exNoiseMat;
exforePic=uint8(zeros(size(forePic)+[26,26,0]));
exforePic(14:end-13,14:end-13,1)=forePic(:,:,1);
exforePic(14:end-13,14:end-13,2)=forePic(:,:,2);
exforePic(14:end-13,14:end-13,3)=forePic(:,:,3);
for i=1:13
exforePic(i,14:end-13,:)=forePic(1,:,:);
exforePic(end+1-i,14:end-13,:)=forePic(end,:,:);
exforePic(14:end-13,i,:)=forePic(:,1,:);
exforePic(14:end-13,end+1-i,:)=forePic(:,end,:);
end
for i=1:3
exforePic(1:13,1:13,i)=forePic(1,1,i);
exforePic(end-13:end,end-13:end,i)=forePic(end,end,i);
exforePic(end-13:end,1:13,i)=forePic(end,1,i);
exforePic(1:13,end-13:end,i)=forePic(1,end,i);
end
newforePic=uint8(zeros(size(forePic)));
for i=1:size(bkgPic,1)
for j=1:size(bkgPic,2)
goffset=(double(bkgPic(i,j))-128)/10;
offsetLim1=floor(goffset)+13;
offsetLim2=ceil(goffset)+13;
sep1=goffset-floor(goffset);
sep2=ceil(goffset)-goffset;
c1=double(exforePic(i+offsetLim1,j+offsetLim1,:));
c2=double(exforePic(i+offsetLim2,j+offsetLim2,:));
if sep1==0
c=double(exforePic(i+offsetLim1,j+offsetLim1,:));
else
c=c2.*sep1+c1.*sep2;
end
newforePic(i,j,:)如何在DW中做图像的水波倒影。。我指的是在DW中。请问用CSS样式中的滤镜能做到么?