基于Matlab實現(xiàn)水波倒影特效的制作
1.使用效果
2.圖像翻轉(zhuǎn)及白化
導入圖像:
% 圖片導入 oriPic=imread('test.jpg'); [Row,Col,~]=size(oriPic);
翻轉(zhuǎn)及白化圖像:
翻轉(zhuǎ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
當然如果我們將這一行:
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); % 翻轉(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.波紋圖像構造
生成噪聲并模糊:
noiseMat=ones(Row,Col); noiseMat=imnoise(noiseMat,'gaussian',0,5); % 噪聲添加 gaussOpt=fspecial('gaussian',[3 3],1); noiseMat=imfilter(noiseMat,gaussOpt);
噪聲圖:
模糊后噪聲圖:
浮雕特效:
實際上浮雕特效就是用以下類似形式的矩陣對圖像進行卷積,卷積結果再加上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;
透視變換:
就是近大遠小,這里為了方便起見只在橫向方向上做了近大遠小的拉伸,豎直方向進行了等比例拉伸,因而不是嚴格意義上的透視變換:
如圖所示實際操作就是把左側藍色區(qū)域拉伸成右側藍色區(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);
注: 如果原圖像尺寸過大,水波就會過于密集,這時候可以適當調(diào)整放縮倍數(shù)或者將原圖像重調(diào)大小到小一點的尺寸。
例如大波浪代碼:
% 圖像透視變換 ============================================================ 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 % 圖片導入 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)) % 噪聲圖構造(高斯噪聲及高斯模糊)=========================================== 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
奇怪畫風哈哈哈:
以上就是基于Matlab實現(xiàn)水波倒影特效的制作的詳細內(nèi)容,更多關于Matlab水波倒影的資料請關注腳本之家其它相關文章!
相關文章
Dijkstra算法最短路徑的C++實現(xiàn)與輸出路徑
今天小編就為大家分享一篇關于Dijkstra算法最短路徑的C++實現(xiàn)與輸出路徑,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-02-02C++調(diào)用EasyX庫實現(xiàn)嫦娥奔月小游戲
這篇文章主要為大家詳細介紹了C++如何調(diào)用EasyX庫編寫一個簡單的嫦娥奔月小游戲,文中的示例代碼講解詳細,感興趣的小伙伴可以參考一下2023-09-09C++實現(xiàn)LeetCode(134.加油站問題)
這篇文章主要介紹了C++實現(xiàn)LeetCode(134.加油站問題),本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下2021-07-07