GUI 弹幕壁纸
- 1.个人需求描述
-
- 1.1 需求
- 1.2 分析
-
- 1.2.1 问题一
- 1.2.2 问题二
- 1.2.3 问题三
- 1.3 搜索关键词
- 2.关键函数
-
- 2.1 create_bg
- 2.2 create_text
- 2.3 image_fusion
- 3.GUI介绍
- 4.过程展示
- 5.总结
- 6.相关链接
1.个人需求描述
1.1 需求
- 我觉得自己今日不够努力,超过4个小时不写代码就会感到空虚,觉得人生没有意义
- 我需要激励自己,从桌面开始,从壁纸开始,眼睛是灵魂的窗户,所见即是所感
- 我需要那种纯色的有文字的壁纸,我个人更加的倾向于简约风格,不要花里胡哨
1.2 分析
- 如何创建一个纯色的背景?
- 如何添加文字?
- 如何做出弹幕的效果?
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:3wall_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:hif a(i,c,1)==255height=i;end
end
%# 获取裁剪宽度上限
for i=c:wif a(r,i,1)==255width=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+1for j=1:width-c+1if pic_alpha(i,j)==1pic_alpha(i,j)=0;elseif pic_alpha(i,j)==0pic_alpha(i,j)=1;else pic_alpha(i,j)=1-pic_alpha(i,j);endend
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;%# 给一个不能访问的索引,进行标记endl_t(i)=1;%# 弹幕位置更新为[1 1]end
endif 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);elser_b(i)=b_size(i);endend%# 颜色融合部分%# 从左上到右下for i=l_t(1):r_b(1)-1for j=l_t(2):r_b(2)-1for k=1:3%# 以下是含有融合是含有透明度的计算公式其实很简单%# C = B*(1-alpha*opicity)+F*alpha*opicitypic_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)>1pic_b(i,j,k)=1;endendendend
end
end
不知道自己下一次看的时候还能不能看懂?,这个表情真有意思?
3.GUI介绍
初始化界面:
设置背景,提取遮罩后图片:
分区介绍:
- 背景图片展示,同时图片处理的过程也会在这里展示。
- 文字图片遮罩,运行过程中会一直变化。
- 颜色调整,滑动条、数字、颜色三者的变化一致。
- 字体大小与透明度的调整,字体需要整数,透明度需要小数。
- 字体的选择,需要选择能显示中文的字体,字体需要设定,不随机。
- 弹幕,可以自行添加多条,会随机选择。
- 背景图片大小,在1位置展示的图片大小。
如果加载图片,这里展示加载图片的大小;
如果生成背景图,则根据给定的尺寸生成; - 根据3位置的颜色,生成背景图。
- 设定弹幕数量,开始加载弹幕的时候,这里的颜色、数值会渐变直到完成。
- 添加弹幕。
- 设置了,但是没有写相关的代码,不可用。
- 加载一张本地图片,可能需要选择一下文件类型。
- 测试文字遮罩是否可以生成,生成之后在2位置展示。
- 将融合后额图片保存在本地。
4.过程展示
自动生成背景:
备注:不知道为什么运行速度这么慢!我jio的是电脑性能的问题!
从本地选择图片:
备注:图片小的时候运行速度还是很快的~
5.总结
关于这件事情是否有意义?
我满足的是自己的需求,这些代码可能别人不会用,我个人也只会用一次,这点看来似乎没有太大必要!消耗时间上用了三天,如果PS的话,早就结束了,如果用js的话可能一个小时就结束了,但:为什么用了matlab?
因为自己现在正在使用matlab,而且需要用到GUI部分的知识,完成这个功能会对以后,对于毕设有所帮助,能够促进我对于matlab的学习,毕竟我有了成果。今后说不定什么时候就用到了,即使需求不一样,但可能hi用到这里面的函数,比如图像融合部分的函数,比如获取遮罩部分的函数~
关于MATLAB GUI
matlab GUI的使用是比较方便的,相较于其他语言,能快速做出一个界面,而且能够导出exe文件,方便在其他电脑上运行,但是如果对方没有matlab就需要装一下环境,大概1G,此后便无需太多顾虑,同版本的matlab程序都可以直接拿来使用,还是很方便的!
程序员是否一定要写有意义的代码?写的代码一定有意义?
可能在一段时间内做了没有意义的事情,写了没有意义的代码,比如之前爬虫,要爬什么网站的?,大概初学者的方向都是一样的吧?!!!我当时甚至还做了界面,写了上千行代码,但是现在依旧不使用。
现在看来当时的做的事情是没意义的,当时而言却是有意义的,毕竟自己满足了吧,学到东西了吧,但当时还遇到一个问题,python中几行代码能解决的问题,我玩了好几个月不觉得厌烦???!!!细思极恐?,再者,今后遇到同样的问题,我会不会感觉有些便利?会不会拿出来自己写过的代码?显然,这是很有可能的,写过的代码既然已经留档,若是遇到相同问题,指定会用到。
长远来看,短时间的无意义的事情,都在逐渐累积成有意义的事情,并对未来的自己有所帮助。
6.相关链接
Link:MATLAB 弹幕壁纸源码
Link:Markdown 表情