0

我有一个原始数据文件,我将其读入字节缓冲区(python 字符串)。每个数据值代表代表图像的 2d 数组的 8 位像素。我知道这张图片的宽度和高度。

我想将图像分割成图块,以便每个图块区域必须大于“最小图块区域”(例如 1024 字节)并小于“最大图块区域”(例如 2048 字节)。只要满足区域限制,这些瓦片的高度和宽度是任意的,并且瓦片不需要全部相同大小。此外,输入数据的大小/长度也不能保证是 2 的幂。

什么是在 python 中执行此操作的最佳方法

问候

4

2 回答 2

2

由于您没有说明“最佳”的含义,我认为它的意思是“使用较少杂乱的代码”。

假设您有以下数据:

from collections import Sequence
import operator

assert(type(MIN_AREA) is int)
assert(type(MAX_AREA) is int)
assert(type(width) is int)
assert(type(height) is int)
assert(instanceof(data, Sequence))
assert(len(data) == width * height)
assert(MAX_AREA >= 2 * MIN_AREA)

(MIN 和 MAX 区域的条件是此工作所必需的)

在某些情况下,任何算法都无法做到这一点,例如将 3x3 图像拆分为 4 到 8 之间的图块。

假设数据按行存储(例如在 PNM 规范中)。

def split_(seq, size):
    return [seq[i:i+size] for i in range(0,len(seq),size)]

tiles = list()
if width >= MIN_AREA:
    # each row is subdivided into multiple tiles
    tile_width = width / (width / MIN_AREA) # integral division
    rows = split_(data, width)
    row_tiles = [split_(row, tile_width) for row in rows]
    tiles = reduce(operator.add, row_tiles)
elif width < MIN_AREA:
    # each tile is composed of rows
    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
            # special case, we need to split vertically the last three rows
            # if the width was 3 too we have a problem but then if we are here
            # then MIN_AREA was 4, and MAX_AREA was 8, and the rows are >= 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

请记住,在最后一种情况下,您会得到两个或三个并排的瓷砖,而所有其他瓷砖都堆叠在它们上方(或下方,取决于行“0”的位置)。

如果您需要存储的不仅仅是原始像素数据,只需调整切片创建过程即可。

于 2010-08-18T10:53:38.620 回答
1

如果您正在处理图像,则应使用PIL(Python 图像库)。然后你只需加载图像:

import Image
i = Image.open(imagefile)

并且您可以轻松裁剪任意大小的区域:

box = (FirstCornerX, FirstCornerY, SecondCornerX, SecondCornerY)
region = im.crop(box)

所以你可以使用它。您还可以在 Image 对象和 2d 数组之间进行转换,但我不太记得它是如何完成的。我有几个函数可以在图像和numpy数组之间进行双向转换,我会看看是否能找到它们。

此外,您可能需要查看PIL 手册以查找处理图像的文档和配方。

于 2010-08-18T08:47:40.043 回答