文章目錄
- 1 前言
- 2 原材料
- 2.1 花燈紙
- 2.2 Python環境和模塊
- 3 制作工序
- 3.1 匯入模塊
- 3.2 打開花燈紙影像
- 3.3 根據花燈紙的大小制作龍骨
- 3.4 給龍骨貼上花燈紙
- 3.5 制作旋轉葉輪
- 3.6 加上照明燈和提系
- 3.7 讓花燈轉起來
- 4 完整源代碼
1 前言
說起元宵節,各位有沒有覺得這是咱們中國人最浪漫的節日呢?國人向來拘謹古板,一年到頭都是小心謹慎地過日子,唯有元宵節這天可以縱情豪放一把,東風夜放花千樹,寶馬雕車香滿路,火樹銀花霓虹閃爍,豪車遍地美女如云,細品,你甚至都能嗅到香奈兒的味道!月上柳梢頭,人約黃昏后,這又是何等的浪漫!比起燭光晚宴、鮮花加持,這份浪漫更顯純真,晚至明清,民間元宵節的喜慶氣氛,堪比西班牙的奔牛節、巴西的狂歡節、泰國的潑水節,
由于眾所周知的原因,估計今年的趵突泉元宵節燈會又要黃了,去哪兒體驗“花市燈如晝”的節日氣氛呢?Don’t worry,沒有什么事能夠難倒程式員——用3D技術也可以做出下圖這樣的走馬燈,算是聊勝于無吧,

2 原材料
2.1 花燈紙
如下所示,還可以加上自己喜歡的圖案、文字等,

2.2 Python環境和模塊
一臺安裝了Python環境的電腦,Python環境需要安裝以下模塊,
- numpy
- pillow
- wxgl
如果沒有上述模塊,請參考下面的命令安裝,
pip install numpy
pip install pillow
pip install wxgl
NumPy和pillow是Python旗下最常用的科學計算庫和影像處理庫,屬于常用模塊,WxGL是一個基于PyOpenGL的三維資料可視化庫,以wx為顯示后端,提供Matplotlib風格的互動式應用模式,同時,也可以和wxPython無縫結合,在wx的表單上繪制三維模型,關于WxGL的更多資訊,請參閱我的另一篇博客《十分鐘玩轉3D繪圖:WxGL完全手冊》,
3 制作工序
花燈制作工序非常簡單,只需要三十行代碼,可以直接在Python IDLE中以互動方式逐行執行,
3.1 匯入模塊
>>> import numpy as np
>>> from PIL import Image
>>> import wxgl.wxplot as plt
3.2 打開花燈紙影像
>>> fn = r'D:\temp\light0115\res\paper.png'
>>> im = np.array(Image.open(fn))/255
>>> im.shape
(400, 942, 3)
fn定義的是影像存盤路徑,請據實修改,Image.open(fn)打開檔案,回傳一個PIL物件,np.array()將PIL物件轉成numpy.ndarray陣列物件,除以255,將影像資料從0到255的值域范圍變成0到1,適應WxGL的介面要求,查看陣列的shape,顯示影像解析度為400像素高、942像素寬,每個像素有三種顏色(此處為RGB),
3.3 根據花燈紙的大小制作龍骨
紙長942像素,卷成圓筒,半徑就是149.9像素,如果把半徑視為1個單位,則高度400像素相當于2.668個單位,
>>> rows, cols, deep = im.shape
>>> cols/(2*np.pi)
149.9239563925654
>>> r = 1
>>> h = 2*np.pi*rows/cols
>>> h
2.6680192387174464
接下來需要制作半徑1個單位、高度2.668個單位的圓筒狀龍骨了,
>>> theta = np.linspace(0, 2*np.pi, cols)
>>> x = r * np.cos(theta)
>>> y = r * np.sin(theta)
>>> z = np.linspace(0, h, rows)
>>> xs = np.tile(x, (rows,1))
>>> ys = np.tile(y, (rows,1))
>>> zs = z.repeat(cols).reshape((rows,cols))
這里的xs、ys、zs就是圓筒狀龍骨上各個點的x坐標、y坐標、z坐標,下面的代碼,每隔10個點抽取1個點,用mesh的方法畫出龍骨形狀,當然,也可以畫出全部的點,那樣頂點就會連成一片,
>>> plt.mesh(xs[::10,::10], ys[::10,::10], zs[::10,::10], mode='FLBL')
>>> plt.show()
用3D的方式畫出來的龍骨,效果如下,

3.4 給龍骨貼上花燈紙
有了龍骨,接下來就可以把花燈紙貼在龍骨上了,繼續操作之前,記得先把剛才彈出的3D龍骨視窗關閉,
>>> plt.mesh(xs, ys, zs, im)
>>> plt.show()
不過,你會立刻發現,花燈紙上下方向貼反了,沒關系,我們可以像下面這樣反轉方向,
>>> plt.mesh(xs, ys, zs, im[::-1])
>>> plt.show()
怎么樣,是不是有一點走馬燈的雛形了呢?

3.5 制作旋轉葉輪
走馬燈之所以能夠轉動,是因為里面有蠟燭加熱形成上升氣流,推動頂部的葉輪旋轉,從而帶動花燈旋轉,當然,這里的葉輪僅僅是個樣子,花燈旋轉依賴另外的機制實作,
>>> theta = np.linspace(0, 2*np.pi, 18, endpoint=False)
>>> x = r * np.cos(theta)
>>> y = r * np.sin(theta)
>>> x[2::3] = x[1::3]
>>> x[1::3] = 0
>>> y[2::3] = y[1::3]
>>> y[1::3] = 0
>>> z = np.ones(18) * h * 0.9
>>> vs = np.stack((x,y,z), axis=1)
>>> plt.mesh(xs, ys, zs, im[::-1])
>>> plt.surface(vs, color='#C03000', method='T', mode='FCBC', alpha=0.8)
>>> plt.show()
葉輪設計有6片,用三角形模擬,顏色深紅,透明度0.8,整體效果略顯粗糙了一點,

3.6 加上照明燈和提系
照明燈用一個白色的圓球表示,提系則是紅色的一條直線,兼做照明燈的電源線,
>>> plt.mesh(xs, ys, zs, im[::-1])
>>> plt.surface(vs, color='#C03000', method='T', mode='FCBC', alpha=0.8)
>>> plt.sphere((0,0,h*0.4), 0.4, '#FFFFFF', slices=60, mode='FCBC')
>>> plt.plot((0,0), (0,0), (0.4*h, 1.5*h), width=3.0, style='solid', cmap='hsv', caxis='z')
3.7 讓花燈轉起來
花燈旋轉的實作非常簡單,只需要給show方法一個rotation引數就可以,
plt.show(rotation='h-')
最終的花燈效果如下,

4 完整源代碼
有了上面的解說,完整的源代碼就不用注釋了,全部代碼三十余行,各位可自行擴展,制作出更多的花燈來,
# -*- coding: utf-8 -*-
import numpy as np
from PIL import Image
import wxgl.wxplot as plt
im = np.array(Image.open('res/paper.png'))/255
rows, cols, deep = im.shape
r, h = 1, 2*np.pi*rows/cols
theta = np.linspace(0, 2*np.pi, cols)
x = r*np.cos(theta)
y = r*np.sin(theta)
z = np.linspace(0, h, rows)
xs = np.tile(x, (rows,1))
ys = np.tile(y, (rows,1))
zs = z.repeat(cols).reshape((rows,cols))
theta = np.linspace(0, 2*np.pi, 18, endpoint=False)
x = r*np.cos(theta)
y = r*np.sin(theta)
x[2::3] = x[1::3]
x[1::3] = 0
y[2::3] = y[1::3]
y[1::3] = 0
z = np.ones(18) * h * 0.9
vs = np.stack((x,y,z), axis=1)
plt.mesh(xs, ys, zs, im[::-1])
plt.surface(vs, color='#C03000', method='T', mode='FCBC', alpha=0.8)
plt.sphere((0,0,h*0.4), 0.4, '#FFFFFF', slices=60, mode='FCBC')
plt.plot((0,0), (0,0), (0.4*h, 1.5*h), width=3.0, style='solid', cmap='hsv', caxis='z')
plt.show(rotation='h-')
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/263762.html
標籤:AI
上一篇:【動手擼深度學習】細粒辨花 一文實踐清華博士Densenet
下一篇:有趣的離線存盤
