- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
火柴人(Stick Figure)是一种极简风格的图形,通常由简单的线段和圆圈组成,却能生动地表达人物的姿态和动作。火柴人不仅广泛应用于动画、漫画和涂鸦中,还可以作为图形学、人工智能等领域的教学和研究工具。本文旨在介绍如何使用Python实现火柴人的设计与绘制,通过编程的方式,让读者了解火柴人背后的基本原理和实现方法.
在开始实现火柴人之前,你需要确保已经安装了Python环境,并且熟悉基本的Python编程知识。此外,为了绘制图形,我们将使用matplotlib库,这是一个强大的绘图库,适用于生成各种静态、动态和交互式的图表.
你可以通过以下命令安装matplotlib:
bash复制代码
pip install matplotlib
火柴人的绘制主要依赖于几何图形的绘制和变换。具体来说,我们需要:
(1)定义关节:火柴人的关节包括头部、肩膀、肘部、手腕、臀部、膝盖和脚踝等。这些关节可以看作二维或三维空间中的点.
(2)绘制线段:根据关节的位置,绘制连接关节的线段,这些线段构成了火柴人的骨骼.
(3)添加圆形:在头部等关节处添加圆形,以表示关节.
(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()
(1)火柴人看起来扭曲或比例不对:这通常是由于关节位置定义不合理或线段连接错误导致的。检查关节位置和连接顺序是否正确.
(2)图形显示不全:确保设置ax.set_aspect('equal'),使得图形按等比例显示.
(3)如何添加动画效果:可以使用matplotlib的FuncAnimation类,通过不断更新关节位置来实现动画效果.
通过上述步骤,你已经成功绘制了一个简单的火柴人。接下来,我们可以尝试更复杂的姿势和动画效果。例如,通过改变关节位置,实现火柴人的跳跃、行走等动作.
下面是一个简单的动画示例,展示火柴人从左到右移动的过程:
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()
以下是完整的代码示例,包括所有步骤和注释:
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实现火柴人的设计与实现的文章就讲到这里了,如果你想了解更多关于Python实现火柴人的设计与实现的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
背景: 我最近一直在使用 JPA,我为相当大的关系数据库项目生成持久层的轻松程度给我留下了深刻的印象。 我们公司使用大量非 SQL 数据库,特别是面向列的数据库。我对可能对这些数据库使用 JPA 有一
我已经在我的 maven pom 中添加了这些构建配置,因为我希望将 Apache Solr 依赖项与 Jar 捆绑在一起。否则我得到了 SolarServerException: ClassNotF
interface ITurtle { void Fight(); void EatPizza(); } interface ILeonardo : ITurtle {
我希望可用于 Java 的对象/关系映射 (ORM) 工具之一能够满足这些要求: 使用 JPA 或 native SQL 查询获取大量行并将其作为实体对象返回。 允许在行(实体)中进行迭代,并在对当前
好像没有,因为我有实现From for 的代码, 我可以转换 A到 B与 .into() , 但同样的事情不适用于 Vec .into()一个Vec . 要么我搞砸了阻止实现派生的事情,要么这不应该发
在 C# 中,如果 A 实现 IX 并且 B 继承自 A ,是否必然遵循 B 实现 IX?如果是,是因为 LSP 吗?之间有什么区别吗: 1. Interface IX; Class A : IX;
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在阅读标准haskell库的(^)的实现代码: (^) :: (Num a, Integral b) => a -> b -> a x0 ^ y0 | y0 a -> b ->a expo x0
我将把国际象棋游戏表示为 C++ 结构。我认为,最好的选择是树结构(因为在每个深度我们都有几个可能的移动)。 这是一个好的方法吗? struct TreeElement{ SomeMoveType
我正在为用户名数据库实现字符串匹配算法。我的方法采用现有的用户名数据库和用户想要的新用户名,然后检查用户名是否已被占用。如果采用该方法,则该方法应该返回带有数据库中未采用的数字的用户名。 例子: “贾
我正在尝试实现 Breadth-first search algorithm , 为了找到两个顶点之间的最短距离。我开发了一个 Queue 对象来保存和检索对象,并且我有一个二维数组来保存两个给定顶点
我目前正在 ika 中开发我的 Python 游戏,它使用 python 2.5 我决定为 AI 使用 A* 寻路。然而,我发现它对我的需要来说太慢了(3-4 个敌人可能会落后于游戏,但我想供应 4-
我正在寻找 Kademlia 的开源实现C/C++ 中的分布式哈希表。它必须是轻量级和跨平台的(win/linux/mac)。 它必须能够将信息发布到 DHT 并检索它。 最佳答案 OpenDHT是
我在一本书中读到这一行:-“当我们要求 C++ 实现运行程序时,它会通过调用此函数来实现。” 而且我想知道“C++ 实现”是什么意思或具体是什么。帮忙!? 最佳答案 “C++ 实现”是指编译器加上链接
我正在尝试使用分支定界的 C++ 实现这个背包问题。此网站上有一个 Java 版本:Implementing branch and bound for knapsack 我试图让我的 C++ 版本打印
在很多情况下,我需要在 C# 中访问合适的哈希算法,从重写 GetHashCode 到对数据执行快速比较/查找。 我发现 FNV 哈希是一种非常简单/好/快速的哈希算法。但是,我从未见过 C# 实现的
目录 LRU缓存替换策略 核心思想 不适用场景 算法基本实现 算法优化
1. 绪论 在前面文章中提到 空间直角坐标系相互转换 ,测绘坐标转换时,一般涉及到的情况是:两个直角坐标系的小角度转换。这个就是我们经常在测绘数据处理中,WGS-84坐标系、54北京坐标系
在软件开发过程中,有时候我们需要定时地检查数据库中的数据,并在发现新增数据时触发一个动作。为了实现这个需求,我们在 .Net 7 下进行一次简单的演示. PeriodicTimer .
二分查找 二分查找算法,说白了就是在有序的数组里面给予一个存在数组里面的值key,然后将其先和数组中间的比较,如果key大于中间值,进行下一次mid后面的比较,直到找到相等的,就可以得到它的位置。
我是一名优秀的程序员,十分优秀!