我希望在 python 中輸出一個串列串列,其中每個串列都包含單個顏色的每個形狀的像素坐標。
即看這張圖片: 128x128 png
我已將其轉換為 RGB 值的 2D 網格。
我希望創建一個串列串列,每個串列都包含紫色“形狀”(正方形、矩形等)的像素坐標。“形狀”的標準只是至少兩個相同顏色的像素彼此相鄰(僅上、下、左、右)。
在我的嘗試中:
# returns a list of instances of a tile which are all adjacent to each other
# i.e. finds a window's individual tiles and returns them as a list
def coagulateTiles(self, tileType, startX, startY, existingComponents = [], foundTiles = None):
# if the pixel is not the right tile OR if it has already been part of another search
if not self.getTileType(startX, startY) == tileType or not (startX, startY) in foundTiles:
return existingComponents
else:
existingComponents.append((startX, startY))
# a dictionary of the adjacent tiles {"north" = (x, y), etc...}
adjacentCoordDict = self.getAdjacentCoords(startX, startY)
for adjacent in adjacentCoordDict:
if adjacent == tileType:
x, y = adjacentCoordDict[adjacent][0], adjacentCoordDict[adjacent][1]
existingComponents.append(self.coagulateTiles(tileType, x, y, existingComponents))
return existingComponents
def tileSearch(self, tile):
items = []
foundTiles = []
for x in range(self.getSizeX()):
for y in range(self.getSizeY()):
if self.getTileType(x, y) == tile:
if tile in self.getAdjacentTiles(x, y).values():
foundTiles.append((x, y))
listOfTileComponents = self.coagulateTiles(tile, x, y, foundTiles = foundTiles)
items.append(listOfTileComponents)
return items
我最終找到了所有這些像素,但是輸出的串列將所有像素放在一個串列中,而不是將“形狀”分成單獨的子串列。
它回傳類似[[(1, 1), (2, 1), (3, 1), (1, 2), (1, 3)]]而不是[[(1, 1), (2, 1)], [(3, 1), (1, 2), (1, 3)]]
我的直覺是,在我的嘗試中當然存在一個簡單的邏輯錯誤,但我似乎無法找到可以指定子串列創建的位置以使其作業。
有任何想法嗎?
這是將上面的影像轉換為我正在使用的網格所需的代碼:
import numpy as np
from PIL import Image
# (x=0,y=0) of the grid is in the top left corner
class Grid():
def __init__(self, sizeX, sizeY):
self.sizeX = sizeX
self.sizeY = sizeY
global rgbMap
rgbMap = {
"wall":( 0, 0, 0),
"background": (255,255,255),
"closet": (192,192,224),
"bathroom": (192,255,255), # /washroom
"dining room": (224,255,192), # livingroom/kitchen/dining room
"bedroom": (255,224,128),
"hall": (255,160, 96),
"balcony": (255,224,224),
"opening": (255, 60,128) # door & window
}
global tileMap
tileMap = {v: k for k, v in rgbMap.items()}
# create a 2d numpy array of the given size
self.grid = self.createGrid(sizeX, sizeY)
def createGrid(self, sizeX, sizeY):
return np.empty((sizeX, sizeY), dtype=tuple)
# function to input a colour into the 2d grid
def populate(self, locationX, locationY, rgbTuple):
self.grid[locationX,locationY] = rgbTuple
def get(self):
return self.grid
def getSizeX(self):
return self.sizeX
def getSizeY(self):
return self.sizeY
class MapGenerator:
def __init__(self, finalSize = 128):
# resize the image to be axa size where a = 128
self.workingGridSize = 512
self.finalSize = finalSize
def createFromSaveFile(self):
self.createGrid(fromMemory=True)
print("populating the grid with data")
self.populateGrid(self.finalSize, self.grid, self.floorplan)
self.floorplan.close()
def createGrid(self, fromMemory = False):
if fromMemory == True:
self.floorplan = Image.open('saved.png')
self.grid = Grid(self.finalSize, self.finalSize)
else:
self.floorplan = Image.open('result.png')
self.grid = Grid(self.workingGridSize, self.workingGridSize)
def populateGrid(self, gridsize, givenGrid, image):
for x in range(0, gridsize):
for y in range(0, gridsize):
# print(map.getpixel((x,y)))
givenGrid.populate(x, y, image.getpixel((x,y)))
if __name__ == "__main__":
newMap = MapGenerator()
# newMap.create()
newMap.createFromSaveFile()
openings = newMap.grid.tileSearch("opening")
print(openings)
uj5u.com熱心網友回復:
我想出了一個可行的 DFS 遞回解決方案:
def tileSearch(self, tile):
"""returns a 2d list containing all the pixels
of each shape of a searched tile type as a sublist
a shape is defined as at least two pixels
of the same colour touching each other with Four-Pixel Connectivity
(up, down, left, right)
Args:
tile (string): the tile to search as a string (see rgbMap dict for tile list)
Returns:
list: a 2D list containing each shape as a sublist of its pixels
"""
searchGrid = copy.deepcopy(self)
resultList = list()
for x in range(searchGrid.getSizeX()):
for y in range(searchGrid.getSizeY()):
if searchGrid.getTileType(x, y) == tile:
adjacentTiles = list(searchGrid.getAdjacentTiles(x, y).values())
if tile in adjacentTiles:
shapeList = list()
searchGrid.coagulateShape(tile, x, y, shapeList)
resultList.append(shapeList)
return resultList
# returns a list of instances of a tile which are all adjacent to each other
# i.e. finds a window's individual tiles and returns them as a list
def coagulateShape(self, tile, x, y, shapeList = []):
""" Performs a recursive Depth First Search
returns a list of coordinates of a tile which are all adjacent to each other
through Four Pixel connectivity (up, down, left, right)
i.e. finds a shape's individual tiles and returns them as a list
Args:
tile (string): the tile to search for (see rgbMap dict for tile list)
x (int): the x coordinate of the starting pixel
y (int): the y coordinate of the starting pixel
shapeList (list): the list that the shape's coordinates will be appended to recursively
"""
# base case
if not self.getTileType(x, y) == tile:
return
# recursive case
self.populate(x, y, (0, 0, 0, 0))
shapeList.append((x, y))
adjacentPixels = list(self.getAdjacentCoords(x, y).values())
for pixel in adjacentPixels:
self.coagulateShape(tile, pixel[0], pixel[1], shapeList)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/445491.html
下一篇:java中的多執行緒
