Further fine tuning to rendering and layering, added subtle details to different kinds of buildings for more realism
19
defines.py
@ -148,6 +148,8 @@ mstr_ortho_layers = [
|
|||||||
("highway", "living_street", 12),
|
("highway", "living_street", 12),
|
||||||
("waterway", "river", 10),
|
("waterway", "river", 10),
|
||||||
("waterway", "stream", 2),
|
("waterway", "stream", 2),
|
||||||
|
("amenity", "parking", "amenity", "parking"),
|
||||||
|
("amenity", "school", "amenity", "school"),
|
||||||
("leisure", "nature_reserve", "landuse", "forest"),
|
("leisure", "nature_reserve", "landuse", "forest"),
|
||||||
("landuse", "forest", "landuse", "forest"),
|
("landuse", "forest", "landuse", "forest"),
|
||||||
("natural", "wood", "natural", "wood"),
|
("natural", "wood", "natural", "wood"),
|
||||||
@ -165,8 +167,6 @@ mstr_ortho_layers = [
|
|||||||
("water", "pond", "natural", "water"),
|
("water", "pond", "natural", "water"),
|
||||||
("water", "river", "natural", "water"),
|
("water", "river", "natural", "water"),
|
||||||
("leisure", "swimming_pool", "natural", "water"),
|
("leisure", "swimming_pool", "natural", "water"),
|
||||||
("amenity", "parking", "amenity", "parking"),
|
|
||||||
("amenity", "school", "amenity", "school"),
|
|
||||||
("highway", "pedestrian", 4),
|
("highway", "pedestrian", 4),
|
||||||
# Z-Order 4
|
# Z-Order 4
|
||||||
("highway", "motorway", 32),
|
("highway", "motorway", 32),
|
||||||
@ -189,9 +189,9 @@ mstr_ortho_layers = [
|
|||||||
("building", "terrace", "building", "industrial"),
|
("building", "terrace", "building", "industrial"),
|
||||||
("building", "hangar", "building", "industrial"),
|
("building", "hangar", "building", "industrial"),
|
||||||
("building", "school", "building", "common"),
|
("building", "school", "building", "common"),
|
||||||
("building", "kindergarten", "building", "kindergarten"),
|
("building", "kindergarten", "building", "kindergarten"),
|
||||||
("building", "public", "building", "public"),
|
("building", "public", "building", "public"),
|
||||||
("building", "commercial", "building", "commercial"),
|
("building", "commercial", "building", "commercial"),
|
||||||
("building", "yes", "building", "common"),
|
("building", "yes", "building", "common"),
|
||||||
("place", "sea", "natural", "sea"),
|
("place", "sea", "natural", "sea"),
|
||||||
("place", "ocean", "natural", "sea")
|
("place", "ocean", "natural", "sea")
|
||||||
@ -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 = [
|
mstr_completion_colors = [
|
||||||
("+50+000", [
|
("+50+000", [
|
||||||
(48,63,34),
|
(48,63,34),
|
||||||
|
123
layergen.py
@ -16,7 +16,7 @@ import glob
|
|||||||
import os
|
import os
|
||||||
from random import randrange
|
from random import randrange
|
||||||
import random
|
import random
|
||||||
from PIL import Image, ImageFilter, ImageDraw, ImagePath, ImageEnhance
|
from PIL import Image, ImageFilter, ImageDraw
|
||||||
from defines import *
|
from defines import *
|
||||||
from log import *
|
from log import *
|
||||||
from tileinfo import *
|
from tileinfo import *
|
||||||
@ -56,11 +56,6 @@ class mstr_layergen:
|
|||||||
def set_latlng_folder(self, latlngfld):
|
def set_latlng_folder(self, latlngfld):
|
||||||
self._latlngfld = 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
|
# Tile info object
|
||||||
def open_tile_info(self):
|
def open_tile_info(self):
|
||||||
self._tileinfo = mstr_tileinfo(self._latitude, self._longitude, self._lat_number, self._lng_number, self._latlngfld)
|
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):
|
for x in range(self._imgsize):
|
||||||
tp = tree_pix[x,y]
|
tp = tree_pix[x,y]
|
||||||
if tp[3] > 0:
|
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:
|
if x+8 < self._imgsize and y+5 < self._imgsize:
|
||||||
shadow_pix[x+8,y+5] = sc
|
shadow_pix[x+8,y+5] = sc
|
||||||
tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))
|
tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))
|
||||||
@ -547,18 +543,12 @@ class mstr_layergen:
|
|||||||
if os.path.isfile(fn):
|
if os.path.isfile(fn):
|
||||||
rsd = Image.open(fn)
|
rsd = Image.open(fn)
|
||||||
rsd_pix = rsd.load()
|
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 y in range(self._imgsize):
|
||||||
for x in range(self._imgsize):
|
for x in range(self._imgsize):
|
||||||
rpix = rsd_pix[x,y]
|
rpix = rsd_pix[x,y]
|
||||||
lpix = layer_comp_pix[x,y]
|
lpix = layer_comp_pix[x,y]
|
||||||
if rpix[3] > 0 and lpix[3] > 0:
|
if rpix[3] > 0 and lpix[3] > 0:
|
||||||
for_pix[x,y] = (rpix[0], rpix[1], rpix[2], rpix[3])
|
layer_comp_pix[x,y] = (lpix[0], lpix[1], lpix[2], 255-rpix[3])
|
||||||
layer_comp.alpha_composite(forest_layer)
|
|
||||||
#if os.path.isfile(fn) == True:
|
|
||||||
# rsd = Image.open(fn)
|
|
||||||
# layer_comp.alpha_composite(rsd)
|
|
||||||
|
|
||||||
# Store layer
|
# Store layer
|
||||||
if self._is_completion == False:
|
if self._is_completion == False:
|
||||||
@ -612,20 +602,6 @@ class mstr_layergen:
|
|||||||
|
|
||||||
shadow = shadow.filter(ImageFilter.GaussianBlur(radius=1.5))
|
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")
|
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")
|
mstr_msg("layergen", "Shadow layer completed")
|
||||||
|
|
||||||
@ -638,14 +614,14 @@ class mstr_layergen:
|
|||||||
ab=False
|
ab=False
|
||||||
al=False
|
al=False
|
||||||
layer_pix = layer_comp.load() # <- Just to be safe
|
layer_pix = layer_comp.load() # <- Just to be safe
|
||||||
|
|
||||||
# Top scan
|
# Top scan
|
||||||
for i in range(0, self._imgsize-1):
|
for i in range(0, self._imgsize-1):
|
||||||
p = layer_pix[i,0]
|
p = layer_pix[i,0]
|
||||||
if p[3] > 0:
|
if p[3] > 0:
|
||||||
at=True
|
at=True
|
||||||
break
|
break
|
||||||
|
|
||||||
# Right scan
|
# Right scan
|
||||||
for i in range(0, self._imgsize-1):
|
for i in range(0, self._imgsize-1):
|
||||||
p = layer_pix[self._imgsize-1,i]
|
p = layer_pix[self._imgsize-1,i]
|
||||||
@ -842,8 +818,8 @@ class mstr_layergen:
|
|||||||
details = Image.new("RGBA", (self._imgsize, self._imgsize))
|
details = Image.new("RGBA", (self._imgsize, self._imgsize))
|
||||||
details_pix = details.load()
|
details_pix = details.load()
|
||||||
layer_pix = layer_comp.load()
|
layer_pix = layer_comp.load()
|
||||||
for y in range(self._imgsize-1):
|
for y in range(self._imgsize):
|
||||||
for x in range(self._imgsize-1):
|
for x in range(self._imgsize):
|
||||||
p = layer_pix[x,y]
|
p = layer_pix[x,y]
|
||||||
if p[3] > 0:
|
if p[3] > 0:
|
||||||
shf_x = x+randrange(1, 16)
|
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_x, shf_y] = (187-d, 179-d, 176-d, aa)
|
||||||
details_pix[shf_x2, shf_y2] = (187-d2, 179-d2, 176-d2, 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
|
# 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")
|
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):
|
for x in range(self._imgsize):
|
||||||
tp = tree_pix[x,y]
|
tp = tree_pix[x,y]
|
||||||
if tp[3] > 0:
|
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:
|
if x+8 < self._imgsize and y+5 < self._imgsize:
|
||||||
shadow_pix[x+8,y+5] = sc
|
shadow_pix[x+8,y+5] = sc
|
||||||
tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))
|
tree_shadow = tree_shadow.filter(ImageFilter.GaussianBlur(radius=2))
|
||||||
@ -959,6 +955,61 @@ class mstr_layergen:
|
|||||||
layer_comp_pix[x,y] = (nr, ng, nb, c[3])
|
layer_comp_pix[x,y] = (nr, ng, nb, c[3])
|
||||||
#layer_comp = layer_comp.filter(ImageFilter.GaussianBlur(radius=1))
|
#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
|
# 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"):
|
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"):
|
||||||
@ -1072,6 +1123,7 @@ class mstr_layergen:
|
|||||||
ptc_src.append(Image.open(p))
|
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" )
|
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:
|
for i in mstr_mask_blur:
|
||||||
if i[0] == self._tag and i[1] == self._value:
|
if i[0] == self._tag and i[1] == self._value:
|
||||||
@ -1095,11 +1147,12 @@ class mstr_layergen:
|
|||||||
|
|
||||||
adj_image.alpha_composite( brd_src )
|
adj_image.alpha_composite( brd_src )
|
||||||
|
|
||||||
|
lyr_pix = lyr_mask.load()
|
||||||
for y in range(self._imgsize):
|
for y in range(self._imgsize):
|
||||||
for x 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]
|
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])
|
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
|
# Up until here we mimiced the exact same behavior as layergen. However, now
|
||||||
|
@ -71,7 +71,7 @@ class mstr_photogen:
|
|||||||
if l[0] == "building":
|
if l[0] == "building":
|
||||||
if os.path.isfile(root_filename + l[0] + "-" + l[1] + "_layer.png"):
|
if os.path.isfile(root_filename + l[0] + "-" + l[1] + "_layer.png"):
|
||||||
bld = Image.open(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)
|
bldg_main.alpha_composite(bld)
|
||||||
# Trees merging
|
# Trees merging
|
||||||
tree_main = Image.new("RGBA", (self._imgsize, self._imgsize))
|
tree_main = Image.new("RGBA", (self._imgsize, self._imgsize))
|
||||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.2 KiB |
BIN
textures/building/area/p16.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
textures/building/area/p17.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
textures/building/area/p18.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 1.4 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.3 KiB |