MATLAB 手把手教你如何将视频水彩风格化(简易版)

Posted slandarer

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MATLAB 手把手教你如何将视频水彩风格化(简易版)相关的知识,希望对你有一定的参考价值。

前言

原本想做视频动漫风格化的,动漫风格化要求图片色块分明,所以用到的是保边缘性极强的双边滤波,但由于双边滤波需要每张图片多次滤波才能出效果,等待时机较长,MATLAB处理循环的能力并不太适合。

事实上本篇文章主要就是教大家如何用matlab简单处理视频,因此我们选择较快的水彩风格化(简易版),但即使是这样长达一分钟的视频处理也足足耗了15分钟

处理效果:
在这里插入图片描述

步骤

1.导入视频

使用VideoReader函数可以导入视频,用法如下(2012版以后的matlab支持VideoReader):

movObj=VideoReader(‘test.mp4’);

这样导入的便是一个结构体
我们可以使用

disp(movObj)

或者

get(movObj)

来查看结构体的属性:

VideoReader - 属性:

常规属性:
Name: ‘test.mp4’
Path: ‘E:\\bin\\matlabPS\\edgeMovie’
Duration: 87.7480
CurrentTime: 0.0800
NumFrames: <正在计算…> 了解更多

视频属性:
Width: 1920
Height: 1080
FrameRate: 25
BitsPerPixel: 24
VideoFormat: ‘RGB24’

其中比较重要的属性有:

  • Duration:视频时长(秒)
  • FrameRate:帧率
  • NumFrames:帧数
2.获取每一帧图片
for k=1:movObj.NumFrames
     frame=read(movObj,k);
end

read(movObj,k)就是提取视频对象第k帧,而视频一共有movObj.NumFrames帧,这些都非常好理解。

3.处理视频每一帧

水彩有一种晕开的感觉,所以我们选择不注重边缘的均值或高斯滤波,再将其与边缘结合
原图:
在这里插入图片描述
sobel卷积:
乘不乘以1.2其实差不多,当然也可以选择matlab自带的sobel边缘检测,不过那样的话边缘没有灰度的差异

ed_img=(255-sobelConv2_gray(rgb2gray(frame))).*1.2;

    function sobelPic=sobelConv2_gray(oriPic)
        Hx=[-1 0 1;-2 0 2;-1 0 1];
        Hy=[1 2 1;0 0 0;-1 -2 -1];

        [rows,cols]=size(oriPic);
        exPic=uint8(zeros([rows+2,cols+2]));
        exPic(2:rows+1,2:cols+1)=oriPic;
        
        exPic(2:rows+1,1)=oriPic(:,1);
        exPic(2:rows+1,cols+2)=oriPic(:,cols);
        exPic(1,2:cols+1)=oriPic(1,:);
        exPic(rows+2,2:cols+1)=oriPic(rows,:);
        
        exPic(1,1)=oriPic(1,1);
        exPic(rows+2,1)=oriPic(rows,1);
        exPic(1,cols+2)=oriPic(1,cols);
        exPic(rows+2,cols+2)=oriPic(rows,cols);
        
        Gx=zeros([rows,cols]);Gy=Gx;
        
        for ii=1:3
            for jj=1:3
                tempPic=double(exPic(ii:rows+ii-1,jj:cols+jj-1));
                Gx=Gx+tempPic.*Hx(ii,jj);
                Gy=Gy+tempPic.*Hy(ii,jj);
            end
        end
        sobelPic=uint8(sqrt(Gx.^2+Gy.^2));
    end

在这里插入图片描述
高斯滤波:

ga_img=imgaussfilt(frame,5);

在这里插入图片描述
图片合成:
点开看大图效果明显一点

newFrame=uint8(double(ga_img).*double(ed_img)./255);

在这里插入图片描述

4.制作新视频

制作新视频首先要用VideoWriter函数创建视频对象

newObj=VideoWriter(‘waterColorResult’);

视频名称为waterColorResult,这里视频格式默认为avi,如果想要mp4格式之类的其他格式,要设置profile属性,例如(mp4格式):

newObj=VideoWriter(‘waterColorResult’,‘MPEG-4’);

设置新视频帧率:
和原视频帧率相同

newObj.FrameRate=movObj.FrameRate;

打开视频对象,并将每一帧写入新视频对象

open(newObj)
for k=1:movObj.NumFrames
     frame=read(movObj,k);
     ga_img=imgaussfilt(frame,5);
     ed_img=(255-sobelConv2_gray(rgb2gray(frame))).*1.2;
     newFrame=uint8(double(ga_img).*double(ed_img)./255);
     %下面这一行就是帧的写入
	 writeVideo(newObj,newFrame); 
end
close(newObj)
5.进度展示

理论上靠前四部已经能够制作出视频了,但是一个视频处理时间不短,我们需要一个进度显示的功能,类似下面这样:

close all;
fig=figure(1);
fig.NumberTitle='off';

for k=1:movObj.NumFrames
     %一大堆操作
     %。。。。。。
     %。。。。。。
     imshow(newFrame)
     fig.Name=['Frame:[',num2str(k),'/',num2str(movObj.NumFrames),']'];
end

这样就能在左上角显示处理进度啦:
在这里插入图片描述

6.完整代码
function waterColorMov
movObj=VideoReader('test.mp4');

newObj=VideoWriter('waterColorResult','MPEG-4'); 
newObj.FrameRate=movObj.FrameRate;
open(newObj)

close all;
fig=figure(1);
fig.NumberTitle='off';

tic
for k=1:movObj.NumFrames
     frame=read(movObj,k);
     ga_img=imgaussfilt(frame,5);
     ed_img=(255-sobelConv2_gray(rgb2gray(frame))).*1.2;
     newFrame=uint8(double(ga_img).*double(ed_img)./255);
	 writeVideo(newObj,newFrame);
     imshow(newFrame)
     fig.Name=['Frame:[',num2str(k),'/',num2str(movObj.NumFrames),']'];
end
toc
close(newObj)

    function sobelPic=sobelConv2_gray(oriPic)
        Hx=[-1 0 1;-2 0 2;-1 0 1];
        Hy=[1 2 1;0 0 0;-1 -2 -1];

        [rows,cols]=size(oriPic);
        exPic=uint8(zeros([rows+2,cols+2]));
        exPic(2:rows+1,2:cols+1)=oriPic;
        
        exPic(2:rows+1,1)=oriPic(:,1);
        exPic(2:rows+1,cols+2)=oriPic(:,cols);
        exPic(1,2:cols+1)=oriPic(1,:);
        exPic(rows+2,2:cols+1)=oriPic(rows,:);
        
        exPic(1,1)=oriPic(1,1);
        exPic(rows+2,1)=oriPic(rows,1);
        exPic(1,cols+2)=oriPic(1,cols);
        exPic(rows+2,cols+2)=oriPic(rows,cols);
        
        Gx=zeros([rows,cols]);Gy=Gx;
        
        for ii=1:3
            for jj=1:3
                tempPic=double(exPic(ii:rows+ii-1,jj:cols+jj-1));
                Gx=Gx+tempPic.*Hx(ii,jj);
                Gy=Gy+tempPic.*Hy(ii,jj);
            end
        end
        sobelPic=uint8(sqrt(Gx.^2+Gy.^2));
    end
end

当然如果不怕处理时间久的话可以尝试别的类型的风格化,and matlab 循环着实有点慢,其实可以考虑一下C++的。。。

原始视频:
链接:https://pan.baidu.com/s/1OMwX1MuDPr_558EBJZ3-FQ
提取码:jkt1

以上是关于MATLAB 手把手教你如何将视频水彩风格化(简易版)的主要内容,如果未能解决你的问题,请参考以下文章

手把手教你用OpenCV和Python实现图像和视频神经风格迁移(代码)

手把手教你如何使用Unity搭建简易图片服务器

手把手教你写一个简易的微前端框架

手把手教你使用 Java AWT 创建一个简易计算器

手把手教你制作简易的计算器

10分钟手把手教你用Android手撸一个简易的个人记账App