04-0006 MATLAB 弹幕壁纸

1.个人需求描述

1.1 需求

  • 我觉得自己今日不够努力,超过4个小时不写代码就会感到空虚,觉得人生没有意义
  • 我需要激励自己,从桌面开始,从壁纸开始,眼睛是灵魂的窗户,所见即是所感
  • 我需要那种纯色的有文字的壁纸,我个人更加的倾向于简约风格,不要花里胡哨

1.2 分析

  1. 如何创建一个纯色的背景?
  2. 如何添加文字?
  3. 如何做出弹幕的效果?

1.2.1 问题一

如何创建一个纯色的背景?

  • 设置RGB值,在matlab中从RGB三维分别写入,保存成图片即可。
  • 需要自己设置尺寸设置颜色生成文件

1.2.2 问题二

如何添加文字?

  • 需要将文字转化为图片,转化后的图片需要保存
  • 为了融合时的方便需要提取文字部分的遮罩以及遮罩的尺寸

1.2.3 问题三

如何做出弹幕的效果?

  • 弹幕一般都是随机位置的,添加弹幕应该随机位置
  • 这是一张静态的壁纸,不需要滚动效果
  • 大小嗯?颜色呢?都需要进行随机,随机大小随机颜色
  • 将文字图片与背景进行图像融合,最好是有半透明效果

总结:目前会遇到的问题就这几个,可能在实现的过程中还会有其他的困难。
这应该也算是需求分析吧,虽然没有完整的文档,但是我很清楚自己需要做什么,知道自己应该做哪些事,大致的解决思路都是有的。
后续的函数也是根据上面的三个想法来的,只是顺序不太一样。

1.3 搜索关键词

  • 如何给壁纸添加弹幕效果
  • 文字壁纸生成
  • 在线生成文字壁纸
  • 在线制作文字壁纸

相关链接:

大部分的结果都是使用python或者js,使用matlab的很少,原因显而易见:
1.我在用matlab,在提高的同时满足自己
2.js很方便,添加文字很快,最多是图片保存成个问题
最后的结果也确实如此,matlab好慢啊,批量处理什么的是不可能的,想要在别人电脑上运行还得安装编译环境,JS写的html界面是个电脑都能运行,自然是很快的啊~
如果需求不是很多的话,用PS也可以,甚至可能用的时间更短!

2.关键函数

2.1 create_bg

我总有一种注释足够清楚不需要写其他文字说明的所觉?是我懒?还是它太简单?

生成背景图片主要是RGB三通道赋值于图片保存的问题,使用matlab已有的函数可以解决,如果中途不想展示给用户看,可以见figure设置成不可见,尺寸也许是有用的所以返回了一下。

%# [背景尺寸]=[高 宽 R G B]
function [b_size] = create_bg(height,width,R,G,B)
%# 生成底图
wall_paper=zeros(height,width,3);
temp_rgb=[R G B];
for i=1:3
    wall_paper(:,:,i)=temp_rgb(i);
end
figure('Visible','off'),imshow(im2double(wall_paper));
%# 写入之后再imshow出来是有颜色的,否则就是没有颜色的,可能与imshow函数有关,它可能会记录数据的格式吧
%# 上述猜测可能是错的
imwrite(uint8(wall_paper),'temp_bg.png');
b_size=[height width]; %# 尺寸写入
end

2.2 create_text

  • f_alpha:是文字图片经处理之后的遮罩
  • f_size:是遮罩的尺寸
  • 最终的融合,是用这个遮罩对于RGB背景的每一层进行的融合。

可能上上面一段话让人很懵,需要下面的解释:

  • 在matlab中文字转化为图片的直接途径是不存在的,insertText函数也只能完成将文字插入图片之后得到新图片的功能,新的图片会存储在figure中,需要使用imshow函数将图片在figur中展示之后,才能获取到新的图片。
  • 使用insertText函数的时,会发现其中的一个属性为BoxOpicity:盒子透明度,文字会在这个盒子内居中显示。
  • 所以我便让这个盒子完全不透明[下图中的黄色部分],保存为图片之后只获取这一部分的内容。

文字插入的展示:
在这里插入图片描述
获取遮罩:
在这里插入图片描述
关于获取遮罩:

  • 开始的时候直接从像素[1 1]开始横向纵向进行查找,一直到不是黄色的位置结束,一般情况下这种都是能够正常运行的。
  • 当文字特别小的时候,boder属性会失效,figure有一个最小尺寸的限制,此时的黄色就不会紧贴左上角。如下:
    在这里插入图片描述
  • 此时,应当找到左上角第一个黄色像素点的位置,再计算尺寸,使用find函数。

具体代码如下:

%# [字体图片遮罩 字体图片尺寸]=[字符串 字体名称 字体大小]
function [f_alpha f_size ]=create_text(str,fontname,fontsize)
%# 文字处理部分
a=strlength(str);   %#字符个数
height=fontsize*2;%#高度,这里采用的是统计方法,对于大部分的,直接乘2就好
width=floor(fontsize*a*1.3);%# 宽度,记得取整

h=figure('Visible','off');  %# 开启一个figure,不让其显示,主要是为了获得句柄
%# 展示一个插入了图片的图像
%# 如果尺寸太小,后面的tigh是无效的,figure有一个最小尺寸
imshow(insertText(zeros(height,width),[0,0],str,'Font',fontname,'BoxOpacity',1,'FontSize',fontsize,'TextColor','black'),'border','tight');
f_pic=getframe(h);  %#获取窗体内容
imwrite(f_pic.cdata,'temp_font.png');%# 写入文件
a=imread('temp_font.png');%# 重新读取

%# 获取字体图片的尺寸
[h w t]=size(a);
%# 黄色R通道的值是255,找到第一个255,返回下标
[r c]=find(a(:,:,1)==255,1,'first');
%# 获取裁剪高度上限
for i=r:h
    if a(i,c,1)==255
        height=i;
    end
end
%# 获取裁剪宽度上限
for i=c:w
    if a(r,i,1)==255
        width=i;
    end
end
%# 重新写入图片,仅仅将字体的box部分写入
pic_new=a(r:height,c:width,:);
pic_new_R=pic_new(:,:,1);

%# 获取遮罩,逐个像素进行处理
%# 利用的是含透明度的图像融合公式
pic_alpha=im2double(pic_new_R); %# 双精度
for i=1:height-r+1
    for j=1:width-c+1
        if pic_alpha(i,j)==1
            pic_alpha(i,j)=0;
        elseif pic_alpha(i,j)==0
            pic_alpha(i,j)=1;
        else 
            pic_alpha(i,j)=1-pic_alpha(i,j);
        end
    end
end
%# 对于字体遮罩及其尺寸进行赋值
f_size=[height-r+1 width-c+1];
f_alpha=pic_alpha;
end

imshow函数boder属性是否为tight的对比:
在这里插入图片描述

2.3 image_fusion

两个图片之间的关系有以下几种:

  • case1-case10,文字图片,黑色的位置是需要裁减掉的
  • Background,背景图片,在背景图片范围的需要进行融合
  • 黄线以上的case1-6属于座标有负值的情况
  • 黄线以下的case7-10属于座标全正的情况
  • 完整在中间的case忘了画,emm

在这里插入图片描述
配合图&注释,理解下面的代码:

%#[新生成图片] = [背景图,背景图片尺寸,字体遮罩,字体尺寸,弹幕位置,字体颜色,字体透明度]
function [pic_b]=image_fusion(pic_b,b_size,pic_alpha,f_size,l_t,font_color,opicity)
%# 获取融合四角下标,在索引都是正的的情况下
%# 如果座标不是正的,需要重新规定l_t,pic_alpha,f_size
%# 这个是全村的重点
%# l_t:弹幕位置,指的是开始绘制弹幕的位置,原则上来说应该从[1 1]开始

temp_f_size=f_size;%# 由于f_size是需要重写的,设置临时变量记录f_size的值
temp_l_t=l_t;%# 同上

for i=1:2 %# 对于l_t两个变量遍历
    if l_t(i)<0 %# 如果该值小于零,需要调整字体图片的尺寸,把在背景之外的剔除掉
        f_size(i)=f_size(i)+l_t(i);%# 正值+负值=新尺寸
        if f_size(i)<0%# 如果此时还<0,那就说明图片完全在背景之外,是不需要绘制的
            f_size(i)=0;%# 给一个不能访问的索引,进行标记
        end
        l_t(i)=1;%# 弹幕位置更新为[1 1]
    end
end

if f_size(1)~=0 &  f_size(2)~=0 %# 当不在图像之外的时候
    if temp_l_t(1)<0 | temp_l_t(2)<0 %# 如果开始设置的弹幕位置有负值,更新需要绘制的pic_alpha
        %# 取出尚且还在背景里面的那一部分,作为新的遮罩
        pic_alpha=pic_alpha(temp_f_size(1)-f_size(1):temp_f_size(1),temp_f_size(2)-f_size(2):temp_f_size(2),:);
    end
    
    %# 正常的计算流程
    r_b=[0 0]; %# 弹幕右下角的位置
    for i=1:2 %# 对l_t两个值进行遍历,对右下部分进行剪切,超出的部分不要
        if l_t(i)+f_size(i)<b_size(i)
        r_b(i)=l_t(i)+f_size(i);
        else
            r_b(i)=b_size(i);
        end
    end
    
    %# 颜色融合部分
    %# 从左上到右下
    for i=l_t(1):r_b(1)-1
        for j=l_t(2):r_b(2)-1
            for k=1:3
                %# 以下是含有融合是含有透明度的计算公式其实很简单
                %# C = B*(1-alpha*opicity)+F*alpha*opicity
                pic_b(i,j,k)=pic_b(i,j,k)*(1-pic_alpha(i-l_t(1)+1,j-l_t(2)+1)*opicity)+font_color(k)/255*pic_alpha(i-l_t(1)+1,j-l_t(2)+1)*opicity;
                if pic_b(i,j,k)>1
                    pic_b(i,j,k)=1;
                end
            end
        end
    end
end
end

不知道自己下一次看的时候还能不能看懂😂,这个表情真有意思😲

3.GUI介绍

初始化界面:
在这里插入图片描述
设置背景,提取遮罩后图片:
在这里插入图片描述
分区介绍:
在这里插入图片描述

  1. 背景图片展示,同时图片处理的过程也会在这里展示。
  2. 文字图片遮罩,运行过程中会一直变化。
  3. 颜色调整,滑动条、数字、颜色三者的变化一致。
  4. 字体大小与透明度的调整,字体需要整数,透明度需要小数。
  5. 字体的选择,需要选择能显示中文的字体,字体需要设定,不随机。
  6. 弹幕,可以自行添加多条,会随机选择。
  7. 背景图片大小,在1位置展示的图片大小。
    如果加载图片,这里展示加载图片的大小;
    如果生成背景图,则根据给定的尺寸生成;
  8. 根据3位置的颜色,生成背景图。
  9. 设定弹幕数量,开始加载弹幕的时候,这里的颜色、数值会渐变直到完成。
  10. 添加弹幕。
  11. 设置了,但是没有写相关的代码,不可用。
  12. 加载一张本地图片,可能需要选择一下文件类型。
  13. 测试文字遮罩是否可以生成,生成之后在2位置展示。
  14. 将融合后额图片保存在本地。

4.过程展示

自动生成背景
在这里插入图片描述
备注:不知道为什么运行速度这么慢!我jio的是电脑性能的问题!

从本地选择图片
在这里插入图片描述
备注:图片小的时候运行速度还是很快的~

5.总结

关于这件事情是否有意义?

我满足的是自己的需求,这些代码可能别人不会用,我个人也只会用一次,这点看来似乎没有太大必要!消耗时间上用了三天,如果PS的话,早就结束了,如果用js的话可能一个小时就结束了,但:为什么用了matlab?

因为自己现在正在使用matlab,而且需要用到GUI部分的知识,完成这个功能会对以后,对于毕设有所帮助,能够促进我对于matlab的学习,毕竟我有了成果。今后说不定什么时候就用到了,即使需求不一样,但可能hi用到这里面的函数,比如图像融合部分的函数,比如获取遮罩部分的函数~


关于MATLAB GUI
matlab GUI的使用是比较方便的,相较于其他语言,能快速做出一个界面,而且能够导出exe文件,方便在其他电脑上运行,但是如果对方没有matlab就需要装一下环境,大概1G,此后便无需太多顾虑,同版本的matlab程序都可以直接拿来使用,还是很方便的!


程序员是否一定要写有意义的代码?写的代码一定有意义?
可能在一段时间内做了没有意义的事情,写了没有意义的代码,比如之前爬虫,要爬什么网站的🤔,大概初学者的方向都是一样的吧?!!!我当时甚至还做了界面,写了上千行代码,但是现在依旧不使用。

现在看来当时的做的事情是没意义的,当时而言却是有意义的,毕竟自己满足了吧,学到东西了吧,但当时还遇到一个问题,python中几行代码能解决的问题,我玩了好几个月不觉得厌烦???!!!细思极恐😰,再者,今后遇到同样的问题,我会不会感觉有些便利?会不会拿出来自己写过的代码?显然,这是很有可能的,写过的代码既然已经留档,若是遇到相同问题,指定会用到。

长远来看,短时间的无意义的事情,都在逐渐累积成有意义的事情,并对未来的自己有所帮助。

6.相关链接

Link:MATLAB 弹幕壁纸源码
Link:Markdown 表情

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章