【CSDN 编者按】元宵佳节,一起赏花灯。

作者 | 许向武       责编 | 张红月

出处 | https://blog.csdn.net/xufive/article/details/114058247

说起元宵节,各位有没有觉得这是咱们中国人最浪漫的节日呢?国人向来拘谨古板,一年到头都是小心谨慎地过日子,唯有元宵节这天可以纵情豪放一把。东风夜放花千树,宝马雕车香满路,火树银花霓虹闪烁,豪车遍地美女如云。细品,你甚至都能嗅到香奈儿的味道!月上柳梢头,人约黄昏后,这又是何等的浪漫!比起烛光晚宴、鲜花加持,这份浪漫更显纯真。晚至明清,民间元宵节的喜庆气氛,堪比西班牙的奔牛节、巴西的狂欢节、泰国的泼水节。

由于众所周知的原因,估计今年的趵突泉元宵节灯会又要黄了。去哪儿体验“花市灯如昼”的节日气氛呢?Don’t worry,没有什么事能够难倒程序员——用3D技术也可以做出下图这样的走马灯,算是聊胜于无吧。

原材料

花灯纸

如下所示,还可以加上自己喜欢的图案、文字等。

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完全手册》https://xufive.blog.csdn.net/article/details/108958992。

制作工序

花灯制作工序非常简单,只需要三十行代码,可以直接在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-')

最终的花灯效果如下。

完整代码

# -*- coding: utf-8 -*-import numpy as np
from PIL import Image
import wxgl.wxplot as pltim = np.array(Image.open('res/paper.png'))/255
rows, cols, deep = im.shaper, 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-')

☞美团败诉,赔偿饿了么 100 万元;华为 Mate X2 首发秒没;库克获 8 亿年终奖 | 极客头条☞平均月薪 21.8k、中国开发者占比最高,揭晓 Go 语言真实现状!☞拿下丰厚的年终奖,却未能拯救总薪酬,2021 年度 IT 薪酬调查报告出炉!
☞当量子计算遇到机器学习

元宵节,程序员用 Python 送你一盏 3D 花灯相关推荐

  1. 元宵节来了,程序员用 Python 送你一盏 3D 花灯

    作者 | 天元浪子 来源 | Python作业辅导员(ID:dailyPython) 说起元宵节,各位有没有觉得这是咱们中国人最浪漫的节日呢?国人向来拘谨古板,一年到头都是小心谨慎地过日子,唯有元宵节 ...

  2. python送程序员收入_程序员学Python后惊叹,这么丰厚的收入是Java给不了的!

    原标题:程序员学Python后惊叹,这么丰厚的收入是Java给不了的! 你都用 Python 来做什么?? 发现很多人都在学习 Python ,但是没有明确的说明可以做什么,主流的功能是什么? 想知道 ...

  3. 30岁自学python找工作-程序员自学Python开发,20到30岁几乎决定了你的未来!

    原标题:程序员自学Python开发,20到30岁几乎决定了你的未来! 之前程序员界流行一句话:人生苦短,请用Python. 随着Python成为网红语言之后,不少程序员想多学这一门语言好傍身. 甚至有 ...

  4. python程序员发展-2018年,程序员对Python有着这些期待!

    [IT168 评论]自1991年首次发布以来,Python的普及程度已经大大提高,现在已经跻身在世界上最流行的编程语言之列,战胜了那些声明速度太慢或无法扩展的语言. 事实上,最近PayPal,Inst ...

  5. python程序员一天写多少行代码-程序员写Python时的5个坏习惯,你有几条?

    很多文章都有介绍怎么写好 Python,我今天呢,相反,说说写代码时的几个坏习惯.有的习惯会让 Bug 变得隐蔽难以追踪,当然,也有的并没有错误,只是个人觉得不够优雅. 注意:示例代码在 Python ...

  6. python3入门与进阶笔记_16_变量进阶 — 黑马程序员《Python入门教程完整版》笔记...

    变量进阶(理解) - 黑马程序员<Python入门教程完整版>笔记 目标变量的引用 可变和不可变类型 局部变量和全局变量 01. 变量的引用变量 和 数据 都是保存在 内存 中的 在 Py ...

  7. python 入门程序_非Python程序员的Python速成课程-如何快速入门

    python 入门程序 This article is for people who already have experience in programming and want to learn ...

  8. java min 函数的使用方法_【Python】Java程序员学习Python(五)— 函数的定义和使用...

    不想做一个待宰的羔羊!!!!要自己变得强大.... 函数的定义和使用放在最前边还是有原因的,现在语言趋于通用,基本类型基本都是那些,重点还是学习对象的使用方法,而最根本的还是方法的使用,因此优先介绍, ...

  9. 给Lisp程序员的Python简介

    给Lisp程序员的Python简介 作者:Peter Norvig,译者:jineslong<zzljlu@gmail.com> 这是一篇为Lisp程序员写的Python简介(一些Pyth ...

最新文章

  1. three相机在模型上_基于 three.js 的 3D 粒子动效实现
  2. hadoop的HDFS-----防火墙导致9870端口无法访问
  3. JavaScript-分支和循环
  4. redis 学习笔记一
  5. eos节点服务器_EOS跌落神坛?
  6. php 判定是否是数组,php判断一个数组是否为有序
  7. 51单片机的前世今世
  8. Excel填充日期和星期
  9. 计算机网络之物理层(定义标准+码间串扰(奈氏准则、香农定理)+基带信号、宽带信号+编码、调制+传输介质)
  10. 做后期必备!500组HDR贴图分享与使用方法讲解
  11. 程序员电脑屏保画面,显示时间
  12. FoxyProxy Standard与brupsuite配置
  13. 第4章 数据库应用系统功能设计与实施
  14. 后缀是lnk是什么文件_ink是什么文件
  15. 汉字转拼音 关于佛字转成了fu
  16. 怎么修改PDF文件中的文字
  17. 怎么实现文字转语音朗读?这几个小技巧快来码住
  18. python语言表示语句结构_python基础语言以及if/while语句结构
  19. ubuntu新建账户并赋予root权限
  20. 【深度学习】入门理解ResNet和他的小姨子们(一)---ResNet

热门文章

  1. 面试—每日一题(2)
  2. 单选 textarea 赋初值
  3. Hangover C语言 UVA2294
  4. Spring data Jpa,Mybatis,读写锁,@Lock 使用
  5. 合理使用webpack提高开发效率
  6. 专业 英语 心智 口才
  7. 性能测试工具AlldayTest 的测试方法及说明
  8. JavaScript 颜色梯度和渐变效果
  9. 地理空间数据Geometry在MySQL中使用(二)
  10. HIVESQL中ROW_NUMBER() OVER语法以及示例