-
Notifications
You must be signed in to change notification settings - Fork 74
Open
Description
I've seen several 3D printed maps using the height map. (And I'm going to make one of my own.) Fixing the water level is a tedious task. It would be nice to have a height map with both terrain and water combined.
The script below is my attempt to create a composite image. It just layers all of the water height maps and takes the largest pixel value. Then it adds the HIRES terrain map using the same process.
There are four disadvantages to my script:
- The water maps are at a much lower resolution, so have to be significantly scaled.
- The water maps are 8-bit instead of 16-bit, so the heights also have to be scaled.
- The water maps encompass a smaller area than the HIRES terrain map. I've got a decent attempt on how to align them, but I'm not sure it's perfect.
- I don't have a platform to distribute the final composite to people who want it.
For these reasons, I believe adding an official combined composite image would be good. I personally don't need anything bigger than 8K by 8K.
import cv2
import numpy as np
import glob
water_map_format = 'heightmap_water*.png'
terrain_map_file = 'heightmap_HIRES_0.125_resized.png'
water_composite_output = 'water_composite.png'
complete_composite_output = 'complete_composite.png'
# Load the water maps
png_files = sorted(glob.glob(water_map_format))
# Read the first map to start the composite
water_composite = cv2.imread(png_files[0], cv2.IMREAD_GRAYSCALE)
# Compare with remaining images
for file in png_files[1:]:
img = cv2.imread(file, cv2.IMREAD_GRAYSCALE) # 8-bit grayscale
# Take the highest pixel value
water_composite = np.maximum(water_composite, img)
# Load the terrain image to get its dimensions
terrain_image = cv2.imread(terrain_map_file, cv2.IMREAD_UNCHANGED) # 16-bit grayscale
terrain_height, terrian_width = terrain_image.shape
# Resize the water composite image to match the terrain
# TODO: This is an estimation.
# Assume the water map is 2/3 the size of the terrain map.
# Add a black border to cover the last bit, then resize.
# Also assume this is a square image.
h, w = water_composite.shape
border_size = int(h * 0.33333 / 2)
water_composite = cv2.copyMakeBorder(
water_composite,
border_size,
border_size,
border_size,
border_size,
borderType=cv2.BORDER_CONSTANT,
value=[0, 0, 0]
)
# Scale it to match the terrain map
water_composite = cv2.resize(water_composite, (terrain_height, terrian_width), interpolation=cv2.INTER_LINEAR)
# Rescale the water composite values to be 16bit
water_composite = water_composite.astype(np.uint16) * 257
# Save off the water composite
cv2.imwrite(water_composite_output, water_composite)
# Combine the terrain and water maps
complete_composite = np.maximum(water_composite, terrain_image)
# Save the result
cv2.imwrite(complete_composite_output, complete_composite)
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels