基于Matlab实现水波倒影特效的制作

 更新时间:2022年03月29日 10:20:16   作者:slandarer  
这篇文章主要介绍了如何利用Matlab制作出水波倒影的特效,文中的示例代码讲解详细,对我们学习Matlab有一定帮助,需要的可以参考一下

1.使用效果

2.图像翻转及白化

导入图像:

% 图片导入 
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))

3.波纹图像构造

生成噪声并模糊: 

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:

数值和位置不重要,重要的是相对位置互为相反数,浮雕过程描述如下:

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);

小波浪及大波浪:

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);

% 图片翻转及白化 ==========================================================
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
% 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);
% 横向拉伸上下边倍数
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实现水波倒影特效的制作的详细内容,更多关于Matlab水波倒影的资料请关注脚本之家其它相关文章!

相关文章

  • C语言数据结构通关时间复杂度和空间复杂度

    C语言数据结构通关时间复杂度和空间复杂度

    对于一个算法,其时间复杂度和空间复杂度往往是相互影响的,当追求一个较好的时间复杂度时,可能会使空间复杂度的性能变差,即可能导致占用较多的存储空间,这篇文章主要给大家介绍了关于C语言时间复杂度、空间复杂度的相关资料,需要的朋友可以参考下
    2022-04-04
  • C++中可正确获取UTF-8字符长度的函数分享

    C++中可正确获取UTF-8字符长度的函数分享

    这篇文章主要介绍了C++中可正确获取UTF-8字符长度的函数分享,需要的朋友可以参考下
    2014-08-08
  • 怎么锁定鼠标的示例代码分享

    怎么锁定鼠标的示例代码分享

    使用代码怎么才能锁定鼠标?这个功能很简单只要一个ClipCursor()就可以搞定,需要的朋友可以参考下
    2014-01-01
  • QT计算时间差的方法详解

    QT计算时间差的方法详解

    这篇文章主要为大家详细介绍了利用QT实现计算两个时间的时间差的方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • C语言数据结构二叉树之堆的实现和堆排序详解

    C语言数据结构二叉树之堆的实现和堆排序详解

    堆是计算机科学中一类特殊的数据结构的统称,通常是一个可以被看做一棵完全二叉树的数组对象。而堆排序是利用堆这种数据结构所设计的一种排序算法。本文将详细介绍堆的实现和堆排序,需要的可以参考一下
    2022-04-04
  • Linux C 获取进程退出值的实现代码

    Linux C 获取进程退出值的实现代码

    本篇文章是对在Linux下使用c语言获取进程退出值的方法进行了详细的分析介绍,需要的朋友参考下
    2013-05-05
  • c++11 实现枚举值到枚举名的转换问题

    c++11 实现枚举值到枚举名的转换问题

    这篇文章主要介绍了c++11 实现枚举值到枚举名的转换,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-03-03
  • C语言回调函数的简单运用

    C语言回调函数的简单运用

    回调函数就是函数指针变量作为另外一个函数的参数而使用的一种应用情形。本文就详细的介绍一下C语言回调函数的简单运用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • Qt+QWidget实现简约美观的加载动画

    Qt+QWidget实现简约美观的加载动画

    这篇文章主要为大家详细介绍了Qt如何结合QWidget实现简约美观的加载动画,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-02-02
  • C语言利用system调用系统命令行详情

    C语言利用system调用系统命令行详情

    这篇文章主要介绍了C语言利用system调用系统命令行详情,system就是调用系统命令行,输入为字符串,然后把这个字符串输出给命令行,让命令行执行。下文的具体内容,需要的小伙伴可以参考一下
    2022-01-01

最新评论