基于Matlab實(shí)現(xiàn)水波倒影特效的制作
1.使用效果


2.圖像翻轉(zhuǎn)及白化
導(dǎo)入圖像:
% 圖片導(dǎo)入
oriPic=imread('test.jpg');
[Row,Col,~]=size(oriPic);
翻轉(zhuǎn)及白化圖像:
翻轉(zhuǎn)就是單純的將行索引倒過來;
白化就是將當(dāng)前像素的顏色按比例和白色取個帶權(quán)均值,行索引越大白色權(quán)重也越大,圖像也就越白。
% 圖片翻轉(zhuǎn)及白化 ==========================================================
whiteMat=((1:Row)./Row./1.2)'*ones(1,Col); % 白化比例矩陣
flipPic=zeros(Row,Col,3); % 翻轉(zhuǎn)后矩陣初始化
for i=1:3
tempChannel=double(oriPic(:,:,i)); % 獲得通道圖
tempChannel=tempChannel(end:-1:1,:); % 翻轉(zhuǎn)
tempChannel=tempChannel.*(1-whiteMat)+255.*whiteMat; % 白化
flipPic(:,:,i)=tempChannel;
end
當(dāng)然如果我們將這一行:
tempChannel=tempChannel.*(1-whiteMat)+255.*whiteMat;
更改為:
tempChannel=tempChannel.*(1-whiteMat)+0.*whiteMat;
就變成了一個黑化的過程:

當(dāng)然你也可以嘗試其他顏色,例如將整段改寫為:
Color=[255,0,0];
colorMat=((1:Row)./Row./1.2)'*ones(1,Col); % 比例矩陣
flipPic=zeros(Row,Col,3); % 翻轉(zhuǎn)后矩陣初始化
for i=1:3
tempChannel=double(oriPic(:,:,i)); % 獲得通道圖
tempChannel=tempChannel(end:-1:1,:); % 翻轉(zhuǎn)
tempChannel=tempChannel.*(1-colorMat)+Color(i).*colorMat; % 漸變
flipPic(:,:,i)=tempChannel;
end
imshow(uint8(flipPic))
3.波紋圖像構(gòu)造
生成噪聲并模糊:
noiseMat=ones(Row,Col);
noiseMat=imnoise(noiseMat,'gaussian',0,5); % 噪聲添加
gaussOpt=fspecial('gaussian',[3 3],1);
noiseMat=imfilter(noiseMat,gaussOpt);噪聲圖:

模糊后噪聲圖:

浮雕特效:
實(shí)際上浮雕特效就是用以下類似形式的矩陣對圖像進(jìn)行卷積,卷積結(jié)果再加上RGB范圍的均值,[0,1]區(qū)間就加0.5,[0,255]區(qū)間就加128:

數(shù)值和位置不重要,重要的是相對位置互為相反數(shù),浮雕過程描述如下:
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;

透視變換:
就是近大遠(yuǎn)小,這里為了方便起見只在橫向方向上做了近大遠(yuǎn)小的拉伸,豎直方向進(jìn)行了等比例拉伸,因而不是嚴(yán)格意義上的透視變換:

如圖所示實(shí)際操作就是把左側(cè)藍(lán)色區(qū)域拉伸成右側(cè)藍(lán)色區(qū)域,并只選取紅框內(nèi)部分,代碼如下:
% 圖像透視變換 ============================================================
exNoiseMat=zeros(Row,Col);
% 橫向拉伸上下邊倍數(shù)
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);
注: 如果原圖像尺寸過大,水波就會過于密集,這時候可以適當(dāng)調(diào)整放縮倍數(shù)或者將原圖像重調(diào)大小到小一點(diǎn)的尺寸。
例如大波浪代碼:
% 圖像透視變換 ============================================================
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);小波浪及大波浪:


4.扭曲置換
這個。。。老朋友了,具體原理還是看這一篇叭:利用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,:)=c;
end
end

5.圖像拼接
就是把倆圖像拼在一起,并把邊緣模糊一下:
% 圖像拼接 ================================================================
resultPic(:,:,1)=[oriPic(:,:,1);newforePic(:,:,1)];
resultPic(:,:,2)=[oriPic(:,:,2);newforePic(:,:,2)];
resultPic(:,:,3)=[oriPic(:,:,3);newforePic(:,:,3)];
% imshow(resultPic)
% 邊緣模糊 ================================================================
gaussOpt=fspecial('gaussian',[3 3],0.5);
gaussPic=imfilter(resultPic,gaussOpt);
resultPic(Row-1:Row+2,:,1)=gaussPic(Row-1:Row+2,:,1);
resultPic(Row-1:Row+2,:,2)=gaussPic(Row-1:Row+2,:,2);
resultPic(Row-1:Row+2,:,3)=gaussPic(Row-1:Row+2,:,3);
imshow(resultPic)
6.完整代碼
function mirrorDown
% @author slandarer
% 圖片導(dǎo)入
oriPic=imread('test.jpg');
[Row,Col,~]=size(oriPic);
% 圖片翻轉(zhuǎn)及白化 ==========================================================
whiteMat=((1:Row)./Row./1.2)'*ones(1,Col); % 白化比例矩陣
flipPic=zeros(Row,Col,3); % 翻轉(zhuǎn)后矩陣初始化
for i=1:3
tempChannel=double(oriPic(:,:,i)); % 獲得通道圖
tempChannel=tempChannel(end:-1:1,:); % 翻轉(zhuǎn)
tempChannel=tempChannel.*(1-whiteMat)+255.*whiteMat; % 白化
flipPic(:,:,i)=tempChannel;
end
% imshow(uint8(flipPic))
% 噪聲圖構(gòu)造(高斯噪聲及高斯模糊)===========================================
noiseMat=ones(Row,Col);
noiseMat=imnoise(noiseMat,'gaussian',0,5); % 噪聲添加
gaussOpt=fspecial('gaussian',[3 3],1);
noiseMat=imfilter(noiseMat,gaussOpt);
imshow(noiseMat)
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;
% imshow(uint8(noiseMat))
% 圖像透視變換 ============================================================
exNoiseMat=zeros(Row,Col);
% 橫向拉伸上下邊倍數(shù)
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);
% imshow(exNoiseMat)
% 扭曲置換 ================================================================
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,:)=c;
end
end
% imshow(newforePic)
% 圖像拼接 ================================================================
resultPic(:,:,1)=[oriPic(:,:,1);newforePic(:,:,1)];
resultPic(:,:,2)=[oriPic(:,:,2);newforePic(:,:,2)];
resultPic(:,:,3)=[oriPic(:,:,3);newforePic(:,:,3)];
% imshow(resultPic)
% 邊緣模糊 ================================================================
gaussOpt=fspecial('gaussian',[3 3],0.5);
gaussPic=imfilter(resultPic,gaussOpt);
resultPic(Row-1:Row+2,:,1)=gaussPic(Row-1:Row+2,:,1);
resultPic(Row-1:Row+2,:,2)=gaussPic(Row-1:Row+2,:,2);
resultPic(Row-1:Row+2,:,3)=gaussPic(Row-1:Row+2,:,3);
imshow(resultPic)
end



奇怪畫風(fēng)哈哈哈:



以上就是基于Matlab實(shí)現(xiàn)水波倒影特效的制作的詳細(xì)內(nèi)容,更多關(guān)于Matlab水波倒影的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
淺談C++日志系統(tǒng)log4cxx的使用小結(jié)詳解
本篇文章是對C++日志系統(tǒng)log4cxx的使用進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05
Dijkstra算法最短路徑的C++實(shí)現(xiàn)與輸出路徑
今天小編就為大家分享一篇關(guān)于Dijkstra算法最短路徑的C++實(shí)現(xiàn)與輸出路徑,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-02-02
C++調(diào)用EasyX庫實(shí)現(xiàn)嫦娥奔月小游戲
這篇文章主要為大家詳細(xì)介紹了C++如何調(diào)用EasyX庫編寫一個簡單的嫦娥奔月小游戲,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以參考一下2023-09-09
C++實(shí)現(xiàn)LeetCode(134.加油站問題)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(134.加油站問題),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
探討register關(guān)鍵字在c語言和c++中的差異
建議不要用register關(guān)鍵字定義全局變量,因?yàn)槿肿兞康纳芷谑菑膱?zhí)行程序開始,一直到程序結(jié)束才會終止,而register變量可能會存放在cpu的寄存器中,如果在程序的整個生命周期內(nèi)都占用著寄存器的話,這是個相當(dāng)不好的舉措2013-10-10

