Python 二叉树算法解决二维装箱问题 (2d bin-packing problem)

本文主要是介绍Python 二叉树算法解决二维装箱问题 (2d bin-packing problem),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

二维装箱问题应用领域比较多,游戏开发中主要应用于贴图合并。

最近在调研图集打包工具的算法实现,看到一种实现方式是通过二叉树算法,比较朴素且有效,则立刻写用例简单测试验证下。

测试结果:(打包后的图用随机纯色色块代替)
在这里插入图片描述

测试代码如下:

from Packer import Packer
from PIL import Image
import cv2
import os
import randomCanvas_Width = 1024
Canvas_Height = 1024
CanvasPixelColor = [255, 255, 255]
ImgPath = "imgLib"# 获取path下的所有图片对象
def getImgList(path):imagelist = []for parent, dirnames, filenames in os.walk(path):for filename in filenames:if filename.lower().endswith(('.png')):img = cv2.imread(os.path.join(parent, filename), cv2.IMREAD_UNCHANGED)imagelist.append(img)print(filename)return imagelist# 新建一张图
def newImg(width, height, r, g, b):img = Image.new('RGB', (width, height))for i in range(0, width):for j in range(0, height):img.putpixel((i, j), (r, g, b))img.save('sqr.png')return img# 在canvas上绘制纯色block
def drawBlockOnCanvas(canvasImg, x, y, w, h, r, g, b):for i in range(x, x + w):for j in range(y, y + h):canvasImg.putpixel((i, j), (r, g, b))return canvasImg# 新建画布
def drawCanvas():wallpaper = newImg(Canvas_Width, Canvas_Height, CanvasPixelColor[0], CanvasPixelColor[1], CanvasPixelColor[2])return wallpaper# 主函数
def main():# 新建一张 1024 * 1024 的画布canvas = drawCanvas()# 初始化Packer对象packer = Packer(Canvas_Width, Canvas_Height)# 读取图片sizeblocks = []rawImgList = getImgList(ImgPath)for img in rawImgList:print(img.shape)w, h, _ = img.shapeblocks.append({'w' : w, 'h' : h})# sort blocks by heightdef get_height(block):return block['h']blocks.sort(key = get_height, reverse=True)# 打包packer.fit(blocks)print("图的总数量" + str(len(blocks)))drawedCount = 0for block in blocks:print(str(block['w']) + "x" + str(block['h']))for block in blocks:print(str(block['w']) + "x" + str(block['h']))if('fit' in block):fit = block['fit']r = random.randint(0, 255)g = random.randint(0, 255)b = random.randint(0, 255)# print(block)drawBlockOnCanvas(canvas, fit['x'], fit['y'], block['w'], block['h'], r, g, b)drawedCount += 1## debug mode to show drew Img one by one# npImg = np.array(canvas)# cv2.imshow("test", npImg)# cv2.waitKey(0)# cv2.destroyAllWindows()else:print("[Error] No Fit in Block -- ")print("DrawedCount : " + str(drawedCount))canvas.save('sqr.png')canvas.show()main()

Packer类的实现:

class Packer:def __init__(self, w, h):self.root = {'x' : 0, 'y' : 0, 'w' : w, 'h' : h, 'used' : False}def fit(self, blocks):for block in blocks:node = self.findNode(self.root, block['w'], block['h'])if node:block['fit'] = self.splitNode(node, block['w'], block['h'])def findNode(self, root, w, h):if(root['used']):return self.findNode(root['right'], w, h) or self.findNode(root['down'], w, h)elif((w <= root['w']) and (h <= root['h'])):return rootelse:return Nonedef splitNode(self, node, w, h):node['used'] = Truenode['down']    = {'x' : node['x'],     'y' : node['y'] + h,    'w' : node['w'] ,        'h' : node['h'] - h,    'used' : False}node['right']   = {'x' : node['x'] + w, 'y' : node['y'],        'w' : node['w'] - w,     'h' : h,        'used' : False}return node

测试验证结论:
算法不足之处在于block中的空白区域可能没有得到很好的利用,可以后续通过递归遍历blocks中"被浪费"的区域,将区域尽可能的合并后 重新利用。

这篇关于Python 二叉树算法解决二维装箱问题 (2d bin-packing problem)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/267558

相关文章

使用Python实现矢量路径的压缩、解压与可视化

《使用Python实现矢量路径的压缩、解压与可视化》在图形设计和Web开发中,矢量路径数据的高效存储与传输至关重要,本文将通过一个Python示例,展示如何将复杂的矢量路径命令序列压缩为JSON格式,... 目录引言核心功能概述1. 路径命令解析2. 路径数据压缩3. 路径数据解压4. 可视化代码实现详解1

python获取网页表格的多种方法汇总

《python获取网页表格的多种方法汇总》我们在网页上看到很多的表格,如果要获取里面的数据或者转化成其他格式,就需要将表格获取下来并进行整理,在Python中,获取网页表格的方法有多种,下面就跟随小编... 目录1. 使用Pandas的read_html2. 使用BeautifulSoup和pandas3.

Python装饰器之类装饰器详解

《Python装饰器之类装饰器详解》本文将详细介绍Python中类装饰器的概念、使用方法以及应用场景,并通过一个综合详细的例子展示如何使用类装饰器,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录1. 引言2. 装饰器的基本概念2.1. 函数装饰器复习2.2 类装饰器的定义和使用3. 类装饰

Python 交互式可视化的利器Bokeh的使用

《Python交互式可视化的利器Bokeh的使用》Bokeh是一个专注于Web端交互式数据可视化的Python库,本文主要介绍了Python交互式可视化的利器Bokeh的使用,具有一定的参考价值,感... 目录1. Bokeh 简介1.1 为什么选择 Bokeh1.2 安装与环境配置2. Bokeh 基础2

Spring 中的循环引用问题解决方法

《Spring中的循环引用问题解决方法》:本文主要介绍Spring中的循环引用问题解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录什么是循环引用?循环依赖三级缓存解决循环依赖二级缓存三级缓存本章来聊聊Spring 中的循环引用问题该如何解决。这里聊

Spring Boot中JSON数值溢出问题从报错到优雅解决办法

《SpringBoot中JSON数值溢出问题从报错到优雅解决办法》:本文主要介绍SpringBoot中JSON数值溢出问题从报错到优雅的解决办法,通过修改字段类型为Long、添加全局异常处理和... 目录一、问题背景:为什么我的接口突然报错了?二、为什么会发生这个错误?1. Java 数据类型的“容量”限制

如何使用 Python 读取 Excel 数据

《如何使用Python读取Excel数据》:本文主要介绍使用Python读取Excel数据的详细教程,通过pandas和openpyxl,你可以轻松读取Excel文件,并进行各种数据处理操... 目录使用 python 读取 Excel 数据的详细教程1. 安装必要的依赖2. 读取 Excel 文件3. 读

Python的time模块一些常用功能(各种与时间相关的函数)

《Python的time模块一些常用功能(各种与时间相关的函数)》Python的time模块提供了各种与时间相关的函数,包括获取当前时间、处理时间间隔、执行时间测量等,:本文主要介绍Python的... 目录1. 获取当前时间2. 时间格式化3. 延时执行4. 时间戳运算5. 计算代码执行时间6. 转换为指

利用Python调试串口的示例代码

《利用Python调试串口的示例代码》在嵌入式开发、物联网设备调试过程中,串口通信是最基础的调试手段本文将带你用Python+ttkbootstrap打造一款高颜值、多功能的串口调试助手,需要的可以了... 目录概述:为什么需要专业的串口调试工具项目架构设计1.1 技术栈选型1.2 关键类说明1.3 线程模

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图