如何用循环实现图像3x3网格分割的坐标生成代码?
问题
我正在编写代码将一张图像沿3x3网格模式分割成多个小图像。目前我为每个“网格单元”显式分配四个角的坐标,以便用于PIL.Image.crop()方法。请问是否有简便的方式用循环实现这段代码?
原代码
from math import floor import matplotlib.pyplot as plt height = 75 width = 75 numRows = 5 numCols = 5 numVertLines = numRows+1 numHorLines = numCols+1 xcoords = [] ycoords = [] grid4coords = [] colIncrement = floor(width/numCols) rowIncrement = floor(height/numRows) print("Incremementing columns by", colIncrement, "pixels") print("Incrementing rows by", rowIncrement, "pixels") for i in range(0, (height+1), rowIncrement): #start from (0,0), increment by rowIncrement until reached xcoords.append(i) for j in range(0, (width+1), colIncrement): #start from (0,0), increment by colIncrement until reached right ycoords.append(j) print("xcoords:",xcoords) print("ycoords",ycoords) ################################## row 1 grid coords TL11 = [xcoords[0], ycoords[0]] TR11 = [xcoords[1], ycoords[0]] BL11 = [xcoords[0], ycoords[1]] BR11 = [xcoords[1], ycoords[1]] TL12 = [xcoords[1], ycoords[0]] TR12 = [xcoords[2], ycoords[0]] BL12 = [xcoords[1], ycoords[1]] BR12 = [xcoords[2], ycoords[1]] TL13 = [xcoords[2], ycoords[0]] TR13 = [xcoords[3], ycoords[0]] BL13 = [xcoords[2], ycoords[1]] BR13 = [xcoords[3], ycoords[1]] ################################ row 2 grid coords TL21 = [xcoords[0], ycoords[1]] TR21 = [xcoords[1], ycoords[1]] BL21 = [xcoords[0], ycoords[2]] BR21 = [xcoords[1], ycoords[2]] TL22 = [xcoords[1], ycoords[1]] TR22 = [xcoords[2], ycoords[1]] BL22 = [xcoords[1], ycoords[2]] BR22 = [xcoords[2], ycoords[2]] TL23 = [xcoords[2], ycoords[1]] TR23 = [xcoords[3], ycoords[1]] BL23 = [xcoords[2], ycoords[2]] BR23 = [xcoords[3], ycoords[2]] ################################ row 3 grid coords TL31 = [xcoords[0], ycoords[2]] TR31 = [xcoords[1], ycoords[2]] BL31 = [xcoords[0], ycoords[3]] BR31 = [xcoords[1], ycoords[3]] TL32 = [xcoords[1], ycoords[2]] TR32 = [xcoords[2], ycoords[2]] BL32 = [xcoords[1], ycoords[3]] BR32 = [xcoords[2], ycoords[3]] TL33 = [xcoords[2], ycoords[2]] TR33 = [xcoords[3], ycoords[2]] BL33 = [xcoords[2], ycoords[3]] BR33 = [xcoords[3], ycoords[3]]
解决方案
当然可以用嵌套循环简化代码,避免手动重复定义每个网格的坐标。而且PIL.Image.crop()实际需要的是一个元组(左, 上, 右, 下),对应你代码里的TL.x, TL.y, BR.x, BR.y,可以直接在循环中生成这个参数,或者按需求保存四个角的坐标。
优化代码示例
from math import floor import matplotlib.pyplot as plt height = 75 width = 75 numRows = 5 numCols = 5 colIncrement = floor(width / numCols) rowIncrement = floor(height / numRows) print("Incremementing columns by", colIncrement, "pixels") print("Incrementing rows by", rowIncrement, "pixels") # 用range直接生成坐标点列表,替代原循环追加 xcoords = list(range(0, height + 1, rowIncrement)) ycoords = list(range(0, width + 1, colIncrement)) print("xcoords:", xcoords) print("ycoords", ycoords) # 嵌套循环生成所有网格的坐标信息 grid_coords = [] # 遍历行索引(每个网格对应行区间[i, i+1]) for i in range(numRows): row_grids = [] # 遍历列索引(每个网格对应列区间[j, j+1]) for j in range(numCols): # 计算当前网格的四个角坐标 TL = [xcoords[i], ycoords[j]] TR = [xcoords[i+1], ycoords[j]] BL = [xcoords[i], ycoords[j+1]] BR = [xcoords[i+1], ycoords[j+1]] # 把坐标和crop所需参数存入字典,方便后续调用 row_grids.append({ 'TL': TL, 'TR': TR, 'BL': BL, 'BR': BR, 'crop_box': (TL[0], TL[1], BR[0], BR[1]) }) grid_coords.append(row_grids) # 打印验证前3行前3列的网格(和原代码输出对应) for row_idx in range(3): print(f"################################## row {row_idx+1} grid coords") for col_idx in range(3): grid = grid_coords[row_idx][col_idx] print(f"TL{row_idx+1}{col_idx+1} = {grid['TL']}") print(f"TR{row_idx+1}{col_idx+1} = {grid['TR']}") print(f"BL{row_idx+1}{col_idx+1} = {grid['BL']}") print(f"BR{row_idx+1}{col_idx+1} = {grid['BR']}")
代码说明
- 用
list(range(...))替代原代码中的循环追加,更简洁地生成坐标点列表。 - 外层循环遍历行起始索引
i,内层遍历列起始索引j,通过i与i+1、j与j+1的组合,直接获取当前网格的边界坐标,无需手动逐个定义。 - 将每个网格的四个角坐标和
crop_box参数存入字典,后续可以直接提取crop_box传给PIL.Image.crop(),也可以单独调用四个角的坐标。 - 最后打印的部分和原代码输出对应,用于验证循环生成的坐标是否正确。
内容的提问来源于stack exchange,提问作者nickreitz
相关产品推荐
相关产品推荐

