使用Python制作一盏 3D 花灯喜迎元宵佳节
作者:酸菜鱼编程 发布时间:2021-08-15 06:35:43
说起元宵节,各位有没有觉得这是咱们中国人最浪漫的节日呢?国人向来拘谨古板,一年到头都是小心谨慎地过日子,唯有元宵节这天可以纵情豪放一把。东风夜放花千树,宝马雕车香满路,火树银花霓虹闪烁,豪车遍地美女如云。细品,你甚至都能嗅到香奈儿的味道!月上柳梢头,人约黄昏后,这又是何等的浪漫!比起烛光晚宴、鲜花加持,这份浪漫更显纯真。晚至明清,民间元宵节的喜庆气氛,堪比西班牙的奔牛节、巴西的狂欢节、泰国的泼水节。
由于众所周知的原因,估计今年的趵突泉元宵节灯会又要黄了。去哪儿体验“花市灯如昼”的节日气氛呢?Don't worry,没有什么事能够难倒程序员——用3D技术也可以做出下图这样的走马灯,算是聊胜于无吧。
1.原材料
花灯纸
如下所示,还可以加上自己喜欢的图案、文字等。
Python环境和模块
一台安装了Python环境的电脑,Python环境需要安装以下模块。
numpy
pillow
wxgl
如果没有上述模块,请参考下面的命令安装。
pip install numpy
pip install pillow
pip install wxgl
NumPy和 pillow 是 Python 旗下最常用的科学计算库和图像处理库,属于常用模块。WxGL 是一个基于 PyOpenGL 的三维数据可视化库,以 wx 为显示后端,提供 Matplotlib 风格的交互式应用模式,同时,也可以和 wxPython 无缝结合,在wx的窗体上绘制三维模型。
2.制作工序
花灯制作工序非常简单,只需要三十行代码,可以直接在Python IDLE中以交互方式逐行执行。
导入模块
>>> import numpy as np
>>> from PIL import Image
>>> import wxgl.wxplot as plt
打开花灯纸图像
>>> 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)。
根据花灯纸的大小制作龙骨
纸长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的方式画出来的龙骨,效果如下。
给龙骨贴上花灯纸
有了龙骨,接下来就可以把花灯纸贴在龙骨上了。继续操作之前,记得先把刚才弹出的3D龙骨窗口关闭。
>>> plt.mesh(xs, ys, zs, im)
>>> plt.show()
不过,你会立刻发现,花灯纸上下方向贴反了。没关系,我们可以像下面这样反转方向。
>>> plt.mesh(xs, ys, zs, im[::-1])
>>> plt.show()
怎么样,是不是有一点走马灯的雏形了呢?
制作旋转叶轮
走马灯之所以能够转动,是因为里面有蜡烛加热形成上升气流,推动顶部的叶轮旋转,从而带动花灯旋转。当然,这里的叶轮仅仅是个样子,花灯旋转依赖另外的机制实现。
>>> 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,整体效果略显粗糙了一点。
加上照明灯和提系
照明灯用一个白色的圆球表示,提系则是红色的一条直线,兼做照明灯的电源线。
>>> 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')
让花灯转起来
花灯旋转的实现非常简单,只需要给show方法一个rotation参数就可以。
plt.show(rotation='h-')
最终的花灯效果如下。
3.完整代码
# -*- 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.cnblogs.com/python147/archive/2021/02/26/14451962.html


猜你喜欢
- 本文介绍了vue生成随机验证码的示例代码,分享给大家,具体如下:样式自调,最终效果如图:实现效果:点击右边input框会自动切换,如果输入的
- 在数据预处理过程中可能需要将列的顺序颠倒,有两种方法。import numpy as npimport pandas as pddf = p
- css usage是一个基于firebug的firefox扩展,可以用来查看页面中的CSS的使用情况,可以清楚的查看css文件中所有的规则在
- 四、 用户注册(reg.php)在看用户注册之流程之前,我把表的用途做个简单说明,现在只是大概的说明,后面我们再仔细了解,大家可以记下这个说
- user-define-session-inc.php文件代码:<?php function mysession_open($save
- 在使用mysql的过程中,有个问题就是mysql的优化,mysql中longblob字段在5.5版本中默认的为1M。 想改变这个问题,需要注
- 如下所示:temp1 = [[] for i in range(10)]temp2 = [temp1 for i in range(20)]
- 第一步一般是建立一个关键字替换表 如 id keyword url 等字段第二步是文章显示时把【文章】内容和【关键字替换表】对应的关键字替换
- 前言:Python可以引入指定路径的文件,原理就是使用sys.path.append加入到程序查找的路径。实验目的:调用不同目录的类和接口,
- 什么是目标检测目标检测关注图像 * 定的物体目标,需要同时解决解决定位(localization) + 识别(Recognition)。相比分
- create table [order] ( code varchar(50), createtime datetime ) --应用 us
- 例子: rsajax.js: var http_request = false; function makePOSTRequest(url,
- 代码如下: '排序 Function Sort1(ary) Dim KeepChecking,I,FirstValue,Second
- 一、python logging日志模块简单封装项目根目录创建 utils/logUtil.pyimport loggingfrom log
- 前言小程序跳一跳最近很火,之前爆出微信游戏小程序漏洞,网上也不乏大神。这里就用一大神的python脚本来刷下高分。 跳一跳python脚本传
- Nodemailer是一个简单易用的Node.js邮件发送组件,具体操作如下1、安装nodemailernpm install nodema
- 实现一个柱状图,这个柱状图的高度在不停的刷新,效果如下:官网是没有动态刷新的示例的,由于需要我查看了其源码,并根据之前示例做出了动态柱状图的
- 今天在写一个研究生创新项目申报书时涉及到一个python画图问题,对于在x轴各个区段显示自定义的字符串有些疑问,特此记录。界面如下所示:代码
- 关于python数据分析常用库pandas中的DataFrame的loc和iloc取数据 基本方法总结归纳及示例如下:1.准备一组DataF
- SpringBoot体系内推荐使用Thymeleaf作为前端页面模板。jsp还得自己整合一下。1.项目结构对比以前的项目结构,main目录下