diff --git a/.gitignore b/.gitignore index 7707809..b9eba7c 100644 --- a/.gitignore +++ b/.gitignore @@ -9,7 +9,7 @@ build/* _C.* outputs/* checkpoints/*.pt - +*test* # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/README.md b/README.md index dcabf36..cb798a8 100644 --- a/README.md +++ b/README.md @@ -167,6 +167,33 @@ And we will automatically save the tracking visualization results in `OUTPUT_VID > [!WARNING] > We initialize the box prompts on the first frame of the input video. If you want to start from different frame, you can refine `ann_frame_idx` by yourself in our code. +### Grounded-SAM-2 Video Object Tracking with Continuous ID (with Grounding DINO) +Users can upload their own video files and specify custom text prompts for grounding and tracking using the Grounding DINO and SAM 2 frameworks. To do this, execute the script: + + +```python +grounded_sam2_tracking_demo_with_continuous_id.py +``` + +You can customize various parameters including: + +- `text`: The grounding text prompt. +- `video_dir`: Directory containing the video files. +- `output_dir`: Directory to save the processed output. +- `output_video_path`: Path for the output video. +- `step`: Frame stepping for processing. +- `box_threshold`: box threshold for groundingdino model +- `text_threshold`: text threshold for groundingdino model +Note: This method supports only the mask type of text prompt. + +The demo video is: +[![car tracking demo data](./assets/tracking_car_1.jpg)](./assets/tracking_car.mp4) + + +After running our demo code, you can get the tracking results as follows: +[![car tracking result data](./assets/tracking_car_mask_1.jpg)](./assets/tracking_car_output.mp4) + + ### Citation If you find this project helpful for your research, please consider citing the following BibTeX entry. diff --git a/assets/tracking_car.mp4 b/assets/tracking_car.mp4 new file mode 100644 index 0000000..8994f8d Binary files /dev/null and b/assets/tracking_car.mp4 differ diff --git a/assets/tracking_car_1.jpg b/assets/tracking_car_1.jpg new file mode 100644 index 0000000..9710271 Binary files /dev/null and b/assets/tracking_car_1.jpg differ diff --git a/assets/tracking_car_mask_1.jpg b/assets/tracking_car_mask_1.jpg new file mode 100644 index 0000000..d628600 Binary files /dev/null and b/assets/tracking_car_mask_1.jpg differ diff --git a/assets/tracking_car_output.mp4 b/assets/tracking_car_output.mp4 new file mode 100644 index 0000000..05aa993 Binary files /dev/null and b/assets/tracking_car_output.mp4 differ diff --git a/assets/zebra.mp4 b/assets/zebra.mp4 new file mode 100644 index 0000000..099eefa Binary files /dev/null and b/assets/zebra.mp4 differ diff --git a/assets/zebra_output.mp4 b/assets/zebra_output.mp4 new file mode 100644 index 0000000..e980dd4 Binary files /dev/null and b/assets/zebra_output.mp4 differ diff --git a/grounded_sam2_hf_model_demo.py b/grounded_sam2_hf_model_demo.py index 10353fa..273a6e6 100644 --- a/grounded_sam2_hf_model_demo.py +++ b/grounded_sam2_hf_model_demo.py @@ -3,7 +3,7 @@ import torch import numpy as np import supervision as sv from supervision.draw.color import ColorPalette -from supervision_utils import CUSTOM_COLOR_MAP +from utils.supervision_utils import CUSTOM_COLOR_MAP from PIL import Image from sam2.build_sam import build_sam2 from sam2.sam2_image_predictor import SAM2ImagePredictor diff --git a/grounded_sam2_tracking_demo.py b/grounded_sam2_tracking_demo.py index 566c4a3..4e7b7a4 100644 --- a/grounded_sam2_tracking_demo.py +++ b/grounded_sam2_tracking_demo.py @@ -7,8 +7,8 @@ from PIL import Image from sam2.build_sam import build_sam2_video_predictor, build_sam2 from sam2.sam2_image_predictor import SAM2ImagePredictor from transformers import AutoProcessor, AutoModelForZeroShotObjectDetection -from track_utils import sample_points_from_masks -from video_utils import create_video_from_images +from utils.track_utils import sample_points_from_masks +from utils.video_utils import create_video_from_images """ @@ -40,10 +40,11 @@ grounding_model = AutoModelForZeroShotObjectDetection.from_pretrained(model_id). # setup the input image and text prompt for SAM 2 and Grounding DINO # VERY important: text queries need to be lowercased + end with a dot -text = "children." +text = "car." -# `video_dir` a directory of JPEG frames with filenames like `.jpg` -video_dir = "notebooks/videos/bedroom" +# `video_dir` a directory of JPEG frames with filenames like `.jpg` + +video_dir = "notebooks/videos/car" # scan all the JPEG frame names in this directory frame_names = [ diff --git a/grounded_sam2_tracking_demo_custom_video_input_gd1.0_hf_model.py b/grounded_sam2_tracking_demo_custom_video_input_gd1.0_hf_model.py index 742294e..29a25c6 100644 --- a/grounded_sam2_tracking_demo_custom_video_input_gd1.0_hf_model.py +++ b/grounded_sam2_tracking_demo_custom_video_input_gd1.0_hf_model.py @@ -10,8 +10,8 @@ from PIL import Image from sam2.build_sam import build_sam2_video_predictor, build_sam2 from sam2.sam2_image_predictor import SAM2ImagePredictor from transformers import AutoProcessor, AutoModelForZeroShotObjectDetection -from track_utils import sample_points_from_masks -from video_utils import create_video_from_images +from utils.track_utils import sample_points_from_masks +from utils.video_utils import create_video_from_images """ Hyperparam for Ground and Tracking diff --git a/grounded_sam2_tracking_demo_custom_video_input_gd1.5.py b/grounded_sam2_tracking_demo_custom_video_input_gd1.5.py index 9999145..663e9fe 100644 --- a/grounded_sam2_tracking_demo_custom_video_input_gd1.5.py +++ b/grounded_sam2_tracking_demo_custom_video_input_gd1.5.py @@ -17,8 +17,8 @@ from tqdm import tqdm from PIL import Image from sam2.build_sam import build_sam2_video_predictor, build_sam2 from sam2.sam2_image_predictor import SAM2ImagePredictor -from track_utils import sample_points_from_masks -from video_utils import create_video_from_images +from utils.track_utils import sample_points_from_masks +from utils.video_utils import create_video_from_images """ Hyperparam for Ground and Tracking diff --git a/grounded_sam2_tracking_demo_with_continuous_id.py b/grounded_sam2_tracking_demo_with_continuous_id.py new file mode 100644 index 0000000..3568ae3 --- /dev/null +++ b/grounded_sam2_tracking_demo_with_continuous_id.py @@ -0,0 +1,198 @@ +import os +import cv2 +import torch +import numpy as np +import supervision as sv +from PIL import Image +from sam2.build_sam import build_sam2_video_predictor, build_sam2 +from sam2.sam2_image_predictor import SAM2ImagePredictor +from transformers import AutoProcessor, AutoModelForZeroShotObjectDetection +from utils.track_utils import sample_points_from_masks +from utils.video_utils import create_video_from_images +from utils.common_utils import CommonUtils +from utils.mask_dictionary_model import MaskDictionatyModel, ObjectInfo +import json +import copy + +""" +Step 1: Environment settings and model initialization +""" +# use bfloat16 for the entire notebook +torch.autocast(device_type="cuda", dtype=torch.bfloat16).__enter__() + +if torch.cuda.get_device_properties(0).major >= 8: + # turn on tfloat32 for Ampere GPUs (https://pytorch.org/docs/stable/notes/cuda.html#tensorfloat-32-tf32-on-ampere-devices) + torch.backends.cuda.matmul.allow_tf32 = True + torch.backends.cudnn.allow_tf32 = True + +# init sam image predictor and video predictor model +sam2_checkpoint = "./checkpoints/sam2_hiera_large.pt" +model_cfg = "sam2_hiera_l.yaml" +device = "cuda" if torch.cuda.is_available() else "cpu" +print("device",device) + +video_predictor = build_sam2_video_predictor(model_cfg, sam2_checkpoint) +sam2_image_model = build_sam2(model_cfg, sam2_checkpoint, device=device) +image_predictor = SAM2ImagePredictor(sam2_image_model) + + +# init grounding dino model from huggingface +model_id = "IDEA-Research/grounding-dino-tiny" +processor = AutoProcessor.from_pretrained(model_id) +grounding_model = AutoModelForZeroShotObjectDetection.from_pretrained(model_id).to(device) + + +# setup the input image and text prompt for SAM 2 and Grounding DINO +# VERY important: text queries need to be lowercased + end with a dot +text = "car." + +# `video_dir` a directory of JPEG frames with filenames like `.jpg` +video_dir = "notebooks/videos/car" +# 'output_dir' is the directory to save the annotated frames +output_dir = "./outputs" +# 'output_video_path' is the path to save the final video +output_video_path = "./outputs/output.mp4" +# create the output directory +CommonUtils.creat_dirs(output_dir) +mask_data_dir = os.path.join(output_dir, "mask_data") +json_data_dir = os.path.join(output_dir, "json_data") +result_dir = os.path.join(output_dir, "result") +CommonUtils.creat_dirs(mask_data_dir) +CommonUtils.creat_dirs(json_data_dir) +# scan all the JPEG frame names in this directory +frame_names = [ + p for p in os.listdir(video_dir) + if os.path.splitext(p)[-1] in [".jpg", ".jpeg", ".JPG", ".JPEG"] +] +frame_names.sort(key=lambda p: int(os.path.splitext(p)[0])) + +# init video predictor state +inference_state = video_predictor.init_state(video_path=video_dir) +step = 10 # the step to sample frames for groundedDino predictor + +sam2_masks = MaskDictionatyModel() +PROMPT_TYPE_FOR_VIDEO = "mask" # box, mask or point +objects_count = 0 + +""" +Step 2: Prompt Grounding DINO and SAM image predictor to get the box and mask for all frames +""" +print("Total frames:", len(frame_names)) +for start_frame_idx in range(0, len(frame_names), step): +# prompt grounding dino to get the box coordinates on specific frame + print("start_frame_idx", start_frame_idx) + # continue + img_path = os.path.join(video_dir, frame_names[start_frame_idx]) + image = Image.open(img_path) + image_base_name = frame_names[start_frame_idx].split(".")[0] + mask_dict = MaskDictionatyModel(promote_type = PROMPT_TYPE_FOR_VIDEO, mask_name = f"mask_{image_base_name}.npy") + + # run Grounding DINO on the image + inputs = processor(images=image, text=text, return_tensors="pt").to(device) + with torch.no_grad(): + outputs = grounding_model(**inputs) + + results = processor.post_process_grounded_object_detection( + outputs, + inputs.input_ids, + box_threshold=0.25, + text_threshold=0.25, + target_sizes=[image.size[::-1]] + ) + + # prompt SAM image predictor to get the mask for the object + image_predictor.set_image(np.array(image.convert("RGB"))) + + # process the detection results + input_boxes = results[0]["boxes"] # .cpu().numpy() + # print("results[0]",results[0]) + OBJECTS = results[0]["labels"] + + # prompt SAM 2 image predictor to get the mask for the object + masks, scores, logits = image_predictor.predict( + point_coords=None, + point_labels=None, + box=input_boxes, + multimask_output=False, + ) + # convert the mask shape to (n, H, W) + if masks.ndim == 2: + masks = masks[None] + scores = scores[None] + logits = logits[None] + elif masks.ndim == 4: + masks = masks.squeeze(1) + + """ + Step 3: Register each object's positive points to video predictor + """ + + # If you are using point prompts, we uniformly sample positive points based on the mask + if mask_dict.promote_type == "mask": + mask_dict.add_new_frame_annotation(mask_list=torch.tensor(masks).to(device), box_list=torch.tensor(input_boxes), label_list=OBJECTS) + else: + raise NotImplementedError("SAM 2 video predictor only support mask prompts") + + + """ + Step 4: Propagate the video predictor to get the segmentation results for each frame + """ + objects_count = mask_dict.update_masks(tracking_annotation_dict=sam2_masks, iou_threshold=0.8, objects_count=objects_count) + print("objects_count", objects_count) + video_predictor.reset_state(inference_state) + if len(mask_dict.labels) == 0: + print("No object detected in the frame, skip the frame {}".format(start_frame_idx)) + continue + video_predictor.reset_state(inference_state) + + for object_id, object_info in mask_dict.labels.items(): + frame_idx, out_obj_ids, out_mask_logits = video_predictor.add_new_mask( + inference_state, + start_frame_idx, + object_id, + object_info.mask, + ) + + video_segments = {} # output the following {step} frames tracking masks + for out_frame_idx, out_obj_ids, out_mask_logits in video_predictor.propagate_in_video(inference_state, max_frame_num_to_track=step, start_frame_idx=start_frame_idx): + frame_masks = MaskDictionatyModel() + + for i, out_obj_id in enumerate(out_obj_ids): + out_mask = (out_mask_logits[i] > 0.0) # .cpu().numpy() + object_info = ObjectInfo(instance_id = out_obj_id, mask = out_mask[0], class_name = mask_dict.get_target_class_name(out_obj_id)) + object_info.update_box() + frame_masks.labels[out_obj_id] = object_info + image_base_name = frame_names[out_frame_idx].split(".")[0] + frame_masks.mask_name = f"mask_{image_base_name}.npy" + frame_masks.mask_height = out_mask.shape[-2] + frame_masks.mask_width = out_mask.shape[-1] + + video_segments[out_frame_idx] = frame_masks + sam2_masks = copy.deepcopy(frame_masks) + + print("video_segments:", len(video_segments)) + """ + Step 5: save the tracking masks and json files + """ + for frame_idx, frame_masks_info in video_segments.items(): + mask = frame_masks_info.labels + mask_img = torch.zeros(frame_masks_info.mask_height, frame_masks_info.mask_width) + for obj_id, obj_info in mask.items(): + mask_img[obj_info.mask == True] = obj_id + + mask_img = mask_img.numpy().astype(np.uint16) + np.save(os.path.join(mask_data_dir, frame_masks_info.mask_name), mask_img) + + json_data = frame_masks_info.to_dict() + json_data_path = os.path.join(json_data_dir, frame_masks_info.mask_name.replace(".npy", ".json")) + with open(json_data_path, "w") as f: + json.dump(json_data, f) + + + +""" +Step 6: Draw the results and save the video +""" +CommonUtils.draw_masks_and_box(video_dir, mask_data_dir, json_data_dir, result_dir) + +create_video_from_images(result_dir, output_video_path, frame_rate=15) \ No newline at end of file diff --git a/grounded_sam2_tracking_demo_with_gd1.5.py b/grounded_sam2_tracking_demo_with_gd1.5.py index 13f0f7d..8be2daa 100644 --- a/grounded_sam2_tracking_demo_with_gd1.5.py +++ b/grounded_sam2_tracking_demo_with_gd1.5.py @@ -14,8 +14,8 @@ import supervision as sv from PIL import Image from sam2.build_sam import build_sam2_video_predictor, build_sam2 from sam2.sam2_image_predictor import SAM2ImagePredictor -from track_utils import sample_points_from_masks -from video_utils import create_video_from_images +from utils.track_utils import sample_points_from_masks +from utils.video_utils import create_video_from_images """ diff --git a/notebooks/videos/car/00001.jpg b/notebooks/videos/car/00001.jpg new file mode 100644 index 0000000..9710271 Binary files /dev/null and b/notebooks/videos/car/00001.jpg differ diff --git a/notebooks/videos/car/00002.jpg b/notebooks/videos/car/00002.jpg new file mode 100644 index 0000000..2d089d5 Binary files /dev/null and b/notebooks/videos/car/00002.jpg differ diff --git a/notebooks/videos/car/00003.jpg b/notebooks/videos/car/00003.jpg new file mode 100644 index 0000000..d6a8aad Binary files /dev/null and b/notebooks/videos/car/00003.jpg differ diff --git a/notebooks/videos/car/00004.jpg b/notebooks/videos/car/00004.jpg new file mode 100644 index 0000000..13bd801 Binary files /dev/null and b/notebooks/videos/car/00004.jpg differ diff --git a/notebooks/videos/car/00005.jpg b/notebooks/videos/car/00005.jpg new file mode 100644 index 0000000..81064b4 Binary files /dev/null and b/notebooks/videos/car/00005.jpg differ diff --git a/notebooks/videos/car/00006.jpg b/notebooks/videos/car/00006.jpg new file mode 100644 index 0000000..5cc5362 Binary files /dev/null and b/notebooks/videos/car/00006.jpg differ diff --git a/notebooks/videos/car/00007.jpg b/notebooks/videos/car/00007.jpg new file mode 100644 index 0000000..24d8a24 Binary files /dev/null and b/notebooks/videos/car/00007.jpg differ diff --git a/notebooks/videos/car/00008.jpg b/notebooks/videos/car/00008.jpg new file mode 100644 index 0000000..fa63b55 Binary files /dev/null and b/notebooks/videos/car/00008.jpg differ diff --git a/notebooks/videos/car/00009.jpg b/notebooks/videos/car/00009.jpg new file mode 100644 index 0000000..067589e Binary files /dev/null and b/notebooks/videos/car/00009.jpg differ diff --git a/notebooks/videos/car/00010.jpg b/notebooks/videos/car/00010.jpg new file mode 100644 index 0000000..e3ce9e0 Binary files /dev/null and b/notebooks/videos/car/00010.jpg differ diff --git a/notebooks/videos/car/00011.jpg b/notebooks/videos/car/00011.jpg new file mode 100644 index 0000000..5df77a3 Binary files /dev/null and b/notebooks/videos/car/00011.jpg differ diff --git a/notebooks/videos/car/00012.jpg b/notebooks/videos/car/00012.jpg new file mode 100644 index 0000000..b8329e6 Binary files /dev/null and b/notebooks/videos/car/00012.jpg differ diff --git a/notebooks/videos/car/00013.jpg b/notebooks/videos/car/00013.jpg new file mode 100644 index 0000000..91870c2 Binary files /dev/null and b/notebooks/videos/car/00013.jpg differ diff --git a/notebooks/videos/car/00014.jpg b/notebooks/videos/car/00014.jpg new file mode 100644 index 0000000..51ff64a Binary files /dev/null and b/notebooks/videos/car/00014.jpg differ diff --git a/notebooks/videos/car/00015.jpg b/notebooks/videos/car/00015.jpg new file mode 100644 index 0000000..a97d97a Binary files /dev/null and b/notebooks/videos/car/00015.jpg differ diff --git a/notebooks/videos/car/00016.jpg b/notebooks/videos/car/00016.jpg new file mode 100644 index 0000000..f283b23 Binary files /dev/null and b/notebooks/videos/car/00016.jpg differ diff --git a/notebooks/videos/car/00017.jpg b/notebooks/videos/car/00017.jpg new file mode 100644 index 0000000..ac24fa2 Binary files /dev/null and b/notebooks/videos/car/00017.jpg differ diff --git a/notebooks/videos/car/00018.jpg b/notebooks/videos/car/00018.jpg new file mode 100644 index 0000000..e9296a1 Binary files /dev/null and b/notebooks/videos/car/00018.jpg differ diff --git a/notebooks/videos/car/00019.jpg b/notebooks/videos/car/00019.jpg new file mode 100644 index 0000000..2c09b10 Binary files /dev/null and b/notebooks/videos/car/00019.jpg differ diff --git a/notebooks/videos/car/00020.jpg b/notebooks/videos/car/00020.jpg new file mode 100644 index 0000000..80e1915 Binary files /dev/null and b/notebooks/videos/car/00020.jpg differ diff --git a/notebooks/videos/car/00021.jpg b/notebooks/videos/car/00021.jpg new file mode 100644 index 0000000..f3b8b67 Binary files /dev/null and b/notebooks/videos/car/00021.jpg differ diff --git a/notebooks/videos/car/00022.jpg b/notebooks/videos/car/00022.jpg new file mode 100644 index 0000000..6e85bbb Binary files /dev/null and b/notebooks/videos/car/00022.jpg differ diff --git a/notebooks/videos/car/00023.jpg b/notebooks/videos/car/00023.jpg new file mode 100644 index 0000000..40eeb54 Binary files /dev/null and b/notebooks/videos/car/00023.jpg differ diff --git a/notebooks/videos/car/00024.jpg b/notebooks/videos/car/00024.jpg new file mode 100644 index 0000000..1c6878c Binary files /dev/null and b/notebooks/videos/car/00024.jpg differ diff --git a/notebooks/videos/car/00025.jpg b/notebooks/videos/car/00025.jpg new file mode 100644 index 0000000..333f7e4 Binary files /dev/null and b/notebooks/videos/car/00025.jpg differ diff --git a/notebooks/videos/car/00026.jpg b/notebooks/videos/car/00026.jpg new file mode 100644 index 0000000..b5f5fcf Binary files /dev/null and b/notebooks/videos/car/00026.jpg differ diff --git a/notebooks/videos/car/00027.jpg b/notebooks/videos/car/00027.jpg new file mode 100644 index 0000000..2b39886 Binary files /dev/null and b/notebooks/videos/car/00027.jpg differ diff --git a/notebooks/videos/car/00028.jpg b/notebooks/videos/car/00028.jpg new file mode 100644 index 0000000..b9557b7 Binary files /dev/null and b/notebooks/videos/car/00028.jpg differ diff --git a/notebooks/videos/car/00029.jpg b/notebooks/videos/car/00029.jpg new file mode 100644 index 0000000..ec2d6bc Binary files /dev/null and b/notebooks/videos/car/00029.jpg differ diff --git a/notebooks/videos/car/00030.jpg b/notebooks/videos/car/00030.jpg new file mode 100644 index 0000000..21c6697 Binary files /dev/null and b/notebooks/videos/car/00030.jpg differ diff --git a/notebooks/videos/car/00031.jpg b/notebooks/videos/car/00031.jpg new file mode 100644 index 0000000..cfa9de2 Binary files /dev/null and b/notebooks/videos/car/00031.jpg differ diff --git a/notebooks/videos/car/00032.jpg b/notebooks/videos/car/00032.jpg new file mode 100644 index 0000000..bb8d3cc Binary files /dev/null and b/notebooks/videos/car/00032.jpg differ diff --git a/notebooks/videos/car/00033.jpg b/notebooks/videos/car/00033.jpg new file mode 100644 index 0000000..f6222a1 Binary files /dev/null and b/notebooks/videos/car/00033.jpg differ diff --git a/notebooks/videos/car/00034.jpg b/notebooks/videos/car/00034.jpg new file mode 100644 index 0000000..3d21a0b Binary files /dev/null and b/notebooks/videos/car/00034.jpg differ diff --git a/notebooks/videos/car/00035.jpg b/notebooks/videos/car/00035.jpg new file mode 100644 index 0000000..66088b7 Binary files /dev/null and b/notebooks/videos/car/00035.jpg differ diff --git a/notebooks/videos/car/00036.jpg b/notebooks/videos/car/00036.jpg new file mode 100644 index 0000000..9c56ff1 Binary files /dev/null and b/notebooks/videos/car/00036.jpg differ diff --git a/notebooks/videos/car/00037.jpg b/notebooks/videos/car/00037.jpg new file mode 100644 index 0000000..f9bc9a0 Binary files /dev/null and b/notebooks/videos/car/00037.jpg differ diff --git a/notebooks/videos/car/00038.jpg b/notebooks/videos/car/00038.jpg new file mode 100644 index 0000000..03e95f7 Binary files /dev/null and b/notebooks/videos/car/00038.jpg differ diff --git a/notebooks/videos/car/00039.jpg b/notebooks/videos/car/00039.jpg new file mode 100644 index 0000000..eacddaa Binary files /dev/null and b/notebooks/videos/car/00039.jpg differ diff --git a/notebooks/videos/car/00040.jpg b/notebooks/videos/car/00040.jpg new file mode 100644 index 0000000..738b867 Binary files /dev/null and b/notebooks/videos/car/00040.jpg differ diff --git a/notebooks/videos/car/00041.jpg b/notebooks/videos/car/00041.jpg new file mode 100644 index 0000000..447f0e8 Binary files /dev/null and b/notebooks/videos/car/00041.jpg differ diff --git a/notebooks/videos/car/00042.jpg b/notebooks/videos/car/00042.jpg new file mode 100644 index 0000000..2b3a8e1 Binary files /dev/null and b/notebooks/videos/car/00042.jpg differ diff --git a/notebooks/videos/car/00043.jpg b/notebooks/videos/car/00043.jpg new file mode 100644 index 0000000..42dbdc8 Binary files /dev/null and b/notebooks/videos/car/00043.jpg differ diff --git a/notebooks/videos/car/00044.jpg b/notebooks/videos/car/00044.jpg new file mode 100644 index 0000000..329fe0d Binary files /dev/null and b/notebooks/videos/car/00044.jpg differ diff --git a/notebooks/videos/car/00045.jpg b/notebooks/videos/car/00045.jpg new file mode 100644 index 0000000..f4d3c4d Binary files /dev/null and b/notebooks/videos/car/00045.jpg differ diff --git a/notebooks/videos/car/00046.jpg b/notebooks/videos/car/00046.jpg new file mode 100644 index 0000000..f83e119 Binary files /dev/null and b/notebooks/videos/car/00046.jpg differ diff --git a/notebooks/videos/car/00047.jpg b/notebooks/videos/car/00047.jpg new file mode 100644 index 0000000..b91be21 Binary files /dev/null and b/notebooks/videos/car/00047.jpg differ diff --git a/notebooks/videos/car/00048.jpg b/notebooks/videos/car/00048.jpg new file mode 100644 index 0000000..7da49fd Binary files /dev/null and b/notebooks/videos/car/00048.jpg differ diff --git a/notebooks/videos/car/00049.jpg b/notebooks/videos/car/00049.jpg new file mode 100644 index 0000000..8ed9e08 Binary files /dev/null and b/notebooks/videos/car/00049.jpg differ diff --git a/notebooks/videos/car/00050.jpg b/notebooks/videos/car/00050.jpg new file mode 100644 index 0000000..15cf06e Binary files /dev/null and b/notebooks/videos/car/00050.jpg differ diff --git a/notebooks/videos/car/00051.jpg b/notebooks/videos/car/00051.jpg new file mode 100644 index 0000000..5155136 Binary files /dev/null and b/notebooks/videos/car/00051.jpg differ diff --git a/notebooks/videos/car/00052.jpg b/notebooks/videos/car/00052.jpg new file mode 100644 index 0000000..d55523b Binary files /dev/null and b/notebooks/videos/car/00052.jpg differ diff --git a/notebooks/videos/car/00053.jpg b/notebooks/videos/car/00053.jpg new file mode 100644 index 0000000..abc6ac1 Binary files /dev/null and b/notebooks/videos/car/00053.jpg differ diff --git a/notebooks/videos/car/00054.jpg b/notebooks/videos/car/00054.jpg new file mode 100644 index 0000000..f3b8c2f Binary files /dev/null and b/notebooks/videos/car/00054.jpg differ diff --git a/notebooks/videos/car/00055.jpg b/notebooks/videos/car/00055.jpg new file mode 100644 index 0000000..f219e80 Binary files /dev/null and b/notebooks/videos/car/00055.jpg differ diff --git a/notebooks/videos/car/00056.jpg b/notebooks/videos/car/00056.jpg new file mode 100644 index 0000000..60e37d1 Binary files /dev/null and b/notebooks/videos/car/00056.jpg differ diff --git a/notebooks/videos/car/00057.jpg b/notebooks/videos/car/00057.jpg new file mode 100644 index 0000000..f2f4d98 Binary files /dev/null and b/notebooks/videos/car/00057.jpg differ diff --git a/notebooks/videos/car/00058.jpg b/notebooks/videos/car/00058.jpg new file mode 100644 index 0000000..5bcd7b2 Binary files /dev/null and b/notebooks/videos/car/00058.jpg differ diff --git a/notebooks/videos/car/00059.jpg b/notebooks/videos/car/00059.jpg new file mode 100644 index 0000000..5e2827e Binary files /dev/null and b/notebooks/videos/car/00059.jpg differ diff --git a/notebooks/videos/car/00060.jpg b/notebooks/videos/car/00060.jpg new file mode 100644 index 0000000..1feb4fb Binary files /dev/null and b/notebooks/videos/car/00060.jpg differ diff --git a/notebooks/videos/car/00061.jpg b/notebooks/videos/car/00061.jpg new file mode 100644 index 0000000..9e8791b Binary files /dev/null and b/notebooks/videos/car/00061.jpg differ diff --git a/notebooks/videos/car/00062.jpg b/notebooks/videos/car/00062.jpg new file mode 100644 index 0000000..cd9e70b Binary files /dev/null and b/notebooks/videos/car/00062.jpg differ diff --git a/notebooks/videos/car/00063.jpg b/notebooks/videos/car/00063.jpg new file mode 100644 index 0000000..0bf2b8b Binary files /dev/null and b/notebooks/videos/car/00063.jpg differ diff --git a/notebooks/videos/car/00064.jpg b/notebooks/videos/car/00064.jpg new file mode 100644 index 0000000..3a70f85 Binary files /dev/null and b/notebooks/videos/car/00064.jpg differ diff --git a/notebooks/videos/car/00065.jpg b/notebooks/videos/car/00065.jpg new file mode 100644 index 0000000..18ea161 Binary files /dev/null and b/notebooks/videos/car/00065.jpg differ diff --git a/notebooks/videos/car/00066.jpg b/notebooks/videos/car/00066.jpg new file mode 100644 index 0000000..746bd03 Binary files /dev/null and b/notebooks/videos/car/00066.jpg differ diff --git a/notebooks/videos/car/00067.jpg b/notebooks/videos/car/00067.jpg new file mode 100644 index 0000000..919ed1d Binary files /dev/null and b/notebooks/videos/car/00067.jpg differ diff --git a/notebooks/videos/car/00068.jpg b/notebooks/videos/car/00068.jpg new file mode 100644 index 0000000..255af9e Binary files /dev/null and b/notebooks/videos/car/00068.jpg differ diff --git a/notebooks/videos/car/00069.jpg b/notebooks/videos/car/00069.jpg new file mode 100644 index 0000000..1246683 Binary files /dev/null and b/notebooks/videos/car/00069.jpg differ diff --git a/notebooks/videos/car/00070.jpg b/notebooks/videos/car/00070.jpg new file mode 100644 index 0000000..d154fea Binary files /dev/null and b/notebooks/videos/car/00070.jpg differ diff --git a/notebooks/videos/car/00071.jpg b/notebooks/videos/car/00071.jpg new file mode 100644 index 0000000..668c506 Binary files /dev/null and b/notebooks/videos/car/00071.jpg differ diff --git a/notebooks/videos/car/00072.jpg b/notebooks/videos/car/00072.jpg new file mode 100644 index 0000000..386e08a Binary files /dev/null and b/notebooks/videos/car/00072.jpg differ diff --git a/notebooks/videos/car/00073.jpg b/notebooks/videos/car/00073.jpg new file mode 100644 index 0000000..8920a2f Binary files /dev/null and b/notebooks/videos/car/00073.jpg differ diff --git a/notebooks/videos/car/00074.jpg b/notebooks/videos/car/00074.jpg new file mode 100644 index 0000000..56f50b2 Binary files /dev/null and b/notebooks/videos/car/00074.jpg differ diff --git a/notebooks/videos/car/00075.jpg b/notebooks/videos/car/00075.jpg new file mode 100644 index 0000000..9bfcc44 Binary files /dev/null and b/notebooks/videos/car/00075.jpg differ diff --git a/notebooks/videos/car/00076.jpg b/notebooks/videos/car/00076.jpg new file mode 100644 index 0000000..2555bd5 Binary files /dev/null and b/notebooks/videos/car/00076.jpg differ diff --git a/notebooks/videos/car/00077.jpg b/notebooks/videos/car/00077.jpg new file mode 100644 index 0000000..11a71d8 Binary files /dev/null and b/notebooks/videos/car/00077.jpg differ diff --git a/notebooks/videos/car/00078.jpg b/notebooks/videos/car/00078.jpg new file mode 100644 index 0000000..124319f Binary files /dev/null and b/notebooks/videos/car/00078.jpg differ diff --git a/notebooks/videos/car/00079.jpg b/notebooks/videos/car/00079.jpg new file mode 100644 index 0000000..453bb97 Binary files /dev/null and b/notebooks/videos/car/00079.jpg differ diff --git a/notebooks/videos/car/00080.jpg b/notebooks/videos/car/00080.jpg new file mode 100644 index 0000000..44d5585 Binary files /dev/null and b/notebooks/videos/car/00080.jpg differ diff --git a/notebooks/videos/car/00081.jpg b/notebooks/videos/car/00081.jpg new file mode 100644 index 0000000..74aea69 Binary files /dev/null and b/notebooks/videos/car/00081.jpg differ diff --git a/notebooks/videos/car/00082.jpg b/notebooks/videos/car/00082.jpg new file mode 100644 index 0000000..7011042 Binary files /dev/null and b/notebooks/videos/car/00082.jpg differ diff --git a/notebooks/videos/car/00083.jpg b/notebooks/videos/car/00083.jpg new file mode 100644 index 0000000..10f2932 Binary files /dev/null and b/notebooks/videos/car/00083.jpg differ diff --git a/notebooks/videos/car/00084.jpg b/notebooks/videos/car/00084.jpg new file mode 100644 index 0000000..c4c55ee Binary files /dev/null and b/notebooks/videos/car/00084.jpg differ diff --git a/notebooks/videos/car/00085.jpg b/notebooks/videos/car/00085.jpg new file mode 100644 index 0000000..16afaa9 Binary files /dev/null and b/notebooks/videos/car/00085.jpg differ diff --git a/notebooks/videos/car/00086.jpg b/notebooks/videos/car/00086.jpg new file mode 100644 index 0000000..ce80569 Binary files /dev/null and b/notebooks/videos/car/00086.jpg differ diff --git a/notebooks/videos/car/00087.jpg b/notebooks/videos/car/00087.jpg new file mode 100644 index 0000000..9ed9195 Binary files /dev/null and b/notebooks/videos/car/00087.jpg differ diff --git a/notebooks/videos/car/00088.jpg b/notebooks/videos/car/00088.jpg new file mode 100644 index 0000000..5bd1a89 Binary files /dev/null and b/notebooks/videos/car/00088.jpg differ diff --git a/notebooks/videos/car/00089.jpg b/notebooks/videos/car/00089.jpg new file mode 100644 index 0000000..296a16d Binary files /dev/null and b/notebooks/videos/car/00089.jpg differ diff --git a/notebooks/videos/car/00090.jpg b/notebooks/videos/car/00090.jpg new file mode 100644 index 0000000..b7a1557 Binary files /dev/null and b/notebooks/videos/car/00090.jpg differ diff --git a/notebooks/videos/car/00091.jpg b/notebooks/videos/car/00091.jpg new file mode 100644 index 0000000..2db928d Binary files /dev/null and b/notebooks/videos/car/00091.jpg differ diff --git a/notebooks/videos/car/00092.jpg b/notebooks/videos/car/00092.jpg new file mode 100644 index 0000000..4b5c424 Binary files /dev/null and b/notebooks/videos/car/00092.jpg differ diff --git a/notebooks/videos/car/00093.jpg b/notebooks/videos/car/00093.jpg new file mode 100644 index 0000000..efab707 Binary files /dev/null and b/notebooks/videos/car/00093.jpg differ diff --git a/notebooks/videos/car/00094.jpg b/notebooks/videos/car/00094.jpg new file mode 100644 index 0000000..d392b26 Binary files /dev/null and b/notebooks/videos/car/00094.jpg differ diff --git a/notebooks/videos/car/00095.jpg b/notebooks/videos/car/00095.jpg new file mode 100644 index 0000000..ffeea13 Binary files /dev/null and b/notebooks/videos/car/00095.jpg differ diff --git a/notebooks/videos/car/00096.jpg b/notebooks/videos/car/00096.jpg new file mode 100644 index 0000000..14a9f90 Binary files /dev/null and b/notebooks/videos/car/00096.jpg differ diff --git a/notebooks/videos/car/00097.jpg b/notebooks/videos/car/00097.jpg new file mode 100644 index 0000000..8bce009 Binary files /dev/null and b/notebooks/videos/car/00097.jpg differ diff --git a/notebooks/videos/car/00098.jpg b/notebooks/videos/car/00098.jpg new file mode 100644 index 0000000..7caf616 Binary files /dev/null and b/notebooks/videos/car/00098.jpg differ diff --git a/notebooks/videos/car/00099.jpg b/notebooks/videos/car/00099.jpg new file mode 100644 index 0000000..0295032 Binary files /dev/null and b/notebooks/videos/car/00099.jpg differ diff --git a/notebooks/videos/car/00100.jpg b/notebooks/videos/car/00100.jpg new file mode 100644 index 0000000..78752cc Binary files /dev/null and b/notebooks/videos/car/00100.jpg differ diff --git a/notebooks/videos/car/00101.jpg b/notebooks/videos/car/00101.jpg new file mode 100644 index 0000000..3c88da4 Binary files /dev/null and b/notebooks/videos/car/00101.jpg differ diff --git a/notebooks/videos/car/00102.jpg b/notebooks/videos/car/00102.jpg new file mode 100644 index 0000000..e6b75ce Binary files /dev/null and b/notebooks/videos/car/00102.jpg differ diff --git a/notebooks/videos/car/00103.jpg b/notebooks/videos/car/00103.jpg new file mode 100644 index 0000000..dd7f4d4 Binary files /dev/null and b/notebooks/videos/car/00103.jpg differ diff --git a/notebooks/videos/car/00104.jpg b/notebooks/videos/car/00104.jpg new file mode 100644 index 0000000..7568fd0 Binary files /dev/null and b/notebooks/videos/car/00104.jpg differ diff --git a/notebooks/videos/car/00105.jpg b/notebooks/videos/car/00105.jpg new file mode 100644 index 0000000..aedb80d Binary files /dev/null and b/notebooks/videos/car/00105.jpg differ diff --git a/notebooks/videos/car/00106.jpg b/notebooks/videos/car/00106.jpg new file mode 100644 index 0000000..8aebd73 Binary files /dev/null and b/notebooks/videos/car/00106.jpg differ diff --git a/notebooks/videos/car/00107.jpg b/notebooks/videos/car/00107.jpg new file mode 100644 index 0000000..8e3a5db Binary files /dev/null and b/notebooks/videos/car/00107.jpg differ diff --git a/notebooks/videos/car/00108.jpg b/notebooks/videos/car/00108.jpg new file mode 100644 index 0000000..c448914 Binary files /dev/null and b/notebooks/videos/car/00108.jpg differ diff --git a/notebooks/videos/car/00109.jpg b/notebooks/videos/car/00109.jpg new file mode 100644 index 0000000..ca94d91 Binary files /dev/null and b/notebooks/videos/car/00109.jpg differ diff --git a/notebooks/videos/car/00110.jpg b/notebooks/videos/car/00110.jpg new file mode 100644 index 0000000..d160eb1 Binary files /dev/null and b/notebooks/videos/car/00110.jpg differ diff --git a/notebooks/videos/car/00111.jpg b/notebooks/videos/car/00111.jpg new file mode 100644 index 0000000..fd77ca8 Binary files /dev/null and b/notebooks/videos/car/00111.jpg differ diff --git a/notebooks/videos/car/00112.jpg b/notebooks/videos/car/00112.jpg new file mode 100644 index 0000000..5af6f0d Binary files /dev/null and b/notebooks/videos/car/00112.jpg differ diff --git a/notebooks/videos/car/00113.jpg b/notebooks/videos/car/00113.jpg new file mode 100644 index 0000000..92f8112 Binary files /dev/null and b/notebooks/videos/car/00113.jpg differ diff --git a/notebooks/videos/car/00114.jpg b/notebooks/videos/car/00114.jpg new file mode 100644 index 0000000..dabbcf2 Binary files /dev/null and b/notebooks/videos/car/00114.jpg differ diff --git a/notebooks/videos/car/00115.jpg b/notebooks/videos/car/00115.jpg new file mode 100644 index 0000000..4a4fd06 Binary files /dev/null and b/notebooks/videos/car/00115.jpg differ diff --git a/notebooks/videos/car/00116.jpg b/notebooks/videos/car/00116.jpg new file mode 100644 index 0000000..62b4143 Binary files /dev/null and b/notebooks/videos/car/00116.jpg differ diff --git a/notebooks/videos/car/00117.jpg b/notebooks/videos/car/00117.jpg new file mode 100644 index 0000000..3395e64 Binary files /dev/null and b/notebooks/videos/car/00117.jpg differ diff --git a/notebooks/videos/car/00118.jpg b/notebooks/videos/car/00118.jpg new file mode 100644 index 0000000..7fcf1b5 Binary files /dev/null and b/notebooks/videos/car/00118.jpg differ diff --git a/notebooks/videos/car/00119.jpg b/notebooks/videos/car/00119.jpg new file mode 100644 index 0000000..063fd27 Binary files /dev/null and b/notebooks/videos/car/00119.jpg differ diff --git a/notebooks/videos/car/00120.jpg b/notebooks/videos/car/00120.jpg new file mode 100644 index 0000000..db31eb1 Binary files /dev/null and b/notebooks/videos/car/00120.jpg differ diff --git a/notebooks/videos/car/00121.jpg b/notebooks/videos/car/00121.jpg new file mode 100644 index 0000000..3f5317f Binary files /dev/null and b/notebooks/videos/car/00121.jpg differ diff --git a/notebooks/videos/car/00122.jpg b/notebooks/videos/car/00122.jpg new file mode 100644 index 0000000..674bf7a Binary files /dev/null and b/notebooks/videos/car/00122.jpg differ diff --git a/notebooks/videos/car/00123.jpg b/notebooks/videos/car/00123.jpg new file mode 100644 index 0000000..0c0c0e0 Binary files /dev/null and b/notebooks/videos/car/00123.jpg differ diff --git a/notebooks/videos/car/00124.jpg b/notebooks/videos/car/00124.jpg new file mode 100644 index 0000000..ce44f19 Binary files /dev/null and b/notebooks/videos/car/00124.jpg differ diff --git a/notebooks/videos/car/00125.jpg b/notebooks/videos/car/00125.jpg new file mode 100644 index 0000000..52b13b7 Binary files /dev/null and b/notebooks/videos/car/00125.jpg differ diff --git a/notebooks/videos/car/00126.jpg b/notebooks/videos/car/00126.jpg new file mode 100644 index 0000000..ad22fc6 Binary files /dev/null and b/notebooks/videos/car/00126.jpg differ diff --git a/notebooks/videos/car/00127.jpg b/notebooks/videos/car/00127.jpg new file mode 100644 index 0000000..b69478a Binary files /dev/null and b/notebooks/videos/car/00127.jpg differ diff --git a/notebooks/videos/car/00128.jpg b/notebooks/videos/car/00128.jpg new file mode 100644 index 0000000..b962ea4 Binary files /dev/null and b/notebooks/videos/car/00128.jpg differ diff --git a/notebooks/videos/car/00129.jpg b/notebooks/videos/car/00129.jpg new file mode 100644 index 0000000..7ee2821 Binary files /dev/null and b/notebooks/videos/car/00129.jpg differ diff --git a/notebooks/videos/car/00130.jpg b/notebooks/videos/car/00130.jpg new file mode 100644 index 0000000..b2a520a Binary files /dev/null and b/notebooks/videos/car/00130.jpg differ diff --git a/notebooks/videos/car/00131.jpg b/notebooks/videos/car/00131.jpg new file mode 100644 index 0000000..108833d Binary files /dev/null and b/notebooks/videos/car/00131.jpg differ diff --git a/notebooks/videos/car/00132.jpg b/notebooks/videos/car/00132.jpg new file mode 100644 index 0000000..4879b0f Binary files /dev/null and b/notebooks/videos/car/00132.jpg differ diff --git a/notebooks/videos/car/00133.jpg b/notebooks/videos/car/00133.jpg new file mode 100644 index 0000000..ade504f Binary files /dev/null and b/notebooks/videos/car/00133.jpg differ diff --git a/notebooks/videos/car/00134.jpg b/notebooks/videos/car/00134.jpg new file mode 100644 index 0000000..ba0df56 Binary files /dev/null and b/notebooks/videos/car/00134.jpg differ diff --git a/notebooks/videos/car/00135.jpg b/notebooks/videos/car/00135.jpg new file mode 100644 index 0000000..7608f92 Binary files /dev/null and b/notebooks/videos/car/00135.jpg differ diff --git a/notebooks/videos/car/00136.jpg b/notebooks/videos/car/00136.jpg new file mode 100644 index 0000000..befcd47 Binary files /dev/null and b/notebooks/videos/car/00136.jpg differ diff --git a/notebooks/videos/car/00137.jpg b/notebooks/videos/car/00137.jpg new file mode 100644 index 0000000..b4f2a5f Binary files /dev/null and b/notebooks/videos/car/00137.jpg differ diff --git a/notebooks/videos/car/00138.jpg b/notebooks/videos/car/00138.jpg new file mode 100644 index 0000000..7c5fa00 Binary files /dev/null and b/notebooks/videos/car/00138.jpg differ diff --git a/notebooks/videos/car/00139.jpg b/notebooks/videos/car/00139.jpg new file mode 100644 index 0000000..0cdbd9f Binary files /dev/null and b/notebooks/videos/car/00139.jpg differ diff --git a/notebooks/videos/car/00140.jpg b/notebooks/videos/car/00140.jpg new file mode 100644 index 0000000..a7bed57 Binary files /dev/null and b/notebooks/videos/car/00140.jpg differ diff --git a/notebooks/videos/car/00141.jpg b/notebooks/videos/car/00141.jpg new file mode 100644 index 0000000..d98cf8f Binary files /dev/null and b/notebooks/videos/car/00141.jpg differ diff --git a/notebooks/videos/car/00142.jpg b/notebooks/videos/car/00142.jpg new file mode 100644 index 0000000..15c217a Binary files /dev/null and b/notebooks/videos/car/00142.jpg differ diff --git a/notebooks/videos/car/00143.jpg b/notebooks/videos/car/00143.jpg new file mode 100644 index 0000000..3e6b40a Binary files /dev/null and b/notebooks/videos/car/00143.jpg differ diff --git a/notebooks/videos/car/00144.jpg b/notebooks/videos/car/00144.jpg new file mode 100644 index 0000000..9f8543b Binary files /dev/null and b/notebooks/videos/car/00144.jpg differ diff --git a/notebooks/videos/car/00145.jpg b/notebooks/videos/car/00145.jpg new file mode 100644 index 0000000..0a51b7e Binary files /dev/null and b/notebooks/videos/car/00145.jpg differ diff --git a/notebooks/videos/car/00146.jpg b/notebooks/videos/car/00146.jpg new file mode 100644 index 0000000..1e4aa62 Binary files /dev/null and b/notebooks/videos/car/00146.jpg differ diff --git a/notebooks/videos/car/00147.jpg b/notebooks/videos/car/00147.jpg new file mode 100644 index 0000000..18baec7 Binary files /dev/null and b/notebooks/videos/car/00147.jpg differ diff --git a/notebooks/videos/car/00148.jpg b/notebooks/videos/car/00148.jpg new file mode 100644 index 0000000..f16f92b Binary files /dev/null and b/notebooks/videos/car/00148.jpg differ diff --git a/notebooks/videos/car/00149.jpg b/notebooks/videos/car/00149.jpg new file mode 100644 index 0000000..be0968a Binary files /dev/null and b/notebooks/videos/car/00149.jpg differ diff --git a/notebooks/videos/car/00150.jpg b/notebooks/videos/car/00150.jpg new file mode 100644 index 0000000..d6da6ae Binary files /dev/null and b/notebooks/videos/car/00150.jpg differ diff --git a/notebooks/videos/car/00151.jpg b/notebooks/videos/car/00151.jpg new file mode 100644 index 0000000..18c1ea5 Binary files /dev/null and b/notebooks/videos/car/00151.jpg differ diff --git a/notebooks/videos/car/00152.jpg b/notebooks/videos/car/00152.jpg new file mode 100644 index 0000000..1e6e065 Binary files /dev/null and b/notebooks/videos/car/00152.jpg differ diff --git a/notebooks/videos/car/00153.jpg b/notebooks/videos/car/00153.jpg new file mode 100644 index 0000000..e86bcb0 Binary files /dev/null and b/notebooks/videos/car/00153.jpg differ diff --git a/notebooks/videos/car/00154.jpg b/notebooks/videos/car/00154.jpg new file mode 100644 index 0000000..9f4e761 Binary files /dev/null and b/notebooks/videos/car/00154.jpg differ diff --git a/notebooks/videos/car/00155.jpg b/notebooks/videos/car/00155.jpg new file mode 100644 index 0000000..9fab722 Binary files /dev/null and b/notebooks/videos/car/00155.jpg differ diff --git a/notebooks/videos/car/00156.jpg b/notebooks/videos/car/00156.jpg new file mode 100644 index 0000000..f14abbb Binary files /dev/null and b/notebooks/videos/car/00156.jpg differ diff --git a/notebooks/videos/car/00157.jpg b/notebooks/videos/car/00157.jpg new file mode 100644 index 0000000..751924c Binary files /dev/null and b/notebooks/videos/car/00157.jpg differ diff --git a/notebooks/videos/car/00158.jpg b/notebooks/videos/car/00158.jpg new file mode 100644 index 0000000..05439e0 Binary files /dev/null and b/notebooks/videos/car/00158.jpg differ diff --git a/notebooks/videos/car/00159.jpg b/notebooks/videos/car/00159.jpg new file mode 100644 index 0000000..26d957d Binary files /dev/null and b/notebooks/videos/car/00159.jpg differ diff --git a/notebooks/videos/car/00160.jpg b/notebooks/videos/car/00160.jpg new file mode 100644 index 0000000..c655053 Binary files /dev/null and b/notebooks/videos/car/00160.jpg differ diff --git a/notebooks/videos/car/00161.jpg b/notebooks/videos/car/00161.jpg new file mode 100644 index 0000000..1f06e52 Binary files /dev/null and b/notebooks/videos/car/00161.jpg differ diff --git a/notebooks/videos/car/00162.jpg b/notebooks/videos/car/00162.jpg new file mode 100644 index 0000000..66b10b1 Binary files /dev/null and b/notebooks/videos/car/00162.jpg differ diff --git a/notebooks/videos/car/00163.jpg b/notebooks/videos/car/00163.jpg new file mode 100644 index 0000000..96a3178 Binary files /dev/null and b/notebooks/videos/car/00163.jpg differ diff --git a/notebooks/videos/car/00164.jpg b/notebooks/videos/car/00164.jpg new file mode 100644 index 0000000..af442a0 Binary files /dev/null and b/notebooks/videos/car/00164.jpg differ diff --git a/notebooks/videos/car/00165.jpg b/notebooks/videos/car/00165.jpg new file mode 100644 index 0000000..ce47524 Binary files /dev/null and b/notebooks/videos/car/00165.jpg differ diff --git a/notebooks/videos/car/00166.jpg b/notebooks/videos/car/00166.jpg new file mode 100644 index 0000000..00316cd Binary files /dev/null and b/notebooks/videos/car/00166.jpg differ diff --git a/notebooks/videos/car/00167.jpg b/notebooks/videos/car/00167.jpg new file mode 100644 index 0000000..32fa8f2 Binary files /dev/null and b/notebooks/videos/car/00167.jpg differ diff --git a/notebooks/videos/car/00168.jpg b/notebooks/videos/car/00168.jpg new file mode 100644 index 0000000..928e345 Binary files /dev/null and b/notebooks/videos/car/00168.jpg differ diff --git a/utils/common_utils.py b/utils/common_utils.py new file mode 100644 index 0000000..255ff3c --- /dev/null +++ b/utils/common_utils.py @@ -0,0 +1,77 @@ +import os +import json +import cv2 +import numpy as np +from dataclasses import dataclass +import random + +class CommonUtils: + @staticmethod + def creat_dirs(path): + """ + Ensure the given path exists. If it does not exist, create it using os.makedirs. + + :param path: The directory path to check or create. + """ + try: + if not os.path.exists(path): + os.makedirs(path, exist_ok=True) + print(f"Path '{path}' did not exist and has been created.") + else: + print(f"Path '{path}' already exists.") + except Exception as e: + print(f"An error occurred while creating the path: {e}") + + @staticmethod + def draw_masks_and_box(raw_image_path, mask_path, json_path, output_path): + CommonUtils.creat_dirs(output_path) + raw_image_name_list = os.listdir(raw_image_path) + raw_image_name_list.sort() + for raw_image_name in raw_image_name_list: + image_path = os.path.join(raw_image_path, raw_image_name) + image = cv2.imread(image_path) + if image is None: + raise FileNotFoundError("Image file not found.") + # load mask + mask_npy_path = os.path.join(mask_path, "mask_"+raw_image_name.split(".")[0]+".npy") + mask = np.load(mask_npy_path) + # color map + unique_ids = np.unique(mask) + colors = {uid: CommonUtils.random_color() for uid in unique_ids} + colors[0] = (0, 0, 0) # background color + + # apply mask to image + colored_mask = np.zeros_like(image) + for uid in unique_ids: + colored_mask[mask == uid] = colors[uid] + alpha = 0.5 # 调整 alpha 值以改变透明度 + output_image = cv2.addWeighted(image, 1 - alpha, colored_mask, alpha, 0) + + + file_path = os.path.join(json_path, "mask_"+raw_image_name.split(".")[0]+".json") + with open(file_path, 'r') as file: + json_data = json.load(file) + # Draw bounding boxes and labels + for obj_id, obj_item in json_data["labels"].items(): + # Extract data from JSON + x1, y1, x2, y2 = obj_item["x1"], obj_item["y1"], obj_item["x2"], obj_item["y2"] + instance_id = obj_item["instance_id"] + class_name = obj_item["class_name"] + + # Draw rectangle + cv2.rectangle(output_image, (x1, y1), (x2, y2), (0, 255, 0), 2) + + # Put text + label = f"{instance_id}: {class_name}" + cv2.putText(output_image, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 2) + + # Save the modified image + output_image_path = os.path.join(output_path, raw_image_name) + cv2.imwrite(output_image_path, output_image) + + print(f"Annotated image saved as {output_image_path}") + + @staticmethod + def random_color(): + """random color generator""" + return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) diff --git a/utils/mask_dictionary_model.py b/utils/mask_dictionary_model.py new file mode 100644 index 0000000..18937b8 --- /dev/null +++ b/utils/mask_dictionary_model.py @@ -0,0 +1,142 @@ +import numpy as np +import json +import torch +import copy +import os +import cv2 +from dataclasses import dataclass, field + +@dataclass +class MaskDictionatyModel: + mask_name:str = "" + mask_height: int = 1080 + mask_width:int = 1920 + promote_type:str = "mask" + labels:dict = field(default_factory=dict) + + def add_new_frame_annotation(self, mask_list, box_list, label_list, background_value = 0): + mask_img = torch.zeros(mask_list.shape[-2:]) + anno_2d = {} + for idx, (mask, box, label) in enumerate(zip(mask_list, box_list, label_list)): + final_index = background_value + idx + 1 + + if mask.shape[0] != mask_img.shape[0] or mask.shape[1] != mask_img.shape[1]: + raise ValueError("The mask shape should be the same as the mask_img shape.") + # mask = mask + mask_img[mask == True] = final_index + # print("label", label) + name = label + box = box # .numpy().tolist() + new_annotation = ObjectInfo(instance_id = final_index, mask = mask, class_name = name, x1 = box[0], y1 = box[1], x2 = box[2], y2 = box[3]) + anno_2d[final_index] = new_annotation + + # np.save(os.path.join(output_dir, output_file_name), mask_img.numpy().astype(np.uint16)) + self.mask_height = mask_img.shape[0] + self.mask_width = mask_img.shape[1] + self.labels = anno_2d + + def update_masks(self, tracking_annotation_dict, iou_threshold=0.8, objects_count=0): + updated_masks = {} + + for seg_obj_id, seg_mask in self.labels.items(): # tracking_masks + flag = 0 + new_mask_copy = ObjectInfo() + if seg_mask.mask.sum() == 0: + continue + + for object_id, object_info in tracking_annotation_dict.labels.items(): # grounded_sam masks + iou = self.calculate_iou(seg_mask.mask, object_info.mask) # tensor, numpy + # print("iou", iou) + if iou > iou_threshold: + flag = object_info.instance_id + new_mask_copy.mask = seg_mask.mask + new_mask_copy.instance_id = object_info.instance_id + new_mask_copy.class_name = seg_mask.class_name + break + + if not flag: + objects_count += 1 + flag = objects_count + new_mask_copy.instance_id = objects_count + new_mask_copy.mask = seg_mask.mask + new_mask_copy.class_name = seg_mask.class_name + updated_masks[flag] = new_mask_copy + self.labels = updated_masks + return objects_count + + def get_target_class_name(self, instance_id): + return self.labels[instance_id].class_name + + + @staticmethod + def calculate_iou(mask1, mask2): + # Convert masks to float tensors for calculations + mask1 = mask1.to(torch.float32) + mask2 = mask2.to(torch.float32) + + # Calculate intersection and union + intersection = (mask1 * mask2).sum() + union = mask1.sum() + mask2.sum() - intersection + + # Calculate IoU + iou = intersection / union + return iou + + def to_dict(self): + return { + "mask_name": self.mask_name, + "mask_height": self.mask_height, + "mask_width": self.mask_width, + "promote_type": self.promote_type, + "labels": {k: v.to_dict() for k, v in self.labels.items()} + } + + + +@dataclass +class ObjectInfo: + instance_id:int = 0 + mask: any = None + class_name:str = "" + x1:int = 0 + y1:int = 0 + x2:int = 0 + y2:int = 0 + logit:float = 0.0 + + def get_mask(self): + return self.mask + + def get_id(self): + return self.instance_id + + def update_box(self): + # 找到所有非零值的索引 + nonzero_indices = torch.nonzero(self.mask) + + # 如果没有非零值,返回一个空的边界框 + if nonzero_indices.size(0) == 0: + # print("nonzero_indices", nonzero_indices) + return [] + + # 计算最小和最大索引 + y_min, x_min = torch.min(nonzero_indices, dim=0)[0] + y_max, x_max = torch.max(nonzero_indices, dim=0)[0] + + # 创建边界框 [x_min, y_min, x_max, y_max] + bbox = [x_min.item(), y_min.item(), x_max.item(), y_max.item()] + self.x1 = bbox[0] + self.y1 = bbox[1] + self.x2 = bbox[2] + self.y2 = bbox[3] + + def to_dict(self): + return { + "instance_id": self.instance_id, + "class_name": self.class_name, + "x1": self.x1, + "y1": self.y1, + "x2": self.x2, + "y2": self.y2, + "logit": self.logit + } \ No newline at end of file diff --git a/supervision_utils.py b/utils/supervision_utils.py similarity index 100% rename from supervision_utils.py rename to utils/supervision_utils.py diff --git a/track_utils.py b/utils/track_utils.py similarity index 100% rename from track_utils.py rename to utils/track_utils.py diff --git a/video_utils.py b/utils/video_utils.py similarity index 100% rename from video_utils.py rename to utils/video_utils.py