Spaces:
Running
Running
| 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 | |