2010-08-18 52 views
0

我有予讀入字節緩衝器(一個python字符串)原始數據文件。每個數據值表示代表圖像的2d陣列的8位像素。我知道這個圖像的寬度和高度。的Python:切片的2D陣列成瓦片

我想的圖像分割成圖塊,使得每個瓦片面積必須大於一個「瓦片分鐘區域」(例如1024個字節)不是「最大瓦區(例如2048字節)的較大和較小。只要面積約束得到滿足,這些瓷磚的高度和寬度就不一樣了,瓷磚也不一定都是相同的大小。另外,輸入數據的大小/長度不保證是2的冪。

請告訴我如果你使用圖像時,你應該使用PIL(Python圖像庫)在Python

問候

回答

1

這樣做的最佳方式。然後你只需加載圖像:

import Image 
i = Image.open(imagefile) 

和您可以輕鬆地裁剪任意大小的區域:

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

,所以你可以使用它。你也可以在Image對象和2d數組之間進行轉換,但我不太清楚它是如何完成的。我有幾個函數來轉換圖像之間的numpy陣列,我會看看我能否找到它們。

此外,你可能想看看PIL handbook找到文檔和食譜處理圖像。

+0

+1:使用PIL將使您的生活更容易使用瓷磚。如果你正在爲遊戲構建一個tile引擎,pygame也可能值得一看。 – ChristopheD 2010-08-18 09:42:53

+0

嗨,感謝您的建議,然而,分裂成瓦片的原因是這樣的圖像可以通過以太網鏈接發送小包和重建在另一端 – mikip 2010-08-18 09:49:30

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方面的條件是必要的這個工作)

有一些案件中,這不可能是與任何算法進行,例如在分離的4和8之間

瓦片的3×3的圖像假設數據由行存儲(如在例如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」)。

如果你需要存儲比原始像素數據更多,只需調整瓦的創建過程。