diff --git a/main.py b/main.py index 5b0dd0e..1ec3300 100644 --- a/main.py +++ b/main.py @@ -13,6 +13,8 @@ def main(): editor = Editor(buffering=True) buildArea = editor.getBuildArea() + print(skeleton_mountain.lines) + blocks = { "wall": "blackstone", "roof": "blackstone", diff --git a/world_maker/Skeleton.py b/world_maker/Skeleton.py index 5d81f28..c62e846 100644 --- a/world_maker/Skeleton.py +++ b/world_maker/Skeleton.py @@ -1,12 +1,19 @@ -import numpy as np -#import skan -from skimage.morphology import skeletonize -from skan.csr import skeleton_to_csgraph -from collections import Counter -from PIL import Image, ImageDraw import random +from collections import Counter +from typing import List, Union + +import numpy as np +from PIL import Image, ImageDraw +from skan.csr import skeleton_to_csgraph +from skimage.morphology import skeletonize + +from gdpc import Editor +def handle_import_image(image: Union[str, Image]) -> Image: + if isinstance(image, str): + return Image.open(image) + return image class Skeleton: @@ -19,6 +26,19 @@ class Skeleton: if data is not None: self.set_skeleton(data) + def transpose_form_heightmap(heightmap: Union[str, Image], coordinates): + + heightmap = handle_import_image(heightmap).convert('L') + + editor = Editor() + xMin = (editor.getBuildArea().begin).x + zMin = (editor.getBuildArea().begin).z + + coordinates_final = [] + + return coordinates_final(coordinates[0] + xMin, heightmap.getpixel( + (coordinates[0], coordinates[2]))[0], coordinates[2] + zMin) + def set_skeleton(self, data: np.ndarray): print("[Skeleton] Start skeletonization...") binary_skeleton = skeletonize(data, method="lee") @@ -35,7 +55,8 @@ class Skeleton: for i in range(len(coordinates[0])): # print((coordinates[0][i], coordinates[1][i], coordinates[2][i])) - self.coordinates.append((coordinates[0][i], coordinates[1][i], coordinates[2][i])) + self.coordinates.append( + (coordinates[0][i], coordinates[1][i], coordinates[2][i])) print("[Skeleton] Skeletonization completed.") def find_next_elements(self, key: str) -> list: @@ -89,7 +110,8 @@ class Skeleton: return line def parse_graph(self, parse_orphan: bool = False): - print("[Skeleton] Start parsing the graph", ("with orphans" if parse_orphan else "") + "...") + print("[Skeleton] Start parsing the graph", + ("with orphans" if parse_orphan else "") + "...") for key, value in sorted( Counter(self.graph.row).items(), key=lambda kv: kv[1], reverse=True ): @@ -160,13 +182,15 @@ class Skeleton: # xzDistance = (max(buildRect.end[0], buildRect.begin[0]) - min(buildRect.end[0], buildRect.begin[0]), # max(buildRect.end[1], buildRect.begin[1]) - min(buildRect.end[1], buildRect.begin[1])) - heightmap = Image.open("./world_maker/data/heightmap.png").convert('RGB') + heightmap = Image.open( + "./world_maker/data/heightmap.png").convert('RGB') # roadsArea = Image.new("L", xzDistance, 0) # width, height = heightmap.size # Lines for i in range(len(self.lines)): - r, g, b = (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) + r, g, b = (random.randint(0, 255), random.randint( + 0, 255), random.randint(0, 255)) for j in range(len(self.lines[i])): z = self.coordinates[self.lines[i][j]][0] @@ -193,7 +217,8 @@ class Skeleton: for i in range(len(self.centers)): # print(self.coordinates[self.centers[i]]) heightmap.putpixel( - (int(self.coordinates[self.centers[i]][0]), int(self.coordinates[self.centers[i]][2])), + (int(self.coordinates[self.centers[i]][0]), int( + self.coordinates[self.centers[i]][2])), (255, 255, 0), ) @@ -228,7 +253,8 @@ class Skeleton: for j in range(len(self.lines[i])): z = self.coordinates[self.lines[i][j]][0] x = self.coordinates[self.lines[i][j]][2] - circle_coords = (z - radius, x - radius, z + radius, x + radius) + circle_coords = (z - radius, x - radius, + z + radius, x + radius) road_area_map_draw.ellipse(circle_coords, fill=255) # Centers diff --git a/world_maker/data/building.png b/world_maker/data/building.png index 75c058c..45c3949 100644 Binary files a/world_maker/data/building.png and b/world_maker/data/building.png differ diff --git a/world_maker/data/city_map.png b/world_maker/data/city_map.png index 6de4e5c..05c4c92 100644 Binary files a/world_maker/data/city_map.png and b/world_maker/data/city_map.png differ diff --git a/world_maker/data/district.png b/world_maker/data/district.png index bcf8455..d7657bd 100644 Binary files a/world_maker/data/district.png and b/world_maker/data/district.png differ diff --git a/world_maker/data/heightmap.png b/world_maker/data/heightmap.png index 0803705..8753fbb 100644 Binary files a/world_maker/data/heightmap.png and b/world_maker/data/heightmap.png differ diff --git a/world_maker/data/highwaymap.png b/world_maker/data/highwaymap.png index 011cb83..521ae0a 100644 Binary files a/world_maker/data/highwaymap.png and b/world_maker/data/highwaymap.png differ diff --git a/world_maker/data/mountain_map.png b/world_maker/data/mountain_map.png index 17e06aa..583e9d1 100644 Binary files a/world_maker/data/mountain_map.png and b/world_maker/data/mountain_map.png differ diff --git a/world_maker/data/roadmap.png b/world_maker/data/roadmap.png index f907fbf..c2b1605 100644 Binary files a/world_maker/data/roadmap.png and b/world_maker/data/roadmap.png differ diff --git a/world_maker/data/skeleton_highway.png b/world_maker/data/skeleton_highway.png index 98de997..60090f5 100644 Binary files a/world_maker/data/skeleton_highway.png and b/world_maker/data/skeleton_highway.png differ diff --git a/world_maker/data/skeleton_highway_area.png b/world_maker/data/skeleton_highway_area.png index 51a1476..377df9b 100644 Binary files a/world_maker/data/skeleton_highway_area.png and b/world_maker/data/skeleton_highway_area.png differ diff --git a/world_maker/data/skeleton_mountain.png b/world_maker/data/skeleton_mountain.png index 6168d74..eb5736f 100644 Binary files a/world_maker/data/skeleton_mountain.png and b/world_maker/data/skeleton_mountain.png differ diff --git a/world_maker/data/skeleton_mountain_area.png b/world_maker/data/skeleton_mountain_area.png index 8e1c2a5..6987edb 100644 Binary files a/world_maker/data/skeleton_mountain_area.png and b/world_maker/data/skeleton_mountain_area.png differ diff --git a/world_maker/data/smooth_sobel_watermap.png b/world_maker/data/smooth_sobel_watermap.png index c54ac73..e312ae2 100644 Binary files a/world_maker/data/smooth_sobel_watermap.png and b/world_maker/data/smooth_sobel_watermap.png differ diff --git a/world_maker/data/sobelmap.png b/world_maker/data/sobelmap.png index 2ac900f..c77ae37 100644 Binary files a/world_maker/data/sobelmap.png and b/world_maker/data/sobelmap.png differ diff --git a/world_maker/data/treemap.png b/world_maker/data/treemap.png index ccc4a60..05daf73 100644 Binary files a/world_maker/data/treemap.png and b/world_maker/data/treemap.png differ diff --git a/world_maker/data/watermap.png b/world_maker/data/watermap.png index 40ee940..f86194d 100644 Binary files a/world_maker/data/watermap.png and b/world_maker/data/watermap.png differ diff --git a/world_maker/data_analysis.py b/world_maker/data_analysis.py index 9793cb9..834d61e 100644 --- a/world_maker/data_analysis.py +++ b/world_maker/data_analysis.py @@ -68,29 +68,29 @@ def filter_sobel(image: Union[str, Image]) -> Image: for i in range(1, h - 1): for j in range(1, w - 1): horizontalGrad = ( - (horizontal[0, 0] * gray_img[i - 1, j - 1]) - + (horizontal[0, 1] * gray_img[i - 1, j]) - + (horizontal[0, 2] * gray_img[i - 1, j + 1]) - + (horizontal[1, 0] * gray_img[i, j - 1]) - + (horizontal[1, 1] * gray_img[i, j]) - + (horizontal[1, 2] * gray_img[i, j + 1]) - + (horizontal[2, 0] * gray_img[i + 1, j - 1]) - + (horizontal[2, 1] * gray_img[i + 1, j]) - + (horizontal[2, 2] * gray_img[i + 1, j + 1]) + (horizontal[0, 0] * gray_img[i - 1, j - 1]) + + (horizontal[0, 1] * gray_img[i - 1, j]) + + (horizontal[0, 2] * gray_img[i - 1, j + 1]) + + (horizontal[1, 0] * gray_img[i, j - 1]) + + (horizontal[1, 1] * gray_img[i, j]) + + (horizontal[1, 2] * gray_img[i, j + 1]) + + (horizontal[2, 0] * gray_img[i + 1, j - 1]) + + (horizontal[2, 1] * gray_img[i + 1, j]) + + (horizontal[2, 2] * gray_img[i + 1, j + 1]) ) newhorizontalImage[i - 1, j - 1] = abs(horizontalGrad) verticalGrad = ( - (vertical[0, 0] * gray_img[i - 1, j - 1]) - + (vertical[0, 1] * gray_img[i - 1, j]) - + (vertical[0, 2] * gray_img[i - 1, j + 1]) - + (vertical[1, 0] * gray_img[i, j - 1]) - + (vertical[1, 1] * gray_img[i, j]) - + (vertical[1, 2] * gray_img[i, j + 1]) - + (vertical[2, 0] * gray_img[i + 1, j - 1]) - + (vertical[2, 1] * gray_img[i + 1, j]) - + (vertical[2, 2] * gray_img[i + 1, j + 1]) + (vertical[0, 0] * gray_img[i - 1, j - 1]) + + (vertical[0, 1] * gray_img[i - 1, j]) + + (vertical[0, 2] * gray_img[i - 1, j + 1]) + + (vertical[1, 0] * gray_img[i, j - 1]) + + (vertical[1, 1] * gray_img[i, j]) + + (vertical[1, 2] * gray_img[i, j + 1]) + + (vertical[2, 0] * gray_img[i + 1, j - 1]) + + (vertical[2, 1] * gray_img[i + 1, j]) + + (vertical[2, 2] * gray_img[i + 1, j + 1]) ) newverticalImage[i - 1, j - 1] = abs(verticalGrad) @@ -184,12 +184,16 @@ def highway_map() -> Image: print("[Data Analysis] Generating highway map...") smooth_sobel = filter_smooth("./world_maker/data/sobelmap.png", 1) negative_smooth_sobel = filter_negative(smooth_sobel) - negative_smooth_sobel_water = subtract_map(negative_smooth_sobel, './world_maker/data/watermap.png') + negative_smooth_sobel_water = subtract_map( + negative_smooth_sobel, './world_maker/data/watermap.png') array_sobel_water = np.array(negative_smooth_sobel_water) - array_sobel_water = ndimage.binary_erosion(array_sobel_water, iterations=12) - array_sobel_water = ndimage.binary_dilation(array_sobel_water, iterations=5) + array_sobel_water = ndimage.binary_erosion( + array_sobel_water, iterations=12) + array_sobel_water = ndimage.binary_dilation( + array_sobel_water, iterations=5) array_sobel_water = filter_smooth_array(array_sobel_water, 5) - array_sobel_water = ndimage.binary_erosion(array_sobel_water, iterations=20) + array_sobel_water = ndimage.binary_erosion( + array_sobel_water, iterations=20) array_sobel_water = filter_smooth_array(array_sobel_water, 6) image = Image.fromarray(array_sobel_water) image_no_details = filter_remove_details(image, 15) @@ -240,7 +244,8 @@ def skeleton_mountain_map(image: Union[str, Image] = './world_maker/data/mountai def smooth_sobel_water() -> Image: watermap = handle_import_image("./world_maker/data/watermap.png") - watermap = filter_negative(filter_remove_details(filter_negative(watermap), 5)) + watermap = filter_negative( + filter_remove_details(filter_negative(watermap), 5)) sobel = handle_import_image("./world_maker/data/sobelmap.png") sobel = filter_remove_details(filter_smooth(sobel, 1), 2) group = group_map(watermap, sobel) @@ -257,14 +262,16 @@ def detect_mountain(image: Union[str, Image] = './world_maker/data/sobelmap.png' criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.2) k = 3 - _, labels, centers = cv2.kmeans(pixels, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS) + _, labels, centers = cv2.kmeans( + pixels, k, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS) centers = np.uint8(centers) segmented_image = centers[labels.flatten()] segmented_image = segmented_image.reshape(sobel.shape) mountain = segmented_image == segmented_image.max() - contours, _ = cv2.findContours(mountain.astype(np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + contours, _ = cv2.findContours(mountain.astype( + np.uint8), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) max_contour = max(contours, key=cv2.contourArea) M = cv2.moments(max_contour) @@ -278,7 +285,8 @@ def detect_mountain(image: Union[str, Image] = './world_maker/data/sobelmap.png' def rectangle_2D_to_3D(rectangle: list[tuple[tuple[int, int], tuple[int, int]]], height_min: int = 6, height_max: int = 10) \ -> list[tuple[tuple[int, int, int], tuple[int, int, int]]]: - image = handle_import_image('./world_maker/data/heightmap.png').convert('L') + image = handle_import_image( + './world_maker/data/heightmap.png').convert('L') new_rectangle = [] for rect in rectangle: start, end = rect @@ -286,7 +294,8 @@ def rectangle_2D_to_3D(rectangle: list[tuple[tuple[int, int], tuple[int, int]]], for x in range(start[0], end[0]): for y in range(start[1], end[1]): avg_height += image.getpixel((x, y)) - avg_height = int(avg_height / ((end[0] - start[0]) * (end[1] - start[1]))) + 1 + avg_height = int( + avg_height / ((end[0] - start[0]) * (end[1] - start[1]))) + 1 new_rectangle.append( ((start[0], avg_height, start[1]), (end[0], avg_height + randint(height_min, height_max), end[1]))) return new_rectangle