Tensorflow-Mandelbrot-曼德勃羅集

本篇文章使用Tensorflow做數(shù)學(xué)運(yùn)算的一個(gè)范例嗤练,并不涉及機(jī)器學(xué)習(xí)俭驮,但可以產(chǎn)生很炫的效果苛让。

曼德勃羅集是人類有史以來(lái)做出的最奇異最瑰麗的幾何圖形.曾被稱為“上帝的指紋”火惊。 這個(gè)點(diǎn)集均出自公式:Zn+1=(Zn)^2 +C液斜,對(duì)于非線性迭代公式Zn+1= (Zn)^2+C累贤,所有使得無(wú)限迭代后的結(jié)果能保持有限數(shù)值的復(fù)數(shù)C的集合,構(gòu)成曼德勃羅集少漆,這篇文章將使用python和tensorflow來(lái)形成最簡(jiǎn)單的曼德勃羅集圖案.



準(zhǔn)備工作

安裝pillow圖像庫(kù)臼膏,windows下管理員運(yùn)行命令行工具,mac下終端命令開頭加sudo示损。

sudo pip3  --trusted-host http://mirrors.aliyun.com/pypi/simple/ install pillow

這里使用了阿里云aliyun的鏡像站點(diǎn)渗磅,也可以更換其他鏡像,參照這里


Pillow顯示圖像

首先介紹一下tensorflow+pillow的繪圖流程检访。

首先我們編寫繪圖函數(shù)DisplayNxN:

import tensorflow as tf
import numpy as np
from PIL import Image #用來(lái)顯示圖片的模塊

def DisplayNxN(atable, fmt='jpeg'):
    #a形狀[x,x]轉(zhuǎn)變到[x,x,1]
    acube = atable.reshape(list(atable.shape)+[1])
    #把[x,x,1]變?yōu)閇x,x,3],只是把一個(gè)元素復(fù)制3份表示每像素
    acube3 = np.concatenate([acube,acube,acube], 2) 
    acube3 = np.uint8(np.clip(acube3, 0, 255)) #裁剪到255
    img=Image.fromarray(acube3)
    img.show()

DisplayNxN主要接收一個(gè)形狀為[n,n]的數(shù)組atable始鱼,例如下面4x4的矩陣(數(shù)據(jù)表)格式:

#atable格式
[[  0.     0.     0.     0.  ]
 [ 63.75  63.75  63.75  63.75]
 [127.5  127.5  127.5  127.5 ]
 [191.25 191.25 191.25 191.25]]

然后acube = atable.reshape(list(atable.shape)+[1])把a(bǔ)table變?yōu)?x4x1的三維的數(shù)字立方形式ar:

#acube格式
[[[  0.  ]
  [  0.  ]
  [  0.  ]
  [  0.  ]]

 [[ 63.75]
  [ 63.75]
  [ 63.75]
  [ 63.75]]

 [[127.5 ]
  [127.5 ]
  [127.5 ]
  [127.5 ]]

 [[191.25]
  [191.25]
  [191.25]
  [191.25]]]

在上面數(shù)組中,每個(gè)最底層元素如[63.75]就代表了一個(gè)像素的顏色脆贵,但我們知道應(yīng)該是[R,G,B]三個(gè)數(shù)字才對(duì)医清,下一步acube3 = np.concatenate([acube,acube,acube], 2)把每個(gè)數(shù)字重復(fù)3遍,就得到了下面的4x4x3的格式

[[[  0.     0.     0.  ]
  [  0.     0.     0.  ]
  [  0.     0.     0.  ]
  [  0.     0.     0.  ]]

 [[ 63.75  63.75  63.75]
  [ 63.75  63.75  63.75]
  [ 63.75  63.75  63.75]
  [ 63.75  63.75  63.75]]

 [[127.5  127.5  127.5 ]
  [127.5  127.5  127.5 ]
  [127.5  127.5  127.5 ]
  [127.5  127.5  127.5 ]]

 [[191.25 191.25 191.25]
  [191.25 191.25 191.25]
  [191.25 191.25 191.25]
  [191.25 191.25 191.25]]]

上面這個(gè)數(shù)據(jù)將生成一個(gè)超小的4像素x4像素的圖像卖氨,第一行是4個(gè)[ 0. 0. 0. ]黑色像素会烙,第二行63.75稍微亮一些,第三行像素更亮双泪,第四行也更亮持搜,所以這是一個(gè)從上到下逐步變亮的黑白圖片,下圖是放大到100x100x3的結(jié)果(先不要著急生成它焙矛,先理解):



Tensorflow數(shù)據(jù)處理

在寫代碼之前葫盼,我們先看一下numpy的np.magrid([start:end:step, start:end:step])這個(gè)函數(shù)。

import numpy as np
Y, X = np.mgrid[0:1:0.25, 0:1:0.25]
print('y',Y)
print('x',X)

它的輸出如下村斟,兩個(gè)4x4的數(shù)組贫导,數(shù)值從0到1,間隔0.25蟆盹。注意孩灯,Y是豎向每行遞增,X是橫向每列遞增的逾滥。

y [[0.   0.   0.   0.  ]
 [0.25 0.25 0.25 0.25]
 [0.5  0.5  0.5  0.5 ]
 [0.75 0.75 0.75 0.75]]
x [[0.   0.25 0.5  0.75]
 [0.   0.25 0.5  0.75]
 [0.   0.25 0.5  0.75]
 [0.   0.25 0.5  0.75]]

這就是最原始的要傳遞給DisplayNxN(atable, fmt='jpeg')函數(shù)的atable數(shù)據(jù)峰档。

下面我們?cè)贒isplayNxN函數(shù)后添加更多代碼(以下代碼處于DisplayNxN函數(shù)外面):

#mgrid[start:end:step, start:end:step] 
#從start到end每份step均分成n份,得到兩個(gè)[n,n]形狀
Y, X = np.mgrid[0:1:0.01, 0:1:0.01]
Yc = tf.constant(Y) #創(chuàng)建常數(shù)張量
clrs = tf.Variable(Yc) #創(chuàng)建張量變量
nextclrs = clrs*16 #對(duì)張量里每個(gè)元素進(jìn)行運(yùn)算,被group包裹讥巡,被step.run循環(huán)執(zhí)行

sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
step = tf.group(
    clrs.assign(nextclrs),
  )
for i in range(2): step.run()
        
DisplayNxN(clrs.eval())

保存并運(yùn)行這個(gè)文件掀亩,可以看到彈出上面顯示100x100像素的黑白漸變圖片。

注意欢顷,MacOS下不要添加sudo命令槽棍,可能會(huì)報(bào)錯(cuò)無(wú)法顯示圖片。

我們留意上面的代碼抬驴,先是Y, X = np.mgrid[0:1:0.01, 0:1:0.01]這句話100x100的數(shù)組炼七,元素的值從0到1分布成100級(jí)。
主要運(yùn)算就是nextclrs = clrs*16布持,把數(shù)組每個(gè)元素乘以16豌拙,執(zhí)行了2次,這樣相當(dāng)于把01范圍的數(shù)值放縮到了0256范圍鳖链,所以能夠最終被顯示為正常的黑白漸變姆蘸。


更多實(shí)驗(yàn)

上面我們提到過(guò)Y, X = np.mgrid[0:1:0.01, 0:1:0.01]得到X和Y兩個(gè)數(shù)組,X是橫向遞增芙委,Y是豎向遞增逞敷。那么如果我們把Yc = tf.constant(Y)中小括號(hào)內(nèi)的Y換成X,那么就能得到橫向的漸變圖灌侣。

Yc = tf.constant(X) 

如果我們把下面的x16運(yùn)算改變一下可以得到下面的圖:

nextclrs = (clrs+X)*12 

使用判斷得到0或1

nextclrs = X<0.5
nextclrs = nextclrs*200

修改DisplayNxN函數(shù)中的concatenate方法把RGB三個(gè)數(shù)字變得不同推捐,得到藍(lán)紫色圖像

acube3 = np.concatenate([20+30*np.cos(acube),
                        60+80*np.sin(acube),
                        200-40*np.cos(acube)], 2) 

更復(fù)雜的運(yùn)算

繼續(xù)上面的例子,我們把它改的更加復(fù)雜一些:

import tensorflow as tf
import numpy as np
from PIL import Image #用來(lái)顯示圖片的模塊

def DisplayNxN(atable, fmt='jpeg'):
    #a形狀[x,x]轉(zhuǎn)變到[x,x,1]
    acube = atable.reshape(list(atable.shape)+[1])
    #把[x,x,1]變?yōu)閇x,x,3],只是把一個(gè)元素復(fù)制3份表示每像素
    #acube3 = np.concatenate([acube,acube,acube], 2) 
    acube3 = np.concatenate([10+20*np.cos(acube),
                        30+50*np.sin(acube),
                        155-80*np.cos(acube)], 2)
    acube3 = np.uint8(np.clip(acube3, 0, 255)) #裁剪到255
    img=Image.fromarray(acube3)
    img.show()
    
#mgrid[start:end:step, start:end:step] 
#從start到end每份step均分成n份侧啼,得到兩個(gè)[n,n]形狀
sess = tf.InteractiveSession()

Y, X = np.mgrid[-1:1:0.005, -2:1:0.005]
Z = X+Y
Z = tf.constant(Z)
clrs = tf.Variable(Z)
nclrs = tf.Variable(tf.zeros_like(Z, tf.float32))

nclrs2 = clrs*2
div = tf.abs(nclrs2) < 3

step = tf.group(
    clrs.assign(nclrs2), 
    nclrs.assign_add(tf.cast(div, tf.float32))
  )

tf.global_variables_initializer().run()
for i in range(10): step.run()
        
DisplayNxN(nclrs.eval())

我們使用復(fù)數(shù)產(chǎn)生圓形

Y, X = np.mgrid[-1:1:0.005, -2:1:0.005]
Z = X+1j*Y
Z = tf.constant(Z.astype(np.complex64))
clrs = tf.Variable(Z)
nclrs = tf.Variable(tf.zeros_like(Z, tf.float32))

最后牛柒,調(diào)整一下nclrs2的算法,產(chǎn)生漂亮的分形圖案

nclrs2 = clrs*clrs+Z
div = tf.abs(nclrs2) < 3

下面還有一些其他算法產(chǎn)生的圖像:


nclrs2=clrs*clrs*clrs-1

nclrs2 = clrs*tf.cos(clrs*2)

nclrs2 = clrs*tf.sin(clrs+Y*0.8)

nclrs2 = clrs*tf.cos(clrs+Y*0.8)+clrs

最后痊乾,是完整的代碼皮壁,僅供參考:

import tensorflow as tf
import numpy as np
from PIL import Image #用來(lái)顯示圖片的模塊

def DisplayNxN(atable, fmt='jpeg'):
    #a形狀[x,x]轉(zhuǎn)變到[x,x,1]
    acube = atable.reshape(list(atable.shape)+[1])
    #把[x,x,1]變?yōu)閇x,x,3],只是把一個(gè)元素復(fù)制3份表示每像素
    #acube3 = np.concatenate([acube,acube,acube], 2) 
    acube3 = np.concatenate([10+20*np.cos(acube),
                        30+50*np.sin(acube),
                        155-80*np.cos(acube)], 2)
    acube3 = np.uint8(np.clip(acube3, 0, 255)) #裁剪到255
    img=Image.fromarray(acube3)
    img.show()
    
#mgrid[start:end:step, start:end:step] 
#從start到end每份step均分成n份,得到兩個(gè)[n,n]形狀
sess = tf.InteractiveSession()

Y, X = np.mgrid[-1:1:0.005, -2:1:0.005]
Z = X+1j*Y
Z = tf.constant(Z.astype(np.complex64))
clrs = tf.Variable(Z)
nclrs = tf.Variable(tf.zeros_like(Z, tf.float32))

nclrs2 = clrs*clrs+Z
div = tf.abs(nclrs2) < 3

step = tf.group(
    clrs.assign(nclrs2),
    nclrs.assign_add(tf.cast(div, tf.float32))
  )

tf.global_variables_initializer().run()
for i in range(100): step.run()
        
DisplayNxN(nclrs.eval())

探索人工智能的新邊界

如果您發(fā)現(xiàn)文章錯(cuò)誤哪审,請(qǐng)不吝留言指正蛾魄;
如果您覺得有用,請(qǐng)點(diǎn)喜歡湿滓;
如果您覺得很有用滴须,感謝轉(zhuǎn)發(fā)~


END

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市叽奥,隨后出現(xiàn)的幾起案子扔水,更是在濱河造成了極大的恐慌,老刑警劉巖朝氓,帶你破解...
    沈念sama閱讀 222,946評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件魔市,死亡現(xiàn)場(chǎng)離奇詭異主届,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)待德,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,336評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門岂膳,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人磅网,你說(shuō)我怎么就攤上這事】曷牛” “怎么了涧偷?”我有些...
    開封第一講書人閱讀 169,716評(píng)論 0 364
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)毙死。 經(jīng)常有香客問我燎潮,道長(zhǎng),這世上最難降的妖魔是什么扼倘? 我笑而不...
    開封第一講書人閱讀 60,222評(píng)論 1 300
  • 正文 為了忘掉前任确封,我火速辦了婚禮,結(jié)果婚禮上再菊,老公的妹妹穿的比我還像新娘爪喘。我一直安慰自己,他們只是感情好纠拔,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,223評(píng)論 6 398
  • 文/花漫 我一把揭開白布秉剑。 她就那樣靜靜地躺著,像睡著了一般稠诲。 火紅的嫁衣襯著肌膚如雪侦鹏。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,807評(píng)論 1 314
  • 那天臀叙,我揣著相機(jī)與錄音略水,去河邊找鬼。 笑死劝萤,一個(gè)胖子當(dāng)著我的面吹牛渊涝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播稳其,決...
    沈念sama閱讀 41,235評(píng)論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼驶赏,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了既鞠?” 一聲冷哼從身側(cè)響起煤傍,我...
    開封第一講書人閱讀 40,189評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嘱蛋,沒想到半個(gè)月后蚯姆,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體五续,經(jīng)...
    沈念sama閱讀 46,712評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,775評(píng)論 3 343
  • 正文 我和宋清朗相戀三年龄恋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了疙驾。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,926評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡郭毕,死狀恐怖它碎,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情显押,我是刑警寧澤扳肛,帶...
    沈念sama閱讀 36,580評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站乘碑,受9級(jí)特大地震影響挖息,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜兽肤,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,259評(píng)論 3 336
  • 文/蒙蒙 一套腹、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧资铡,春花似錦电禀、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,750評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至宛官,卻和暖如春葫松,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背底洗。 一陣腳步聲響...
    開封第一講書人閱讀 33,867評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工腋么, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人亥揖。 一個(gè)月前我還...
    沈念sama閱讀 49,368評(píng)論 3 379
  • 正文 我出身青樓珊擂,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親费变。 傳聞我的和親對(duì)象是個(gè)殘疾皇子摧扇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,930評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容