天天看點

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

項目源碼:shan-shui inf

隻要輸入任意字元串,這個AI便會生成一幅全新的畫作,每一幅都是世間獨一無二的,就像是開山水畫盲盒。

并且這些作品并不是簡單的元素堆積——項目中沒有用到任何一張圖檔素材,所有的景物都是代碼生成的。

我們可以看到畫中的山石錯落有緻。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

樹木各具神态——或蒼勁有力,或郁郁蔥蔥,或新芽初發,或垂垂老矣。

遠山和近景,都做了不同層次的處理。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

對飲的文人、垂釣的老者各具神态,山上的寶塔、田間的茅草屋各有特點。偶爾還藏了一個電線杆和Pizza Hut的彩蛋,讓你迷失在畫裡,不知身處何處。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

而完成這些的核心代碼都是H5純手寫的,沒有用到第三方庫,整個檔案大小不過100多K。這樣一個“簡簡單單”的程式,再加上一塊V853開發闆,就也能輕松渲染出一幅獨一無二山水畫,若是再心靈手巧一點,把它做成一個電子相框裱起來挂在工位上,陶冶情操,豈不美哉。

可以看出,作者不僅對AI算法有很深的了解,在國畫上也有很高的造詣,才能實作科技與人文的深度結合。

那麼,這些神奇是如何實作的呢?知乎AI大佬 【胡虎護弧呼】給我們介紹了一些簡單的原理。

宛若手繪的山

執行個體下載下傳:mountain handmade

山水畫裡的樹葉與小樹是用多邊形表示的。從簡單的開始,一個三角形代表山的形狀,直線作為陰影。現在從視覺上看來,這些代表陰影的直線還是太過生硬,完全不像可以生成“山水畫”的感覺,我們來把分立的直線變成下圖這樣連續的曲線。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

有時候簡單的方法的也有驚人的效果。我們可以用一根斜率稍微不相同的線的向下切,并在垂直邊和水準邊選擇幾個采樣點。然後在這些有序的點之間連接配接曲線,比如貝塞爾曲線或Catmull-Rom曲線。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

生成曲線時,如果是标準的曲線,那麼肯定太規則了不好看。那麼再加控制點,再加噪音弄得更随機一點。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

這些陰影的邊界是三角形,還是太規則,于是把這些邊界也多弄些控制點多弄些噪音。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

再把陰影線條的粗細變成随機形式,以及表示山的形狀的直線變成多段折線,最終效果如下。記得陰影和有光照的地方需要描邊。現在山的受到光照的地方太秃了,那麼再來加上一些變換。第一種如下圖,下圖左加了一道小山溝,下圖中為小山溝加上一些陰影,最後效果如下圖右。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

似乎還是有些不自然...山的邊緣真的隻是首尾相連的折線嘛?我們可以把這些折線稍微延長一些,然後再加上第二座山。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫
僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

目前隻是繪出了單座山,如何确定連片的山脈的位置呢?一種容易想到的方法是讓山都生成在一根直線附近。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

另一種方法是生成首尾相連的折線段,用這些折線段作為山的輪廓。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

也可以先用多邊形限制山的生成範圍,然後在多邊形内放置線段,用于生成山脈。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫
僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

有了山,也就相當于給山脈打下了堅實的地基,接下來要做的就是給山水畫添上其他的元素:樹木、亭子、古人.......

樹木的随機生成——數值奇異值分解

從源碼角度切入樹木的随機生成,繁多的樹木其實也是由類似的噪點和數學函數的運算進行了大小、形态以及位置的确定。

tree02生成的部分源碼:

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

以 ‘tree02’ 為例子,樹木的随機生成方式與山體随機生成的方式在原理上是大緻相同的,兩者應該都是使用了大量的噪點和數學函數從頭開始模組化,并随機配置設定坐标位置的。

那随機生成的樹木又是如何做到棵棵都不一樣的呢,這裡就有可能使用到了渲染程式設計中的數值奇異值分解原理了(不代表作者源碼是基于該原理随機生成)。

奇異值分解表達如下:

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

其中A 是原矩陣。V 和 U都是旋轉矩陣,Sigma 是對角矩陣,代表伸縮矩陣。網上資料很多,這裡不解釋。

這裡僅僅讨論它的實體意義。比如對于某個向量矩陣變換A,如果它是純伸縮矩陣,那麼左右奇異矩陣都是機關矩陣

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

經過矩陣變換後,為了資料降維,找出變換最明顯的向量,需要選擇正x 軸和正y 軸,如下圖。藍色軸和黃色軸即為在本次矩陣變化中,變化最為明顯的向量。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

注意向量并不局限于邊,三角形内的任意一段向量都可以,端點不固定,方向不固定。隻是說藍色向量,黃色向量在此次矩陣變換中,變長或變短的程度最大。它們變長或變短的倍數,就是奇異值。

如果這是個剪切矩陣,那麼可能如下:

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

那麼我們需要旋轉一下黃色或藍色向量,來保證黃色向量和藍色向量仍然是所有向量中長度變化最明顯的。比如黃色向量變長為原來的1.3倍。但是與之前的純伸縮矩陣相比,也就是與上圖相比,它還旋轉了135度,這是矩陣U 的功勞。而藍色向量縮短為原來的0.7倍,同樣旋轉了135度,這是矩陣V的功勞。

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

噪點可能在經過如上原理的函數運算後,最終生成了各式各樣的樹木、山巒、建築等等等,該種函數運算的随機生成方式同時也展現于其他類型樹木生成的源碼之中。

tree07生成的部分源碼:

僅用5000行代碼,在全志V853上AI渲染出一億幅山水畫

作者Huang Lingdong

作者Huang Lingdong,大學畢業于卡耐基梅隆大學,現于母校的Studio for Creative Inquiry做研究助理,為博物館和學校等組織開發互動媒體項目。

繼續閱讀