本文介绍如何使用 py3dbp 解决三维装箱问题。文章包含了从基本概念、实战案例到最终生成动态GIF可视化的流程及代码实现。
在物流、仓储和制造业中,如何将不同尺寸的物品高效地装入一个有限的容器(如卡车、集装箱或箱子)是一个经典且极具挑战性的问题。这就是著名的三维装箱问题(3D Bin Packing Problem, 3D-BPP)。解决好这个问题能显著节约运输成本、提高空间利用率。
Python社区为我们提供了一个强大而简洁的工具——py3dbp。本文将带您深入了解这个库,并通过一个实际案例,展示如何从零开始解决一个装箱问题,并最终创建一个直观的动态装箱过程GIF。

一、py3dbp 核心概念
在使用之前,我们先了解 py3dbp 的三个核心组件:
- Packer (装箱器):这是执行装箱算法的核心引擎。您可以把它想象成一个负责指挥的工人。
- Bin (箱子/容器):代表您要装入物品的容器。它有明确的属性,如名称、长、宽、高和最大承重。在我们的案例中,这就是一辆货车。
- Item (物品):代表需要被装入箱子的物品。它同样有名称、长、宽、高和重量等属性。
整个工作流程非常直观:创建箱子和一系列物品 -> 将它们都交给装箱器 -> 装箱器执行算法 -> 检视装箱结果。
二、实战案例:装载一辆货车
假设我们有一辆小型货车和一批不同规格的货物,我们的目标是尽可能多地将这些货物装入车厢。
- 货车车厢尺寸 (Bin): 587cm (长) x 235cm (宽) x 270cm (高)。
- 货物列表 (Items): 我们有多种不同尺寸和数量的箱子需要装载。
第1步:安装必要的库
您需要安装 py3dbp 用于核心计算,matplotlib 用于绘图,以及 imageio 用于将图片序列合成为GIF。
pip install py3dbp
pip install matplotlib
pip install imageio```
第2步:编写代码实现装箱
我们将遵循以下步骤编写代码:
- 导入库。
- 定义 Bin (货车) 和 Item (货物)。
- 创建 Packer 并将箱子和物品添加进去。
- 执行装箱算法并打印结果。
第3步:生成动态GIF可视化
静态的结果报告虽然清晰,但远不如一个动态图来得直观。我们将编写一个函数,它能一步步地展示每个箱子是如何被放入车厢的,并最终将这个过程保存为 GIF 文件。
这需要我们:
- 编写一个函数,能绘制出任意数量物品在箱子中的3D视图。
- 循环调用这个绘图函数,从1个物品开始,每次增加1个,并将每一帧保存为图片。
- 使用 imageio 将所有图片帧合成为一个GIF。
下面是包含完整代码(计算+可视化)的脚本:
import os
import imageio
import numpy as np
from py3dbp import Packer, Bin, Item
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
# --- Matplotlib 全局设置 ---
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False# 用来正常显示负号
def plot_packing_result(bin_obj, items_to_plot, title, save_path=None):
"""
绘制指定物品在箱子中的3D视图 (已修正数据类型问题)
"""
fig = plt.figure(figsize=(12, 10))
ax = fig.add_subplot(111, projection='3d')
# 为不同物品分配颜色
num_items = len(items_to_plot)
cmap = plt.get_cmap('viridis')
colors = [cmap(i) for i in np.linspace(0, 0.9, num_items)] if num_items > 0else []
color_map = {item.name: colors[i] for i, item in enumerate(items_to_plot)}
# 绘制每个已装箱的物品
for item in items_to_plot:
item_d = float(item.depth)
item_w = float(item.width)
item_h = float(item.height)
pos = item.position
x, y, z = float(pos[0]), float(pos[1]), float(pos[2])
vertices = [
(x, y, z), (x + item_d, y, z), (x + item_d, y + item_w, z), (x, y + item_w, z),
(x, y, z + item_h), (x + item_d, y, z + item_h), (x + item_d, y + item_w, z + item_h), (x, y + item_w, z + item_h)
]
faces = [
[vertices[0], vertices[1], vertices[2], vertices[3]], [vertices[4], vertices[5], vertices[6], vertices[7]],
[vertices[0], vertices[1], vertices[5], vertices[4]], [vertices[2], vertices[3], vertices[7], vertices[6]],
[vertices[1], vertices[2], vertices[6], vertices[5]], [vertices[0], vertices[3], vertices[7], vertices[4]]
]
poly3d = Poly3DCollection(faces, facecolors=color_map.get(item.name), linewidths=1, edgecolors='k', alpha=0.85)
ax.add_collection3d(poly3d)
ax.set_xlim(0, float(bin_obj.depth))
ax.set_ylim(0, float(bin_obj.width))
ax.set_zlim(0, float(bin_obj.height))
ax.set_xlabel('长度 (X轴 / depth)')
ax.set_ylabel('宽度 (Y轴 / width)')
ax.set_zlabel('高度 (Z轴 / height)')
ax.view_init(elev=20, azim=-45)
plt.title(title, fontsize=16)
if save_path:
plt.savefig(save_path)
plt.close(fig)
else:
plt.show()
def create_animated_gif(bin_obj, output_filename='packing_animation.gif'):
"""
创建并保存装箱过程的GIF动画
"""
packed_items = bin_obj.items
ifnot packed_items:
print("分析:没有成功装入任何物品,无法创建GIF。请检查物品尺寸是否相对于容器过大。")
return
frame_folder = "gif_frames"
ifnot os.path.exists(frame_folder):
os.makedirs(frame_folder)
filenames = []
print(f"步骤1:为GIF生成 {len(packed_items) + 1} 帧图片...")
for i in range(len(packed_items) + 1):
frame_path = os.path.join(frame_folder, f"frame_{i:03d}.png")
if i == 0:
plot_packing_result(bin_obj, [], f"第 {i}/{len(packed_items)} 步: 空货车", save_path=frame_path)
else:
item_being_packed = packed_items[i-1]
plot_packing_result(bin_obj, packed_items[:i], f"第 {i}/{len(packed_items)} 步: 装入 {item_being_packed.name}", save_path=frame_path)
filenames.append(frame_path)
print("步骤2:将所有图片帧合成为GIF文件...")
with imageio.get_writer(output_filename, mode='I', duration=3.5) as writer:
for filename in filenames:
image = imageio.imread(filename)
writer.append_data(image)
print(f"成功!GIF动画已保存至: {output_filename}")
for filename in filenames:
os.remove(filename)
os.rmdir(frame_folder)
# ================== 主程序入口 ==================
if __name__ == '__main__':
packer = Packer()
# 按照 (名称, 宽, 高, 深, ...) 的顺序创建 Bin
truck = Bin('货车', 235, 270, 587, 1000.0)
packer.add_bin(truck)
# 按照 (名称, 宽, 高, 深, ...) 的顺序创建 Item
packer.add_item(Item('大号箱子-1', 100, 100, 100, 15.0))
packer.add_item(Item('大号箱子-2', 100, 100, 100, 15.0))
packer.add_item(Item('中号箱子-1', 70, 60, 80, 10.0))
packer.add_item(Item('中号箱子-2', 70, 60, 80, 10.0))
packer.add_item(Item('中号箱子-3', 70, 60, 80, 10.0))
packer.add_item(Item('小号箱子-1', 40, 30, 50, 5.0))
packer.add_item(Item('小号箱子-2', 40, 30, 50, 5.0))
packer.add_item(Item('小号箱子-3', 40, 30, 50, 5.0))
packer.add_item(Item('小号箱子-4', 40, 30, 50, 5.0))
packer.add_item(Item('扁平箱子-1', 150, 10, 120, 8.0))
packer.add_item(Item('扁平箱子-2', 150, 10, 120, 8.0))
packer.add_item(Item('瘦高箱子-1', 40, 200, 40, 12.0))
packer.add_item(Item('瘦高箱子-2', 40, 200, 40, 12.0))
packer.add_item(Item('超大号箱子', 300, 300, 300, 100.0))
print("开始执行装箱算法...")
packer.pack(bigger_first=True, distribute_items=False)
packed_bin = packer.bins[0]
print(f"\n计算完毕!")
print(f"已装入物品数量: {len(packed_bin.items)}")
print(f"未装入物品数量: {len(packed_bin.unfitted_items)}")
create_animated_gif(packed_bin, 'packing_animation.gif')
三、运行与结果
将以上代码保存为 .py 文件并运行。程序会首先在控制台输出装箱结果,然后开始生成GIF的每一帧。完成后,您会在代码文件所在的目录下找到一个名为 packing_animation.gif 的文件。
这个GIF文件会像下面这样,动态地展示每一个箱子被依次放入货车的过程。
AI大模型学习福利
作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。
一、全套AGI大模型学习路线
AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获取
二、640套AI大模型报告合集
这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获
三、AI大模型经典PDF籍
随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获
四、AI大模型商业化落地方案

因篇幅有限,仅展示部分资料,需要点击文章最下方名片即可前往获
作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量

5434

被折叠的 条评论
为什么被折叠?



