Skip to content

Commit ea983d8

Browse files
author
Hannah DeFazio
committed
Create file for cooking specific functions, move functions around and make them more generic
1 parent eeb8bd1 commit ea983d8

File tree

4 files changed

+178
-228
lines changed

4 files changed

+178
-228
lines changed

angel_system/data/common/cli/add_activity_gt_to_kwcoco.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,16 @@ def main():
1111
default="obj_annotations.mscoco.json",
1212
help="kwcoco filename",
1313
)
14+
parser.add_argument(
15+
"--task",
16+
type=str,
17+
default="medical",
18+
help="Task name",
19+
)
1420

1521
args = parser.parse_args()
1622

17-
add_activity_gt_to_kwcoco(args.dset)
23+
add_activity_gt_to_kwcoco(args.task, args.dset)
1824

1925

2026
if __name__ == "__main__":

angel_system/data/common/kwcoco_utils.py

+5-203
Original file line numberDiff line numberDiff line change
@@ -50,107 +50,6 @@ def load_kwcoco(dset):
5050
return dset
5151

5252

53-
def replace_compound_label(
54-
preds,
55-
obj,
56-
detected_classes,
57-
using_contact,
58-
obj_hand_contact_state=False,
59-
obj_obj_contact_state=False,
60-
):
61-
"""
62-
Check if some subset of obj is in `detected_classes`
63-
64-
Designed to catch and correct incorrect compound classes
65-
Ex: obj is "mug + filter cone + filter" but we detected "mug + filter cone"
66-
"""
67-
68-
compound_objs = [x.strip() for x in obj.split("+")]
69-
detected_objs = [[y.strip() for y in x.split("+")] for x in detected_classes]
70-
71-
replaced_classes = []
72-
for detected_class, objs in zip(detected_classes, detected_objs):
73-
for obj_ in objs:
74-
if obj_ in compound_objs:
75-
replaced_classes.append(detected_class)
76-
break
77-
78-
if replaced_classes == []:
79-
# Case 0, We didn't detect any of the objects
80-
replaced = None
81-
elif len(replaced_classes) == 1:
82-
# Case 1, we detected a subset of the compound as one detection
83-
replaced = replaced_classes[0]
84-
# print(f'replaced {replaced} with {obj}')
85-
86-
preds[obj] = preds.pop(replaced)
87-
88-
if using_contact:
89-
for i in range(len(preds[obj])):
90-
preds[obj][i]["obj_hand_contact_state"] = obj_hand_contact_state
91-
preds[obj][i]["obj_obj_contact_state"] = obj_obj_contact_state
92-
else:
93-
# Case 2, the compound was detected as separate boxes
94-
replaced = replaced_classes
95-
# print(f'Combining {replaced} detections into compound \"{obj}\"')
96-
97-
new_bbox = None
98-
new_conf = None
99-
new_obj_obj_conf = None
100-
new_obj_hand_conf = None
101-
for det_obj in replaced:
102-
assert len(preds[det_obj]) == 1
103-
bbox = preds[det_obj][0]["bbox"]
104-
conf = preds[det_obj][0]["confidence_score"]
105-
106-
if new_bbox is None:
107-
new_bbox = bbox
108-
else:
109-
# Find mix of bboxes
110-
# TODO: first double check these are close enough that it makes sense to combine?
111-
new_tlx, new_tly, new_brx, new_bry = new_bbox
112-
tlx, tly, brx, bry = bbox
113-
114-
new_bbox = [
115-
min(new_tlx, tlx),
116-
min(new_tly, tly),
117-
max(new_brx, brx),
118-
max(new_bry, bry),
119-
]
120-
121-
new_conf = conf if new_conf is None else (new_conf + conf) / 2 # average???
122-
if using_contact:
123-
obj_obj_conf = preds[det_obj][0]["obj_obj_contact_conf"]
124-
new_obj_obj_conf = (
125-
obj_obj_conf
126-
if new_obj_obj_conf is None
127-
else (new_obj_obj_conf + obj_obj_conf) / 2
128-
)
129-
obj_hand_conf = preds[det_obj][0]["obj_hand_contact_conf"]
130-
new_obj_hand_conf = (
131-
obj_hand_conf
132-
if new_obj_hand_conf is None
133-
else (new_obj_hand_conf + obj_hand_conf) / 2
134-
)
135-
136-
# remove old preds
137-
preds.pop(det_obj)
138-
139-
new_pred = {
140-
"confidence_score": new_conf,
141-
"bbox": new_bbox,
142-
}
143-
if using_contact:
144-
new_pred["obj_obj_contact_state"] = obj_obj_contact_state
145-
new_pred["obj_obj_contact_conf"] = new_obj_obj_conf
146-
new_pred["obj_hand_contact_state"] = obj_hand_contact_state
147-
new_pred["obj_hand_contact_conf"] = new_obj_hand_conf
148-
149-
preds[obj] = [new_pred]
150-
151-
return preds, replaced
152-
153-
15453
def add_hl_hands_to_kwcoco(dset, remove_existing=True, using_contact=True):
15554
"""Add bounding boxes for the hands based on the Hololen's joint positions
15655
@@ -256,7 +155,7 @@ def add_hl_hands_to_kwcoco(dset, remove_existing=True, using_contact=True):
256155
print(f"Saved predictions to {dset.fpath}")
257156

258157

259-
def add_activity_gt_to_kwcoco(dset):
158+
def add_activity_gt_to_kwcoco(task, dset):
260159
"""Takes an existing kwcoco file and fills in the "activity_gt"
261160
field on each image based on the activity annotations.
262161
@@ -268,7 +167,7 @@ def add_activity_gt_to_kwcoco(dset):
268167
# Load kwcoco file
269168
dset = load_kwcoco(dset)
270169

271-
data_dir = "/data/PTG/medical/"
170+
data_dir = f"/data/PTG/{task}/"
272171
activity_gt_dir = f"{data_dir}/activity_anns"
273172

274173
for video_id in dset.index.videos.keys():
@@ -278,15 +177,15 @@ def add_activity_gt_to_kwcoco(dset):
278177

279178
if "_extracted" in video_name:
280179
video_name = video_name.split("_extracted")[0]
281-
video_task = "m2"#video["recipe"]
180+
video_skill = "m2"#video["recipe"]
282181

283182
with open(
284-
f"../config/activity_labels/medical/task_{video_task}.yaml", "r"
183+
f"../config/activity_labels/{task}/task_{video_skill}.yaml", "r"
285184
) as stream:
286185
recipe_activity_config = yaml.safe_load(stream)
287186
recipe_activity_labels = recipe_activity_config["labels"]
288187

289-
recipe_activity_gt_dir = f"{activity_gt_dir}/{video_task}_labels/"
188+
recipe_activity_gt_dir = f"{activity_gt_dir}/{video_skill}_labels/"
290189

291190
activity_gt_fn = (
292191
f"{recipe_activity_gt_dir}/{video_name}_activity_labels_v2.csv"
@@ -342,42 +241,6 @@ def add_activity_gt_to_kwcoco(dset):
342241
dset.dump(dset.fpath, newlines=True)
343242

344243

345-
def plot_class_freq_per_step(freq_dict, act_labels, cat_labels, label_frame_freq):
346-
"""Plot the number of objects detected, normalized by the number of frames
347-
per activity
348-
"""
349-
SMALL_SIZE = 8
350-
MEDIUM_SIZE = 10
351-
BIGGER_SIZE = 8
352-
353-
matplotlib.rc("font", size=BIGGER_SIZE + 3)
354-
matplotlib.rc("xtick", labelsize=BIGGER_SIZE)
355-
matplotlib.rc("ytick", labelsize=BIGGER_SIZE)
356-
357-
fig, ax = plt.subplots()
358-
359-
mat = []
360-
for k, v in freq_dict.items():
361-
mat.append(v)
362-
363-
mat = np.array(mat)
364-
365-
norm_mat = mat / label_frame_freq[:, None]
366-
norm_mat = norm_mat.T
367-
368-
plt.imshow(norm_mat)
369-
plt.colorbar()
370-
371-
plt.xlabel("activities")
372-
plt.ylabel("object class")
373-
374-
plt.xticks(range(len(act_labels)), act_labels, rotation="vertical")
375-
plt.yticks(range(len(cat_labels)), cat_labels)
376-
377-
# plt.show()
378-
plt.savefig("obj_freq_per_act.png", bbox_inches="tight", dpi=300)
379-
380-
381244
def visualize_kwcoco_by_label(dset=None, save_dir=""):
382245
"""Draw the bounding boxes from the kwcoco file on
383246
the associated images
@@ -466,67 +329,6 @@ def visualize_kwcoco_by_label(dset=None, save_dir=""):
466329
plt.close("all")
467330

468331

469-
def reorder_images(dset):
470-
# Data paths
471-
data_dir = "/data/PTG/cooking/"
472-
ros_bags_dir = f"{data_dir}/ros_bags/"
473-
coffee_ros_bags_dir = f"{ros_bags_dir}/coffee/coffee_extracted/"
474-
tea_ros_bags_dir = f"{ros_bags_dir}/tea/tea_extracted/"
475-
476-
# Load kwcoco file
477-
dset = load_kwcoco(dset)
478-
gid_to_aids = dset.index.gid_to_aids
479-
480-
new_dset = kwcoco.CocoDataset()
481-
482-
new_dset.dataset["info"] = dset.dataset["info"].copy()
483-
for cat_id, cat in dset.cats.items():
484-
new_dset.add_category(**cat)
485-
486-
for video_id, video in dset.index.videos.items():
487-
# Add video to new dataset
488-
if "_extracted" in video["name"]:
489-
video["name"] = video["name"].split("_extracted")[0]
490-
new_dset.add_video(**video)
491-
492-
# Find folder of images for video
493-
video_name = video["name"]
494-
if "tea" in video_name:
495-
images_dir = f"{tea_ros_bags_dir}/{video_name}_extracted/images"
496-
else:
497-
images_dir = f"{coffee_ros_bags_dir}/{video_name}_extracted/images"
498-
499-
images = glob.glob(f"{images_dir}/*.png")
500-
if not images:
501-
warnings.warn(f"No images found in {video_name}")
502-
images = Re_order(images, len(images))
503-
504-
for image in images:
505-
# Find image in old dataset
506-
image_lookup = dset.index.file_name_to_img
507-
old_img = image_lookup[image]
508-
509-
new_im = old_img.copy()
510-
del new_im["id"]
511-
512-
new_gid = new_dset.add_image(**new_im)
513-
514-
# Add annotations for image
515-
old_aids = gid_to_aids[old_img["id"]]
516-
old_anns = ub.dict_subset(dset.anns, old_aids)
517-
518-
for old_aid, old_ann in old_anns.items():
519-
new_ann = old_ann.copy()
520-
521-
del new_ann["id"]
522-
new_ann["image_id"] = new_gid
523-
new_dset.add_annotation(**new_ann)
524-
525-
new_dset.fpath = dset.fpath.split(".mscoco.json")[0] + "_reordered_imgs.mscoco.json"
526-
new_dset.dump(new_dset.fpath, newlines=True)
527-
print(f"Saved dset to {new_dset.fpath}")
528-
529-
530332
def imgs_to_video(imgs_dir):
531333
"""Convert directory of images to a video"""
532334
video_name = imgs_dir.split("/")[-1] + ".avi"

0 commit comments

Comments
 (0)