Matlab图像边缘检测制作视频

用Matlab来进行图像边缘检测,输出边缘线条视频,过程全记录,内含全部源码。

效果

放在了我的b站上:我用Matlab摆烂了你的AE作业_哔哩哔哩_bilibili

下面可以直接观看:

源视频在这里: AE原作:大二AE结课作业 《过 年》(已摆烂)_哔哩哔哩_bilibili

b站上其他版本:《友 商 链 接》:
我用Matlab摆烂了你的AE作业_哔哩哔哩_bilibili (他是红色的
我用Matlab摆烂了你的ae作业_哔哩哔哩_bilibili (黑色,点更细致了
我用Matlab摆烂了你的ae作业_哔哩哔哩_bilibili (这个跟第一个差不多,甚至个人感觉比第一个要清晰,但是没有第一个火,第一个比这个早发布六小时,那这样说我岂不是更加凉凉了。。。


如何制作

吃瓜的到这里可以走了(若想当个故事看也不是不行),有matlab的同学想玩一玩可以往下看,源码全分享。(这里不讲怎么下载matlab,为此专门下载30G大小的matlab不划算。)

1 工作目录

创建edgespics两个空文件夹,pics是视频逐帧输出后的图片存放的路径,edgespics文件夹中图片经边缘处理后生成图片的存放路径。

out2pic.mzed.mpic2video.m三个matlab脚本文件

放入source.mp4原视频

output.mp4是处理后生成的视频

2 源码

源码是我从网上搜来的,改了一点,但是那是好几十天前的事情了,原网站我已经找不到了,侵删。其实我把代码放网上搜了一下确实搜到一个,但那个和我最初参考的不一样,他也没放源码链接,我也不知道哪个是原创,反正代码我不是原创。但是本文章的内容确实是原创。天下代码一大抄

代码中 “你的工作路径” 要替换为自己的,就是上图中的文件存放在哪里了。例如我的是

D:\0programing\matlab_work\ImageEdgeDetection

zed.mpic2video.m代码中的for循环用到了帧数,要根据具体视频来改变,运行完out2pic.m后,pics文件夹中有几张图片就是几帧。

2.1 out2pic.m:将视频分割逐帧分割为图片

1
2
3
4
5
6
7
8
9
10
11
12
clear;
clc;
se = strel('line',11,90);
path='你的工作路径\source.mp4'; %视频存放路径
obj=VideoReader(path);
num=obj.NumberOfFrames;
for i=1:num %帧数,这里的i最终为1801
frame=read(obj,i);
lujing=strcat('你的工作路径\pics\',num2str(i)); %帧图输出路径
lujing=strcat(lujing,'.jpg');
imwrite(frame,lujing)
end

2.2 zed.m:逐个图片运用边缘检测算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
close all;
clc;
for i=1:1801 %前面所得的视频帧数
path='你的工作路径\pics\'; %帧图路径
disp(i);
path=strcat(path,num2str(i));
p=strcat(path,'.jpg');
f=imread(p);
f=rgb2gray(f);
roberts=edge(f,'roberts'); %roberts算子
[m,n]=find(roberts==1);
%scatter(n,-m,'.'); % 1 去掉注释直接展示
mh=scatter(n,-m,'.'); % 2 确定输出
axis([0 1280 -720 0]); %可依据窗口大小自行调整坐标系,这里输出图片是1280x720
lujing=strcat('你的工作路径\edges\',num2str(i)); % 3 输出存放路径
lujing=strcat(lujing,'.jpg'); % 4 输出格式为ipg
saveas(mh,lujing); % 5 保存
%这里默认是将边缘检测的每一张图片保存,方便后续合成视频;也可以不用保存直接展示,只需将注释编号为1的语句取消注释,将2、3、4、5加上注释即可。但直接展示的话效果不太好,比较卡。
pause(0.05);
end

9:28开始运行边缘检测算法,10:15运行结束,1801张图片跑了四五十分钟,最后可以生成一分多钟的视频。

2.3 pic2video.m:将生成的边缘检测图片合成视频

1
2
3
4
5
6
7
8
9
10
11
12
13
14
clear;
clc;
WriterObj=VideoWriter('output.mp4', 'MPEG-4'); %这里输出的路径是默认路径,合成的视频的格式是mp4
WriterObj.FrameRate = 25; %控制输出视频帧率,原视频为25,没有这行的话默认30
open(WriterObj);
for i=1:1801 %帧图数量
pic='你的工作路径\edges\'; %前面边缘检测的图片的存储路径
pic=strcat(pic,num2str(i));
ppic=strcat(pic,'.jpg');
frame=imread(ppic); % 读取图像,放在变量frame中
disp(ppic);
writeVideo(WriterObj,frame); % 将frame放到变量WriterObj中
end
close(WriterObj);

至此,视频合成好了,但是没有声音,用剪辑软件添加声音。

3 遇到的问题

3.1 运行zed.m时弹出的figure窗口不要关闭!!!

别问我怎么知道的,说多了都是泪……

这个是figure窗口:

这个是可能报的错:

千万别关!!!!

3.2 合成视频时图片分辨率不符报错

查一下472.jpg和473.jpg的分辨率属性

我也不知道什么原因,原图都是1280x720,可能上面我图中关闭了一下figure导致的?但是我关闭窗口的时候应该没合成到472吧。472及以前的分辨率是875x656,473及以后的分辨率是875x657。给writeVideo整不会了,罢工了。

再跑一遍zed.m是不可能的,累死。机智如我,把前472张合成一下output1.mp4,473后面的合成一个output2.mp4,通过控制pic2video.m中for循环i的取值来实现,记得合成后改名,不然合成第二个会覆盖第一个。之后用剪辑软件拼接起来,就算前后两个视频分辨率不同,剪辑软件可不会像writeVideo那样罢工。

3.3 合成视频后与原视频帧数不符

合成视频发现它短了,查属性,发现原视频是25帧的,我输出的是30帧的。

网上查了一下怎么改VideoWriter输出的帧数,代码里加了一行。

再次输出视频,帧数还为30,离谱。。。幸好我慧眼如炬,发现我从网上抄的代码和原来的代码大小写不一样,如下:(我不说你们也发现不了W和w不一样吧

1
2
WriterObj=VideoWriter('output.mp4', 'MPEG-4');
writerObj.FrameRate = 25;

改了以后代码运行正常(上面给的源码已经是修改过的了,放心食用。

4 待改进

在只有matlab进程的条件下:

CPU利用率:

GPU利用率:

我也不知道怎么能把CPU占满一点,也不知道怎么调用GPU来处理,产出个一分钟的视频要操作将近一个小时,辛苦我的CPU了。

这是本站第一篇实质性内容的文章,实操的小伙伴遇到什么问题可以在评论区留言。