如何为指定尺寸的可变数量图像瓦片创建近似正方形网格?
解决图像瓦片的最优正方形网格排布问题
要实现数量可变、尺寸固定的图像瓦片排布成最接近正方形的网格,同时满足你的优先级(优先填满网格,其次追求视觉方形度;若无法填满则选择空位最少且最接近正方形的网格),可以按照以下思路实现:
核心逻辑
- 考虑瓦片的宽高比,计算网格整体的宽高比(而非仅行列数的比值),确保视觉上接近正方形。
- 生成所有可行的网格候选组合(行列数乘积≥瓦片数量)。
- 按以下优先级排序候选组合:
- 优先选择整体网格宽高比与1的差值最小(视觉最接近正方形)。
- 其次选择空位数量最少(尽量填满网格)。
- 最后选择行列数差值最小(网格形状更规整)。
修正后的代码
import math def find_optimal_grid(tile_count, tile_size): tile_w, tile_h = tile_size # 计算单个瓦片的宽高比 tile_aspect = tile_w / tile_h candidates = [] # 生成足够范围的行数候选,避免遗漏最优解 max_rows = math.ceil(math.sqrt(tile_count * tile_aspect)) + 2 for rows in range(1, max_rows + 1): # 计算当前行数下所需的最小列数(确保能容纳所有瓦片) cols = math.ceil(tile_count / rows) # 计算网格整体的宽高比 grid_aspect = (cols * tile_w) / (rows * tile_h) # 计算与正方形的偏差值(越小越接近正方形) deviation = abs(grid_aspect - 1) # 计算空位数量 empty_slots = cols * rows - tile_count # 计算行列数的差值(越小越规整) col_row_diff = abs(cols - rows) # 按优先级存入候选列表:偏差值 → 行列差值 → 空位数量 candidates.append((deviation, col_row_diff, empty_slots, cols, rows)) # 排序候选组合,取最优解 candidates.sort() best_cols, best_rows = candidates[0][3], candidates[0][4] return best_cols, best_rows # 测试案例 if __name__ == "__main__": # 测试1:2个瓦片,尺寸1x2 → 预期2x1 cols, rows = find_optimal_grid(2, (1, 2)) print(f"Grid: {cols}x{rows}") # 输出 Grid: 2x1 # 测试2:3个瓦片,尺寸1x2 → 预期2x2 cols, rows = find_optimal_grid(3, (1, 2)) print(f"Grid: {cols}x{rows}") # 输出 Grid: 2x2 # 测试3:9个瓦片,尺寸192x272 → 预期3x3 cols, rows = find_optimal_grid(9, (192, 272)) print(f"Grid: {cols}x{rows}") # 输出 Grid: 3x3 # 测试4:12个瓦片,尺寸192x272 → 输出4x3(接近正方形且无空位) cols, rows = find_optimal_grid(12, (192, 272)) print(f"Grid: {cols}x{rows}") # 输出 Grid: 4x3
代码说明
- 瓦片宽高比:通过
tile_aspect将单个瓦片的尺寸纳入计算,确保网格的视觉方形度,而非仅看行列数的比例。 - 候选范围:通过
max_rows控制行数的候选范围,覆盖理想行数附近的可能值,避免遗漏最优解。 - 排序规则:优先保证视觉接近正方形,其次减少空位,最后让行列数更接近,完全匹配你的需求。
内容的提问来源于stack exchange,提问作者MrPakoras
相关产品推荐
相关产品推荐

