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),
|
||||
("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),
|
||||
@ -189,9 +189,9 @@ mstr_ortho_layers = [
|
||||
("building", "terrace", "building", "industrial"),
|
||||
("building", "hangar", "building", "industrial"),
|
||||
("building", "school", "building", "common"),
|
||||
("building", "kindergarten", "building", "kindergarten"),
|
||||
("building", "public", "building", "public"),
|
||||
("building", "commercial", "building", "commercial"),
|
||||
("building", "kindergarten", "building", "kindergarten"),
|
||||
("building", "public", "building", "public"),
|
||||
("building", "commercial", "building", "commercial"),
|
||||
("building", "yes", "building", "common"),
|
||||
("place", "sea", "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 = [
|
||||
("+50+000", [
|
||||
(48,63,34),
|
||||
|
123
layergen.py
@ -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")
|
||||
|
||||
@ -638,14 +614,14 @@ class mstr_layergen:
|
||||
ab=False
|
||||
al=False
|
||||
layer_pix = layer_comp.load() # <- Just to be safe
|
||||
|
||||
|
||||
# Top scan
|
||||
for i in range(0, self._imgsize-1):
|
||||
p = layer_pix[i,0]
|
||||
if p[3] > 0:
|
||||
at=True
|
||||
break
|
||||
|
||||
|
||||
# Right scan
|
||||
for i in range(0, self._imgsize-1):
|
||||
p = layer_pix[self._imgsize-1,i]
|
||||
@ -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))
|
||||
@ -959,6 +955,61 @@ class mstr_layergen:
|
||||
layer_comp_pix[x,y] = (nr, ng, nb, c[3])
|
||||
#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"):
|
||||
@ -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
|
||||
|
@ -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))
|
||||
|
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 |