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 表情

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