DynamicSceneGeneration / dynamic_utils.py
wcx
Init commit
8f3b56b
import numpy as np
import random
import copy
PRIVATE_OBJECT_LIST = ["AlarmClock", "CellPhone", "Cloth", "CreditCard", "HandTower", "KeyChain", "Laptop", "Pillow", "TeddyBear", "Towel", "Watch"]
COMMONLY_USED_OBJECT_LIST = ['Book', 'CD', 'Newspaper']
FILTER_TYPE = [
"AlarmClock",
"BaseballBat",
"BasketBall",
"Bowl",
"Book"
"CellPhone",
"Cloth",
"CreditCard",
'Cup',
'DishSponge',
'Fork',
'KeyChain',
"Laptop",
'Knife',
"Mug",
"Newspaper",
'Pen',
'Pencil',
'Pillow',
'Plate',
'Spoon',
'SprayBottle',
'Vase',
'Watch',
]
PICKUPABLE_OBJECT_LIST = ['AlarmClock', 'AluminumFoil', 'Apple', 'AppleSliced', 'BaseballBat',
'BasketBall', 'Book', 'Boots', 'Bottle', 'Bowl', 'Box', 'Bread',
'BreadSliced', 'ButterKnife', 'Candle', 'CD', 'CellPhone', 'Cloth',
'CreditCard', 'Cup', 'DishSponge', 'Dumbbell', 'Egg', 'EggCracked',
'Fork', 'HandTowel', 'Kettle', 'KeyChain', 'Knife', 'Ladle', 'Laptop',
'Lettuce', 'LettuceSliced', 'Mug', 'Newspaper', 'Pan', 'PaperTowelRoll',
'Pen', 'Pencil', 'PepperShaker', 'Pillow', 'Plate', 'Plunger', 'Pot', 'Potato',
'PotatoSliced', 'RemoteControl', 'SaltShaker', 'ScrubBrush', 'SoapBar', 'SoapBottle',
'Spatula', 'Spoon', 'SprayBottle', 'Statue', 'TableTopDecor', 'TeddyBear', 'TennisRacket',
'TissueBox', 'ToiletPaper', 'Tomato', 'TomatoSliced', 'Towel', 'Vase', 'Watch', 'WateringCan', 'WineBottle']
RECEPTACLE_LIST = ['ArmChair', 'Bathtub', 'BathtubBasin', 'Bed', 'Bowl', 'Box', 'Cabinet', 'Chair', 'CoffeeMachine', 'CoffeeTable',
'CounterTop', 'Cup', 'Desk', 'DiningTable', 'Drawer', 'Dresser', 'Fridge', 'GarbageCan', 'HandTowelHolder',
'LaundryHamper', 'Microwave', 'Mug', 'Ottoman', 'Pan', 'Plate', 'Pot', 'Safe', 'Shelf', 'SideTable', 'Sink',
'SinkBasin', 'Sofa', 'StoveBurner', 'Toaster', 'Toilet', 'ToiletPaperHanger', 'TowelHolder', 'TVStand']
def get_obj_type(obj_id):
return obj_id.split('|')[0]
def get_obj_belong_type(obj_id):
obj_type = get_obj_type(obj_id)
belong_type = "public"
if obj_type in PRIVATE_OBJECT_LIST:
belong_type = "private"
elif obj_type in COMMONLY_USED_OBJECT_LIST:
belong_type = "part_public"
return belong_type
class Sampler():
def __init__(self):
self.schedules = []
self.activity_base = {}
self.character = []
self.character_specific = {}
self.scene_layout = {}
self.object_prior = {}
def clear_character_specific(self):
self.character_specific = {}
for c in self.character:
self.character_specific[c] = {}
self.character_specific[c]['room'] = {}
self.character_specific[c]['related_object'] = []
def set_activity(self, character_info, activity_base, schedules):
self.activity_base = activity_base
self.character_info = character_info
self.character = [c['name'] for c in self.character_info]
self.schedules = schedules
self.clear_character_specific()
def set_scene_layout(self, scene_layout):
self.scene_layout = scene_layout
self.clear_character_specific()
def get_character_group(self):
result = [[c] for c in self.character]
return result
def object_allocation(self):
rooms = self.scene_layout['room']
bedrooms = [room for room in rooms if room['roomType'] == 'Bedroom']
bathrooms = [room for room in rooms if room['roomType'] == 'Bathroom']
character_group = self.get_character_group()
bedroom_stack = copy.deepcopy(bedrooms)
bathroom_stack = copy.deepcopy(bathrooms)
for cg in character_group:
if len(bedroom_stack) > 0:
cd_bedroom = bedroom_stack[-1]
bedroom_stack.pop(-1)
else:
cd_bedroom = bedrooms[0]
if len(bathroom_stack) > 0:
cd_bathroom = bathroom_stack[-1]
bathroom_stack.pop(-1)
else:
cd_bathroom = bathrooms[0]
for c in cg:
self.character_specific[c]['room'] = {
'Bedroom':cd_bedroom['roomId'],
'Bathroom':cd_bathroom['roomId']
}
#object
pickup_objects = self.scene_layout['pickupable object']
for pobj in pickup_objects:
pobj_type = get_obj_type(pobj)
#private
if pobj_type in PRIVATE_OBJECT_LIST:
for character in self.character_specific:
private_objects = self.character_specific[character]['related_object']
exist = False
for o in private_objects:
if get_obj_type(o) == pobj_type:
exist = True
break
if not exist:
self.character_specific[character]['related_object'].append(pobj)
break
#common used (not all characters)
elif pobj_type in COMMONLY_USED_OBJECT_LIST:
if len(self.character) >= 2:
selected_characters = random.sample(self.character, 2)
else:
selected_characters = self.character
for sc in selected_characters:
self.character_specific[sc]['related_object'].append(pobj)
def sample_schedules(self, id=0):
character = self.character[id]
schedules = self.schedules[id]
activity_base = self.activity_base[id]
results = {}
for day in schedules:
day_schedule = []
for activity in schedules[day]:
activity_name = activity['activity']
#character = activity['character']
if activity_name not in activity_base:
continue
activity_content = activity_base[activity_name]
#sample room
rooms = list(activity_content.keys())
room_probs = np.array([activity_content[room]['room_prob'] for room in activity_content])
if not room_probs.sum() == 1:
room_probs = room_probs / room_probs.sum()
choose_ids = [i for i in range(len(rooms))]
choose_id = np.random.choice(choose_ids, p=room_probs.ravel())
room = rooms[choose_id]
#room ground to scene
final_rooms = []
#卧室和厕所找分配
if (room == 'Bedroom' or room == 'Bathroom'):
final_room_id = self.character_specific[character]['room'][room]
for r in self.scene_layout['room']:
if r['roomId'] == final_room_id:
final_room = r
break
else:
for scene_room in self.scene_layout['room']:
if scene_room['roomType'] == room:
final_rooms.append(scene_room)
#final_room = final_rooms[0]
final_room = np.random.choice(final_rooms)
#sample object
object_effect = activity_content[room]['object_effect']
sample_objects = []
for obj in object_effect:
object_prob = float(object_effect[obj]['object_prob'])
random_num = random.random()
if random_num < object_prob:
sample_objects.append(obj)
#sample receptacle
sample_receptacles = []
for obj in sample_objects:
#除去房间中没有的receptacle,并重新归一化
possible_receptacles_init = object_effect[obj]['receptacles']
possible_receptacles = []
for pr in possible_receptacles_init:
for child in final_room['children']:
if pr[0] == child.split('|')[0] and pr[0]!='Fridge':
possible_receptacles.append(pr)
break
if len(possible_receptacles) == 0:
continue
prob_sum = 0
for pr in possible_receptacles:
prob_sum += pr[1]
for i in range(len(possible_receptacles)):
possible_receptacles[i][1] = possible_receptacles[i][1] / prob_sum
receptacle_probs = np.array([recep[1] for recep in possible_receptacles])
choose_ids = [i for i in range(len(receptacle_probs))]
choose_id = np.random.choice(choose_ids, p=receptacle_probs.ravel())
receptacle = possible_receptacles[choose_id][0]
sample_receptacles.append([obj, receptacle])
final_sample = []
for type_sample in sample_receptacles:
obj_type = type_sample[0]
receptacle_type = type_sample[1]
final_obj = ""
final_recep = ""
related_objs = self.character_specific[character]['related_object']
if obj_type in PRIVATE_OBJECT_LIST:
for ro in related_objs:
if get_obj_type(ro) == obj_type:
final_obj = ro
break
else:
exist = False
for ro in related_objs:
if get_obj_type(ro) == obj_type:
exist = True
final_obj = ro
break
if not exist:
#从全部找
cand_final_obj = []
for pick_obj in self.scene_layout['pickupable object']:
if pick_obj.split("|")[0] == obj_type:
#final_obj = pick_obj
cand_final_obj.append(pick_obj)
if len(cand_final_obj) > 0:
final_obj = np.random.choice(cand_final_obj)
for recep in final_room['children']:
if recep.split('|')[0] == receptacle_type:
final_recep = recep
break
if len(final_obj)>0 and len(final_recep) > 0:
final_sample.append({
'object':final_obj,
'receptacle':final_recep
})
day_schedule.append({
'activity':activity_name,
'character':character,
'start_time':activity['start_time'],
'end_time':activity['end_time'],
'room':final_room['roomId'],
'room_type':final_room['roomType'],
'content':final_sample,
})
results[day] = day_schedule
return results
def sample(self):
self.object_allocation()
sample_schedules = {}
keys = list(self.schedules[0].keys())
for key in keys:
sample_schedules[key] = []
for i in range(len(self.character)):
schedule = self.sample_schedules(i)
for key in keys:
sample_schedules[key].extend(schedule[key])
def compare_time(item):
return item['start_time']
for key in keys:
sample_schedules[key] = sorted(sample_schedules[key], key=compare_time)
return sample_schedules, None, None
def get_layout(house_info):
objects = house_info['objects']
rooms = house_info['rooms']
room_info = []
receptacle_info = []
pickupable_object_info = []
for room in rooms:
room_info.append({
'roomId':room['id'],
'roomType':room['roomType'],
'roomPolygon':room['floorPolygon'],
'children':[],
})
def isIn(obj, room):
pos = obj['position']
room_polygon = room['roomPolygon']
polygon_n = len(room_polygon)
j = polygon_n - 1
res = False
for i in range(polygon_n):
if ((room_polygon[i]['z']>pos['z'])!=(room_polygon[j]['z']>pos['z']) and \
pos['x']< (room_polygon[j]['x'] - room_polygon[i]['x']) * (pos['z'] - room_polygon[i]['z'])/(room_polygon[j]['z'] - room_polygon[i]['z']) + room_polygon[i]['x'] ):
res = not res
j = i
return res
def get_type(oid):
return oid.split('|')[0]
def get_receptacle_info(obj):
rinfo = {
'id':obj['id'],
}
if 'children' in obj:
rc = []
for child in obj['children']:
rc.append(child['id'])
if get_type(child['id']) in PICKUPABLE_OBJECT_LIST:
pickupable_object_info.append(child['id'])
if get_type(child['id']) in RECEPTACLE_LIST:
get_receptacle_info(child)
if len(rc) >0:
rinfo['children'] = rc
receptacle_info.append(rinfo)
for obj in objects:
for room in room_info:
if isIn(obj, room):
room['children'].append(obj['id'])
#print("{} in {}".format(obj['id'], room['roomType']))
break
if get_type(obj['id']) in RECEPTACLE_LIST:
get_receptacle_info(obj)
if get_type(obj['id']) in PICKUPABLE_OBJECT_LIST:
pickupable_object_info.append(obj['id'])
for r in room_info:
del r['roomPolygon']
layout_info = {
'room':room_info,
'receptacle': receptacle_info,
'pickupable object' : pickupable_object_info
}
return layout_info