Further fine tuning to rendering and layering, added subtle details to different kinds of buildings for more realism

This commit is contained in:
Marcus Str. 2024-10-12 21:18:39 +02:00
parent 265197d295
commit 817d65639d
21 changed files with 103 additions and 41 deletions

View File

@ -148,6 +148,8 @@ mstr_ortho_layers = [
("highway", "living_street", 12),
("waterway", "river", 10),
("waterway", "stream", 2),
("amenity", "parking", "amenity", "parking"),
("amenity", "school", "amenity", "school"),
("leisure", "nature_reserve", "landuse", "forest"),
("landuse", "forest", "landuse", "forest"),
("natural", "wood", "natural", "wood"),
@ -165,8 +167,6 @@ mstr_ortho_layers = [
("water", "pond", "natural", "water"),
("water", "river", "natural", "water"),
("leisure", "swimming_pool", "natural", "water"),
("amenity", "parking", "amenity", "parking"),
("amenity", "school", "amenity", "school"),
("highway", "pedestrian", 4),
# Z-Order 4
("highway", "motorway", 32),
@ -395,6 +395,15 @@ mstr_building_base_colors = [
]
# Base colors to add some details to all kinds of buildings
mstr_building_detail_colors = [
(136, 132, 86), # Some kind of moss
(136, 90, 86), # Some kind of rust or darkening
(154, 154, 154), # Other random details
(97, 97, 97) # Square or line details, alpha-blended
]
mstr_completion_colors = [
("+50+000", [
(48,63,34),

View File

@ -16,7 +16,7 @@ import glob
import os
from random import randrange
import random
from PIL import Image, ImageFilter, ImageDraw, ImagePath, ImageEnhance
from PIL import Image, ImageFilter, ImageDraw
from defines import *
from log import *
from tileinfo import *
@ -56,11 +56,6 @@ class mstr_layergen:
def set_latlng_folder(self, latlngfld):
self._latlngfld = latlngfld
# Open DB
def open_db(self):
self._tiledb = mstr_tiledb(self._latitude, self._longitude, self._latlngfld)
self._tiledb.create_tables()
# Tile info object
def open_tile_info(self):
self._tileinfo = mstr_tileinfo(self._latitude, self._longitude, self._lat_number, self._lng_number, self._latlngfld)
@ -473,7 +468,8 @@ class mstr_layergen:
for x in range(self._imgsize):
tp = tree_pix[x,y]
if tp[3] > 0:
sc = (0,0,0,180)
rndshd = randrange(5, 210)
sc = (0,0,0,rndshd)
if x+8 < self._imgsize and y+5 < self._imgsize:
shadow_pix[x+8,y+5] = sc
tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))
@ -547,18 +543,12 @@ class mstr_layergen:
if os.path.isfile(fn):
rsd = Image.open(fn)
rsd_pix = rsd.load()
forest_layer = Image.new("RGBA", (self._imgsize, self._imgsize))
for_pix = forest_layer.load()
for y in range(self._imgsize):
for x in range(self._imgsize):
rpix = rsd_pix[x,y]
lpix = layer_comp_pix[x,y]
if rpix[3] > 0 and lpix[3] > 0:
for_pix[x,y] = (rpix[0], rpix[1], rpix[2], rpix[3])
layer_comp.alpha_composite(forest_layer)
#if os.path.isfile(fn) == True:
# rsd = Image.open(fn)
# layer_comp.alpha_composite(rsd)
layer_comp_pix[x,y] = (lpix[0], lpix[1], lpix[2], 255-rpix[3])
# Store layer
if self._is_completion == False:
@ -612,20 +602,6 @@ class mstr_layergen:
shadow = shadow.filter(ImageFilter.GaussianBlur(radius=1.5))
"""
for y in range(self._imgsize-1):
for x in range(self._imgsize-1):
m = mask_pix[x,y]
shf_x = 0
shf_x = x + mstr_shadow_shift
if shf_x < self._imgsize:
a = mask_pix[x,y][3]
st = 0
st = random.uniform(0.45, mstr_shadow_strength)
ca = a * st
aa = int(ca)
shadow_pix[shf_x, y] = (0,0,0,aa)
"""
shadow.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_shadow.png")
mstr_msg("layergen", "Shadow layer completed")
@ -842,8 +818,8 @@ class mstr_layergen:
details = Image.new("RGBA", (self._imgsize, self._imgsize))
details_pix = details.load()
layer_pix = layer_comp.load()
for y in range(self._imgsize-1):
for x in range(self._imgsize-1):
for y in range(self._imgsize):
for x in range(self._imgsize):
p = layer_pix[x,y]
if p[3] > 0:
shf_x = x+randrange(1, 16)
@ -859,6 +835,25 @@ class mstr_layergen:
details_pix[shf_x, shf_y] = (187-d, 179-d, 176-d, aa)
details_pix[shf_x2, shf_y2] = (187-d2, 179-d2, 176-d2, aa)
# Image for roof details
roof_details = Image.new("RGBA", (self._imgsize, self._imgsize))
roof_det_pix = roof_details.load()
for y in range(self._imgsize):
for x in range(self._imgsize):
mp = mask_pix[x,y]
if mp[3] == 255:
# Determine if we render some pixel
rnd = randrange(1, 3)
if rnd == 2:
# Find a range for the base color of the pixel
d = randrange(21)
# Find a random alpha value
a = randrange(1, 151)
nc = (mstr_building_detail_colors[0][0]-d, mstr_building_detail_colors[0][1]-d, mstr_building_detail_colors[0][2]-d, a)
roof_det_pix[x,y] = nc
layer_comp.alpha_composite(roof_details)
# Let's see how it works with this method
details.save(mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer_details.png")
@ -899,7 +894,8 @@ class mstr_layergen:
for x in range(self._imgsize):
tp = tree_pix[x,y]
if tp[3] > 0:
sc = (0,0,0,180)
rndshd = randrange(5, 210)
sc = (0,0,0,rndshd)
if x+8 < self._imgsize and y+5 < self._imgsize:
shadow_pix[x+8,y+5] = sc
tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))
@ -960,6 +956,61 @@ class mstr_layergen:
#layer_comp = layer_comp.filter(ImageFilter.GaussianBlur(radius=1))
# Let's add some details to the roofs
if self._tag == "building":
vls = [ "detached", "hotel", "farm", "semidetached_house", "apartments", "civic", "house", "school", "kindergarten", "yes" ]
if self._value in vls:
roof_additional_detail = Image.new("RGBA", (self._imgsize, self._imgsize))
rad_pix = roof_additional_detail.load()
for r in range(30001):
lx = randrange(self._imgsize)
ly = randrange(self._imgsize)
mp = mask_pix[lx,ly]
if mp[3] == 255:
# Brighter or darker pixel
bod = randrange(1,3)
c = 0
if bod == 2:
c = 40
else:
c = 200
dt = (c, c, c, 130)
rad_pix[lx,ly] = dt
if lx+1 < self._imgsize:
rad_pix[lx+1, ly] = dt
if lx+1 < self._imgsize and ly+1 < self._imgsize:
rad_pix[lx+1, ly+1] = dt
if ly+1 < self._imgsize:
rad_pix[lx, ly+1] = dt
layer_comp.alpha_composite(roof_additional_detail)
# Let's put some other details on commercial buildings
if self._tag == "building":
vls = [ "office", "retail", "industrial" ]
if self._value in vls:
# Find a suitable location to render something
for r in range(15001):
lx = randrange(self._imgsize)
ly = randrange(self._imgsize)
mp = mask_pix[lx,ly]
# Think of some random shape
if mp[3] == 255:
rw = randrange(3,8)
rh = randrange(3,8)
sh = Image.new("RGBA", (rw, rh), (30,30,30,130))
shp = sh.load()
for sy in range(rh):
for sx in range(rw):
if sx > 0 and sx < rw and sy > 0 and sy < rh: shp[sx, sy] = (180,180,180,160)
rt = randrange(1, 3)
if rt == 2:
sh = sh.rotate(45, expand=True)
layer_comp.alpha_composite(sh, (lx, ly))
# Highways and runways of any kind get some special treatment
if (self._tag == "highway" and self._value == "motorway") or (self._tag == "highway" and self._value == "primary") or (self._tag == "highway" and self._value == "secondary") or (self._tag == "highway" and self._value == "tertiary") or (self._tag == "aeroway" and self._value == "runway"):
# We will now add some white lines for coolness
@ -1072,6 +1123,7 @@ class mstr_layergen:
ptc_src.append(Image.open(p))
osm_mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + ".png" )
lyr_mask = Image.open( mstr_datafolder + "_cache/" + str(self._latitude) + "-" + str(self._lat_number) + "_" + str(self._longitude) + "-" + str(self._lng_number) + "_" + self._tag + "-" + self._value + "_layer.png" )
for i in mstr_mask_blur:
if i[0] == self._tag and i[1] == self._value:
@ -1095,11 +1147,12 @@ class mstr_layergen:
adj_image.alpha_composite( brd_src )
lyr_pix = lyr_mask.load()
for y in range(self._imgsize):
for x in range(self._imgsize):
if mask_pix[x, y][3] > 0:
if lyr_pix[x, y][3] > 0:
rgb=adj_pix[x,y]
a=mask_pix[x,y]
a=lyr_pix[x,y]
adj_pix[x, y] = ( rgb[0], rgb[1], rgb[2], a[3])
# Up until here we mimiced the exact same behavior as layergen. However, now

View File

@ -71,7 +71,7 @@ class mstr_photogen:
if l[0] == "building":
if os.path.isfile(root_filename + l[0] + "-" + l[1] + "_layer.png"):
bld = Image.open(root_filename + l[0] + "-" + l[1] + "_layer.png")
bld = bld.filter(ImageFilter.GaussianBlur(radius=1))
bld = bld.filter(ImageFilter.GaussianBlur(radius=0.7))
bldg_main.alpha_composite(bld)
# Trees merging
tree_main = Image.new("RGBA", (self._imgsize, self._imgsize))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB