Fixed layer resolution

This commit is contained in:
Pax1601 2024-03-06 16:42:58 +01:00
parent c99b5ed19f
commit f2d4f0b0ca
4 changed files with 130 additions and 36 deletions

View File

@ -0,0 +1,3 @@
Syria
Test
Caucasus

View File

@ -5,12 +5,20 @@
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"name": "Main",
"type": "python",
"request": "launch",
"program": "main.py",
"console": "integratedTerminal",
"args": ["./configs/Test/MediumResolution.yml"]
},
{
"name": "Convert",
"type": "python",
"request": "launch",
"program": "convert_to_jpg.py",
"console": "integratedTerminal",
"args": ["./Syria/tiles", "./Syria/jpg"]
}
]
}

View File

@ -0,0 +1,98 @@
import sys
import os
import numpy
from PIL import Image
from concurrent import futures
from os import listdir
from os.path import isfile, isdir, join
# global counters
fut_counter = 0
tot_futs = 0
def printProgressBar(iteration, total, prefix = '', suffix = '', decimals = 1, length = 100, fill = '', printEnd = "\r"):
percent = ("{0:." + str(decimals) + "f}").format(100 * (iteration / float(total)))
filledLength = int(length * iteration // total)
bar = fill * filledLength + '-' * (length - filledLength)
print(f'\r{prefix} |{bar}| {percent}% {suffix}', end = printEnd)
# Print New Line on Complete
if iteration == total:
print()
def done_callback(fut):
global fut_counter, tot_futs
fut_counter += 1
printProgressBar(fut_counter, tot_futs)
def remove_black_areas(im):
data = numpy.array(im)
red, green, blue = data.T
# If present, remove any "black" areas
background_areas = (red < 10) & (blue < 10) & (green < 10)
data[..., :][background_areas.T] = (221, 221, 221)
return Image.fromarray(data)
def convert_tiles(source, dest, tile):
zoom = tile[0]
X = tile[1]
Y = tile[2]
if not os.path.exists(os.path.join(dest, str(zoom))):
try:
os.mkdir(os.path.join(dest, str(zoom)))
except FileExistsError:
# Ignore this error, it means one other thread has already created the folder
pass
except Exception as e:
raise e
if not os.path.exists(os.path.join(dest, str(zoom), str(X))):
try:
os.mkdir(os.path.join(dest, str(zoom), str(X)))
except FileExistsError:
# Ignore this error, it means one other thread has already created the folder
pass
except Exception as e:
raise e
remove_black_areas(Image.open(os.path.join(source, str(zoom), str(X), f"{Y}.png")).convert('RGB')).save(os.path.join(dest, str(zoom), str(X), f"{Y}.jpg"))
if len(sys.argv) < 3:
print("Please provide a source and a destination folder")
else:
source = sys.argv[1]
dest = sys.argv[2]
if not os.path.exists(dest):
try:
os.mkdir(dest)
except FileExistsError:
# Ignore this error, it means one other thread has already created the folder
pass
except Exception as e:
raise e
print(f"Listing source tiles...")
existing_tiles = []
zooms = [int(f) for f in listdir(source) if isdir(join(source, f))]
for zoom in zooms:
Xs = [int(f) for f in listdir(join(source, str(zoom))) if isdir(join(source, str(zoom), f))]
for X in Xs:
Ys = [int(f.removesuffix(".png")) for f in listdir(os.path.join(source, str(zoom), str(X))) if isfile(join(source, str(zoom), str(X), f))]
for Y in Ys:
existing_tiles.append((zoom, X, Y))
print(f"{len(existing_tiles)} tiles will be converted")
# Merge the tiles with parallel thread execution
with futures.ThreadPoolExecutor() as executor:
print(f"Converting tiles to jpg...")
print(f"Initializing exectuion pool")
futs = [executor.submit(convert_tiles, source, dest, tile) for tile in existing_tiles]
tot_futs = len(futs)
fut_counter = 0
[fut.add_done_callback(done_callback) for fut in futs]
[fut.result() for fut in futures.as_completed(futs)]

View File

@ -86,10 +86,10 @@ def extract_tiles(n, screenshots_XY, params):
os.mkdir(os.path.join(output_directory, "tiles", str(zoom), str(X)))
except FileExistsError:
# Ignore this error, it means one other thread has already created the folder
continue
pass
except Exception as e:
raise e
img.crop(box).save(os.path.join(output_directory, "tiles", str(zoom), str(X), f"{Y}.jpg"))
img.crop(box).convert('RGBA').save(os.path.join(output_directory, "tiles", str(zoom), str(X), f"{Y}.png"))
n += 1
else:
@ -100,21 +100,17 @@ def merge_tiles(base_path, zoom, tile):
Y = tile[1]
# If the image already exists, open it so we can paste the higher quality data in it
if os.path.exists(os.path.join(base_path, str(zoom - 1), str(X), f"{Y}.jpg")):
dst = Image.open(os.path.join(base_path, str(zoom - 1), str(X), f"{Y}.jpg"))
dst.putalpha(255)
dst = make_background_transparent(dst)
if os.path.exists(os.path.join(base_path, str(zoom - 1), str(X), f"{Y}.png")):
dst = Image.open(os.path.join(base_path, str(zoom - 1), str(X), f"{Y}.png"))
else:
dst = Image.new('RGBA', (256, 256), (221, 221, 221, 255))
dst = Image.new('RGBA', (256, 256), (0, 0, 0, 0))
# Loop on all the 4 subtiles in the tile
positions = [(0, 0), (0, 1), (1, 0), (1, 1)]
for i in range(0, 4):
# Open the subtile, if it exists, and resize it down to 128x128
if os.path.exists(os.path.join(base_path, str(zoom), str(2*X + positions[i][0]), f"{2*Y + positions[i][1]}.jpg")):
im = Image.open(os.path.join(base_path, str(zoom), str(2*X + positions[i][0]), f"{2*Y + positions[i][1]}.jpg")).resize((128, 128))
im.putalpha(255)
im = make_background_transparent(im)
if os.path.exists(os.path.join(base_path, str(zoom), str(2*X + positions[i][0]), f"{2*Y + positions[i][1]}.png")):
im = Image.open(os.path.join(base_path, str(zoom), str(2*X + positions[i][0]), f"{2*Y + positions[i][1]}.png")).resize((128, 128))
dst.paste(im, (positions[i][0] * 128, positions[i][1] * 128), im)
# Create the output folder if it exists
@ -128,7 +124,7 @@ def merge_tiles(base_path, zoom, tile):
raise e
# Save the image
remove_black_areas(dst.convert('RGB')).save(os.path.join(base_path, str(zoom - 1), str(X), f"{Y}.jpg"), quality=98)
dst.save(os.path.join(base_path, str(zoom - 1), str(X), f"{Y}.png"), quality=98)
def computeCorrectionFactor(XY, n_width, n_height, map_config, zoom, output_directory, port):
# Take screenshots at the given position, then east and south of it
@ -216,26 +212,6 @@ def takeScreenshot(XY, n_width, n_height, map_config, zoom, output_directory, f,
# Rotate, resize and save the screenshot
screenshot.rotate(math.degrees(geo_data['northRotation'])).resize((int(sx * screenshot.width) + correction[0], int(sy * screenshot.height)+ correction[1] )).save(os.path.join(output_directory, "screenshots", f"{f}_{n}_{zoom}.jpg"), quality=98)
def make_background_transparent(im):
data = numpy.array(im)
red, green, blue, alpha = data.T
# If present, remove any "background" areas
background_areas = (red > 211) & (red < 231) & (green > 211) & (green < 231) & (blue > 211) & (blue < 231)
data[..., :][background_areas.T] = (0, 0, 0, 0) # make transparent
return Image.fromarray(data)
def remove_black_areas(im):
data = numpy.array(im)
red, green, blue = data.T
# If present, remove any "black" areas
background_areas = (red < 10) & (blue < 10) & (green < 10)
data[..., :][background_areas.T] = (221, 221, 221)
return Image.fromarray(data)
def run(map_config, port):
global tot_futs, fut_counter
@ -262,6 +238,12 @@ def run(map_config, port):
usable_width = screen_config['width'] - 400 # Keep a margin around the center
usable_height = screen_config['height'] - 400 # Keep a margin around the center
existing_zoom_levels = [int(f) for f in listdir(os.path.join(output_directory, "tiles")) if isdir(join(output_directory, "tiles", f))]
if len(existing_zoom_levels) == 0:
final_level = 1
else:
final_level = max(existing_zoom_levels)
with open(map_config['boundary_file'], 'rt', encoding="utf-8") as bp:
# Read the config file
doc = bp.read()
@ -355,12 +337,15 @@ def run(map_config, port):
print(f"Feature {f} of {len(features)} completed!")
f += 1
if zoom <= final_level:
final_level = int(input(f"Zoom level already exists. Starting from level {zoom}, please enter desired final zoom level: "))
########### Assemble tiles to get lower zoom levels
for current_zoom in range(zoom, 8, -1):
for current_zoom in range(zoom, final_level, -1):
Xs = [int(d) for d in listdir(os.path.join(output_directory, "tiles", str(current_zoom))) if isdir(join(output_directory, "tiles", str(current_zoom), d))]
existing_tiles = []
for X in Xs:
Ys = [int(f.removesuffix(".jpg")) for f in listdir(os.path.join(output_directory, "tiles", str(current_zoom), str(X))) if isfile(join(output_directory, "tiles", str(current_zoom), str(X), f))]
Ys = [int(f.removesuffix(".png")) for f in listdir(os.path.join(output_directory, "tiles", str(current_zoom), str(X))) if isfile(join(output_directory, "tiles", str(current_zoom), str(X), f))]
for Y in Ys:
existing_tiles.append((X, Y))
@ -368,7 +353,7 @@ def run(map_config, port):
for tile in existing_tiles:
if (int(tile[0] / 2), int(tile[1] / 2)) not in tiles_to_produce:
tiles_to_produce.append((int(tile[0] / 2), int(tile[1] / 2)))
# Merge the tiles with parallel thread execution
with futures.ThreadPoolExecutor() as executor:
print(f"Merging tiles for zoom level {current_zoom - 1}...")