要将一个2D数组切分成多个块,可以考虑使用以下几种方法,具体取决于如何定义块的划分规则和需求。如果你希望将2D数组均匀地切分成固定大小的小块,可以使用简单的循环和切片操作。
1、问题背景
Python 中, 如果有一个 raw 数据文件,将其读入到字节缓冲区(python 字符串),其中每一个数据值代表一个2d 数组中 8 位像素。已知此图片的宽度和高度,想将图片切分成多个块,并且每一个块的面积必须大于最小块面积(如:1024 字节),小于最大块面积(如:2048 字节)。这些块的高度和宽度是任意的,只要满足面积约束即可,并且块的大小不必相同。此外,输入数据的长度也不一定是2的幂。
2、解决方案
方法一:
为了代码尽量简洁,可以将数据存储为按行存储的行。
import collections
import operator
def split_(seq, size):
return [seq[i:i+size] for i in range(0,len(seq),size)]
def split_image(data, width, height, MIN_AREA, MAX_AREA):
tiles = list()
if width >= MIN_AREA:
# 每行可以细分为多个块
tile_width = width / (width / MIN_AREA) # 整数除法
rows = split_(data, width)
row_tiles = [split_(row, tile_width) for row in rows]
tiles = reduce(operator.add, row_tiles)
elif width < MIN_AREA:
# 每个块由多行组成
min_tile_height = int(MIN_AREA / width) + 1
tile_height = height / (height / min_tile_height)
tile_size = tile_height * width
tiles = split_(data, tile_size)
if len(tiles[-1]) < MIN_AREA:
if (tile_height > 2):
tiles[-2] += tiles[-1]
del tiles[-1]
else: # tile_height == 2, the case 1 don't pass here
# 特殊情况,我们需要垂直分割最后三行
# 如果宽度也是3,那么我们就遇到了问题,但如果我们在这里
# 那么MIN_AREA为4,MAX_AREA为8,行数大于等于5
if width > 3:
last_three_rows = split_(tiles[-2] + tiles[-1], width)
tiles[-2] = reduce(operator.add,[row[:width/2] for row in last_three_rows])
tiles[-1] = reduce(operator.add,[row[width/2:] for row in last_three_rows])
else: # width = 3 and MIN_AREA = 4
last_five_rows = reduce(operator.add, tiles[-3:])
three_columns = [last_five_rows[i::3] for i in range(3)]
tiles[-3:] = three_columns
return tiles
方法二:
如果是在处理图片,可以使用 PIL(Python Imaging Library)。
import Image
def split_image(imagefile, MIN_AREA, MAX_AREA):
i = Image.open(imagefile)
width, height = i.size
data = list(i.getdata())
tiles = list()
if width >= MIN_AREA:
tile_width = width / (width / MIN_AREA) # 整数除法
for y in range(0, height, tile_width):
for x in range(0, width, tile_width):
box = (x, y, x + tile_width, y + tile_width)
region = i.crop(box)
tiles.append(list(region.getdata()))
elif width < MIN_AREA:
min_tile_height = int(MIN_AREA / width) + 1
tile_height = height / (height / min_tile_height)
tile_size = tile_height * width
for y in range(0, height, tile_height):
for x in range(0, width):
box = (x, y, x + width, y + tile_height)
region = i.crop(box)
tiles.append(list(region.getdata()))
return tiles
函数 split_image
将图像切成块,并将每个块的数据存储到一个列表中。然后可以对每个块单独处理。
有时候需要根据块的形状或大小来划分数组,这可能需要使用图像处理库或者几何算法来检测并划分块。这些示例展示了如何根据不同的需求将2D数组切分成多个块。具体选择哪种方法取决于我们的应用场景和数据结构。