当前位置: 首页 > news >正文

Python实现火柴人的设计与实现

1.引言

火柴人(Stick Figure)是一种极简风格的图形,通常由简单的线段和圆圈组成,却能生动地表达人物的姿态和动作。火柴人不仅广泛应用于动画、漫画和涂鸦中,还可以作为图形学、人工智能等领域的教学和研究工具。本文旨在介绍如何使用Python实现火柴人的设计与绘制,通过编程的方式,让读者了解火柴人背后的基本原理和实现方法。

2.准备工作

在开始实现火柴人之前,你需要确保已经安装了Python环境,并且熟悉基本的Python编程知识。此外,为了绘制图形,我们将使用matplotlib库,这是一个强大的绘图库,适用于生成各种静态、动态和交互式的图表。

你可以通过以下命令安装matplotlib

bash复制代码
​
pip install matplotlib

3.基础理论知识

火柴人的绘制主要依赖于几何图形的绘制和变换。具体来说,我们需要:

(1)定义关节:火柴人的关节包括头部、肩膀、肘部、手腕、臀部、膝盖和脚踝等。这些关节可以看作二维或三维空间中的点。

(2)绘制线段:根据关节的位置,绘制连接关节的线段,这些线段构成了火柴人的骨骼。

(3)添加圆形:在头部等关节处添加圆形,以表示关节。

(4)变换与动画:通过变换关节的位置,可以实现火柴人的动作和动画效果。

4.步骤详解

下面,我们将逐步介绍如何使用Python和matplotlib绘制火柴人。

(1)导入库

首先,我们需要导入matplotlib库中的pyplot模块:

import matplotlib.pyplot as plt  
import numpy as np

(2)定义关节位置

为了简单起见,我们先在二维平面上定义火柴人的关节位置。这里以一个简单的火柴人站立姿势为例:

# 定义关节位置  
head = [0, 1]  
torso = [0, 0]  
left_shoulder = [-0.5, 0]  
left_elbow = [-1, -0.5]  
left_hand = [-1, -1]  
right_shoulder = [0.5, 0]  
right_elbow = [1, -0.5]  
right_hand = [1, -1]  
left_hip = [-0.5, -0.5]  
left_knee = [-1, -1.5]  
left_foot = [-1, -2]  
right_hip = [0.5, -0.5]  
right_knee = [1, -1.5]  
right_foot = [1, -2]  # 将关节位置存储在一个字典中  
joints = {  'head': head,  'torso': torso,  'left_shoulder': left_shoulder,  'left_elbow': left_elbow,  'left_hand': left_hand,  'right_shoulder': right_shoulder,  'right_elbow': right_elbow,  'right_hand': right_hand,  'left_hip': left_hip,  'left_knee': left_knee,  'left_foot': left_foot,  'right_hip': right_hip,  'right_knee': right_knee,  'right_foot': right_foot  
}

(3)绘制火柴人

接下来,我们编写一个函数,根据关节位置绘制火柴人:

def draw_stick_figure(joints, ax):  # 绘制身体  body_parts = [  ('torso', 'head'),  ('torso', 'left_shoulder'), ('left_shoulder', 'left_elbow'), ('left_elbow', 'left_hand'),  ('torso', 'right_shoulder'), ('right_shoulder', 'right_elbow'), ('right_elbow', 'right_hand'),  ('torso', 'left_hip'), ('left_hip', 'left_knee'), ('left_knee', 'left_foot'),  ('torso', 'right_hip'), ('right_hip', 'right_knee'), ('right_knee', 'right_foot')  ]  for start, end in body_parts:  start_pos = np.array(joints[start])  end_pos = np.array(joints[end])  ax.plot([start_pos[0], end_pos[0]], [start_pos[1], end_pos[1]], 'k-')  # 绘制头部  circle = plt.Circle(joints['head'], 0.1, color='black', fill=True)  ax.add_patch(circle)  # 绘制手部(可选)  circle = plt.Circle(joints['left_hand'], 0.05, color='black', fill=True)  ax.add_patch(circle)  circle = plt.Circle(joints['right_hand'], 0.05, color='black', fill=True)  ax.add_patch(circle)  # 绘制脚部(可选)  circle = plt.Circle(joints['left_foot'], 0.05, color='black', fill=True)  ax.add_patch(circle)  circle = plt.Circle(joints['right_foot'], 0.05, color='black', fill=True)  ax.add_patch(circle)

(4)绘制并显示图形

最后,我们创建一个图形对象,调用绘制函数,并显示结果:

def main():  fig, ax = plt.subplots()  ax.set_aspect('equal')  ax.axis('off')  # 关闭坐标轴  draw_stick_figure(joints, ax)  plt.show()  if __name__ == "__main__":  main()

5.常见问题解答

(1)火柴人看起来扭曲或比例不对:这通常是由于关节位置定义不合理或线段连接错误导致的。检查关节位置和连接顺序是否正确。

(2)图形显示不全:确保设置ax.set_aspect('equal'),使得图形按等比例显示。

(3)如何添加动画效果:可以使用matplotlibFuncAnimation类,通过不断更新关节位置来实现动画效果。

6.成果案例分享

通过上述步骤,你已经成功绘制了一个简单的火柴人。接下来,我们可以尝试更复杂的姿势和动画效果。例如,通过改变关节位置,实现火柴人的跳跃、行走等动作。

下面是一个简单的动画示例,展示火柴人从左到右移动的过程:

import matplotlib.animation as animation  def update_position(frame, joints):  # 这里我们简单地将火柴人向右移动  translation = 0.1 * frame  for key in joints.keys():  joints[key][0] += translation  return joints  def animate(frame):  global joints_anim  joints_anim = update_position(frame, joints_anim)  ax.clear()  ax.set_aspect('equal')  ax.axis('off')  draw_stick_figure(joints_anim, ax)  def main_animation():  fig, ax = plt.subplots()  global joints_anim  joints_anim = {key: value.copy() for key, value in joints.items()}  # 复制初始关节位置  ani = animation.FuncAnimation(fig, animate, frames=100, interval=100)  plt.show()  if __name__ == "__main__":  main_animation()

7.案例代码示例

以下是完整的代码示例,包括所有步骤和注释:

import matplotlib.pyplot as plt  
import numpy as np  
import matplotlib.animation as animation  # 定义关节位置  
joints = {  'head': [0, 1],  'torso': [0, 0],  'left_shoulder': [-0.5, 0],  'left_elbow': [-1, -0.5],  'left_hand': [-1, -1],  'right_shoulder': [0.5, 0],  'right_elbow': [1, -0.5],  'right_hand': [1, -1],  'left_hip': [-0.5, -0.5],  'left_knee': [-1, -1.5],  'left_foot': [-1, -2],  'right_hip': [0.5, -0.5],  'right_knee': [1, -1.5],  'right_foot': [1, -2]  
}  # 将关节位置转换为numpy数组,以便进行数学运算  
joints = {key: np.array(value) for key, value in joints.items()}  # 绘制火柴人的函数  
def draw_stick_figure(joints, ax):  # 清除之前的绘图  ax.clear()  # 设置坐标轴的比例和限制  ax.set_aspect('equal')  ax.set_xlim(-2, 2)  ax.set_ylim(-2.5, 1.5)  # 定义身体部分和对应的颜色(可选)  body_parts = [  ('torso', 'head', 'black'),  ('torso', 'left_shoulder', 'black'), ('left_shoulder', 'left_elbow', 'black'), ('left_elbow', 'left_hand', 'black'),  ('torso', 'right_shoulder', 'black'), ('right_shoulder', 'right_elbow', 'black'), ('right_elbow', 'right_hand', 'black'),  ('torso', 'left_hip', 'black'), ('left_hip', 'left_knee', 'black'), ('left_knee', 'left_foot', 'black'),  ('torso', 'right_hip', 'black'), ('right_hip', 'right_knee', 'black'), ('right_knee', 'right_foot', 'black')  ]  # 绘制火柴人的各个部分  for part in body_parts:  start_joint, end_joint, color = part[0], part[1], part[2] if len(part) > 2 else 'black'  ax.plot([joints[start_joint][0], joints[end_joint][0]], [joints[start_joint][1], joints[end_joint][1]], color=color, linewidth=2)  # 显示网格(可选)  ax.grid(True)  # 创建图形和坐标轴  
fig, ax = plt.subplots()  # 初始化函数(用于动画)  
def init():  draw_stick_figure(joints, ax)  return []  # 返回空列表,因为我们没有需要更新的艺术家对象  # 动画更新函数  
def update(frame):  # 这里可以添加使火柴人移动或改变姿势的逻辑  # 例如,简单地旋转手臂或腿  # 但为了简化,我们在这里不改变关节位置  draw_stick_figure(joints, ax)  return []  # 同样返回空列表  # 创建动画  
ani = animation.FuncAnimation(fig, update, frames=100, init_func=init, blit=True, interval=100)  # 显示图形  
plt.show()

请注意以下几点:

(1)我将关节位置转换为了numpy数组,以便在需要时进行数学运算(虽然在这个简单的例子中并没有用到)。

(2)在draw_stick_figure函数中,我添加了设置坐标轴比例和限制的代码,以及一个可选的网格显示。

(3)在body_parts列表中,我添加了颜色参数,但在这个例子中,我默认使用了黑色。你可以根据需要更改颜色。

(4)在update函数中,我没有改变关节位置,因此火柴人在动画中保持静止。你可以根据需要添加逻辑来改变火柴人的姿势或位置。

(5)我使用了FuncAnimation来创建动画,并设置了100帧和每帧之间的间隔为100毫秒。你可以根据需要调整这些参数。

运行这段代码将显示一个包含静止火柴人的窗口,并且由于动画的设置,它会每隔100毫秒重新绘制一次(尽管看起来是静止的,因为关节位置没有改变,感兴趣的读者朋友可以尝试改变关节位置)。

相关文章:

Python实现火柴人的设计与实现

1.引言 火柴人(Stick Figure)是一种极简风格的图形,通常由简单的线段和圆圈组成,却能生动地表达人物的姿态和动作。火柴人不仅广泛应用于动画、漫画和涂鸦中,还可以作为图形学、人工智能等领域的教学和研究工具。本文…...

衡石分析平台系统分析人员手册-应用模版

应用模板​ 应用模板使分析成果能被快速复用,节省应用创作成本,提升应用创作效率。此外应用模板实现了应用在不同环境上快速迁移。 支持应用复制功能 用户可以从现有的分析成果关联到新的分析需求并快速完成修改。 支持应用导出为模板功能 实现多个用户…...

Git和SVN

一. Git和SVN的区别 1.1 Git是分布式的,SVN是集中式的 1.2 Git复杂概念多,SVN简单易上手 Git 的命令实在太多了,日常工作需要掌握 add, commit, status, fetch, push, rebase等,若要熟练掌握,还必须掌握 rebase和 m…...

【C语言教程】【常用类库】(十八)宏与预处理 - <stddef.h> 和 <stdbool.h>

18. 宏与预处理 - <stddef.h> 和 <stdbool.h> C语言的宏和预处理指令在程序编译之前就被执行&#xff0c;用于文件包含、符号定义、条件编译等操作。理解和运用宏和预处理可以提高代码的灵活性和可移植性。 18.1 宏定义与条件编译 18.1.1 #define 与参数化宏 #…...

订单超时过期的实现方案的探讨

在我们的业务开发中&#xff0c;会遇到这样一个场景&#xff0c;用户下了一个单&#xff0c;如果超过20分钟不进行支付&#xff0c;订单就要变成已取消状态。 字段设定 订单中需要设定了三个字段&#xff1a;订单是否取消、是否支付、支付超时时间。 订单是否取消会存在&…...

C++中的CRTP

CRTP&#xff0c;全称为 Curiously Recurring Template Pattern&#xff08;奇异递归模板模式&#xff09;&#xff0c;是一种在C中使用继承和模板技术来实现静态多态和功能复用的惯用法。它使用派生类来模板参数化基类&#xff0c;使得基类能够访问派生类&#xff0c;从而在编…...

go压缩的使用

基础&#xff1a;使用go创建一个zip func base(path string) {// 创建 zip 文件zipFile, err : os.Create("test.zip")if err ! nil {panic(err)}defer zipFile.Close()// 创建一个新的 *Writer 对象zipWriter : zip.NewWriter(zipFile)defer zipWriter.Close()// 创…...

一图解千言,了解常见的流程图类型及其作用

在企业管理、软件研发过程中&#xff0c;经常会需要进行各种业务流程梳理&#xff0c;而流程图就是梳理业务时必要的手段&#xff0c;同时也是梳理的产出。但在不同的情况下适用的流程图又不尽相同。 本文我们就一起来总结一下8 种最常见的流程图类型 数据流程图 数据流程图&…...

【微信小程序_19_自定义组件(1)】

摘要:本文主要介绍了小程序开发中自定义组件的相关知识。包括组件的创建与引用,可在项目根目录创建组件文件夹,生成相应文件,并根据使用频率选择全局或局部引用。还阐述了组件和页面的区别,如组件的.json 文件需声明 “component: true”,.js 文件调用 Component () 函数…...

标准版admin后台页面添加及开发操作流程及注意事项

基础介绍 CRMEB后台管理是基于vue2技术栈进行开发搭建的 Vue Router 使用的是v3版本&#xff0c;mode为history模式 如需修改 mode 请在src/setting.js中修改routerMode 新建页面 新建路由 根据目录结构&#xff0c;需要在src/router/modules中对应模块中&#xff0c;添加对…...

‘perl‘ 不是内部或外部命令,也不是可运行的程序 或批处理文件。

‘perl’ 不是内部或外部命令,也不是可运行的程序 或批处理文件。 明明已经根据教程安装了perl环境,但是在cmd中依赖报该错误,本章教程提供解决办法。 一、激活perl环境 state shell ActiveState-Perl-5.36.0此时输入perl -v 是可以直接输出perl版本号的。 二、找到perl的执…...

如何利用CMMI帮助组织消除低价值流程

CMMI发展到今天&#xff0c;过程中历经了不断的蜕变和升级。从早期的CMM到今天的CMMI3.0&#xff0c;从早期的22个过程域优化组合到今天的20个实践域&#xff0c;从早期隶属的SEI到今天的CMMI研究院&#xff0c;所有的变化都是与时俱进&#xff0c;都是为了提供更好的实践&…...

如何理解线程安全这个概念?

文章目录 为什么需要线程安全&#xff1f;线程安全的实现方式总结推荐阅读文章 线程安全&#xff08;Thread Safety&#xff09;是指在多线程环境中&#xff0c;多个线程同时访问某个对象时&#xff0c;不会导致程序出现错误的状态或不一致的结果。简单来说&#xff0c;线程安全…...

代码随想录算法训练营第48天| 739. 每日温度,496.下一个更大元素 I,503.下一个更大元素II

第十一章&#xff1a;图论part01 图论理论基础 大家可以在看图论理论基础的时候&#xff0c;很多内容 看不懂&#xff0c;例如也不知道 看完之后 还是不知道 邻接矩阵&#xff0c;邻接表怎么用&#xff0c; 别着急。 理论基础大家先对各个概念有个印象就好&#xff0c;后面在…...

Qt 支持打包成安卓

1. 打开维护Qt&#xff0c;双击MaintenanceTool.exe 2.登陆进去,默认是添加或移除组件&#xff0c;点击下一步&#xff0c; 勾选Android, 点击下一步 3.更新安装中 4.进度100%&#xff0c;完成安装&#xff0c;重启。 5.打开 Qt Creator&#xff0c;编辑-》Preferences... 6.进…...

PDF工具类源码

PDF-Guru: PDF Guru Anki是一款以PDF为中心的多功能办公学习工具箱软件&#xff0c;包含四大板块功能&#xff1a;PDF实用工具箱、Anki制卡神器、Anki最强辅助、视频笔记神器&#xff0c;软件功能众多且强大&#xff0c;熟练运用可以大幅提高办公和学习效率&#xff0c;绝对是您…...

NirCmd-Gui-Chinese-Introduction

简介 此程序是我的一个练习作品&#xff0c;单纯是为了提升编程水平&#xff0c;次要是为了做一个NirCmd的Gui&#xff0c;其实主要成分还是Gui&#xff0c;核心代码就两三行。 主要是Gui&#xff0c;功能基于nircmd.exe实现&#xff0c;程序本身不提供一些重要的功能。 关于…...

吴恩达深度学习笔记(7)

误差分析&#xff1a; 你运行一个算法代替人类计算&#xff0c;但是没有达到人类的效果&#xff0c;需要手动检查算法中的错误&#xff0c;对模型的一些部分做相应调整&#xff0c;才能更好地提升分类的精度。如果不加分析去做&#xff0c;可能几个月的努力对于提升精度并没有…...

二、数据离线处理场景化解决方案

https://connect.huaweicloud.com/courses/learn/Learning/sp:cloudEdu_?courseNocourse-v1:HuaweiXCBUCNXE147Self-paced&courseType1 1.离线处理方案 **业务场景-安平领域** 业务场景-金融领域 离线批处理常用组件 HDFS&#xff1a;分布式文件系统&#xff0c;为各种…...

算法题总结(十四)——贪心算法(上)

贪心算法 什么是贪心 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 贪心的套路&#xff08;什么时候用贪心&#xff09; 刷题或者面试的时候&#xff0c;手动模拟一下感觉可以局部最优推出整体最优&#xff0c;而且想不到反例&#xff0c;那么就试一试…...

DAY 47

三、通道注意力 3.1 通道注意力的定义 # 新增&#xff1a;通道注意力模块&#xff08;SE模块&#xff09; class ChannelAttention(nn.Module):"""通道注意力模块(Squeeze-and-Excitation)"""def __init__(self, in_channels, reduction_rat…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

MMaDA: Multimodal Large Diffusion Language Models

CODE &#xff1a; https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA&#xff0c;它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构&#xf…...

【论文笔记】若干矿井粉尘检测算法概述

总的来说&#xff0c;传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度&#xff0c;通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

用鸿蒙HarmonyOS5实现中国象棋小游戏的过程

下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...

Python训练营-Day26-函数专题1:函数定义与参数

题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一个名为 calculate_circle_area 的函数&#xff0c;该函数接收圆的半径 radius 作为参数&#xff0c;并返回圆的面积。圆的面积 π * radius (可以使用 math.pi 作为 π 的值)要求&#xff1a;函数接收一个位置参数 radi…...

在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南

在RK3588上搭建ROS1环境:创建节点与数据可视化实战指南 背景介绍完整操作步骤1. 创建Docker容器环境2. 验证GUI显示功能3. 安装ROS Noetic4. 配置环境变量5. 创建ROS节点(小球运动模拟)6. 配置RVIZ默认视图7. 创建启动脚本8. 运行可视化系统效果展示与交互技术解析ROS节点通…...