Skip to content

deeplabcut.create_project.add

Functions:

Name Description
add_new_videos

Add new videos to the config file at any stage of the project.

add_new_videos

add_new_videos(config: str | Path, videos: list[str | Path], copy_videos=False, coords=None, extract_frames=False)

Add new videos to the config file at any stage of the project.

Parameters:

Name Type Description Default

config

string

String containing the full path of the config file in the project.

required

videos

list

A list of strings containing the full paths of the videos to include in the project.

required

copy_videos

bool

If True, the videos will be copied to your project/videos directory. If False, symlinks of the videos are copied instead. Defaults to False.

False

coords

list

A list containing the list of cropping coordinates of the video. Defaults to None.

None

extract_frames

bool

If True, extract_frames will be run on the new videos. Defaults to False.

False

Examples:

Video will be added, with cropping dimensions according to the frame dimensions of mouse5.avi:

deeplabcut.add_new_videos(
    "/home/project/reaching-task-Tanmay-2018-08-23/config.yaml",
    ["/data/videos/mouse5.avi"],
)

Video will be added, with cropping dimensions [0,100,0,200]:

deeplabcut.add_new_videos(
    "/home/project/reaching-task-Tanmay-2018-08-23/config.yaml",
    ["/data/videos/mouse5.avi"],
    copy_videos=False,
    coords=[[0, 100, 0, 200]],
)

Two videos will be added, with cropping dimensions [0,100,0,200] and [0,100,0,250], respectively:

deeplabcut.add_new_videos(
    "/home/project/reaching-task-Tanmay-2018-08-23/config.yaml",
    ["/data/videos/mouse5.avi", "/data/videos/mouse6.avi"],
    copy_videos=False,
    coords=[[0, 100, 0, 200], [0, 100, 0, 250]],
)
Source code in deeplabcut/create_project/add.py
def add_new_videos(
    config: str | Path,
    videos: list[str | Path],
    copy_videos=False,
    coords=None,
    extract_frames=False,
):
    """Add new videos to the config file at any stage of the project.

    Args:
        config (string): String containing the full path of the config file in the project.
        videos (list): A list of strings containing the full paths of the videos to include in the project.
        copy_videos (bool, optional): If True, the videos will be copied to your
            project/videos directory. If False, symlinks of the videos are copied
            instead. Defaults to False.
        coords (list, optional): A list containing the list of cropping coordinates of the video. Defaults to None.
        extract_frames (bool, optional): If True, extract_frames will be run on the new
            videos. Defaults to False.

    Examples:
        Video will be added, with cropping dimensions according to the frame dimensions of
        mouse5.avi:

            deeplabcut.add_new_videos(
                "/home/project/reaching-task-Tanmay-2018-08-23/config.yaml",
                ["/data/videos/mouse5.avi"],
            )

        Video will be added, with cropping dimensions [0,100,0,200]:

            deeplabcut.add_new_videos(
                "/home/project/reaching-task-Tanmay-2018-08-23/config.yaml",
                ["/data/videos/mouse5.avi"],
                copy_videos=False,
                coords=[[0, 100, 0, 200]],
            )

        Two videos will be added, with cropping dimensions [0,100,0,200] and
        [0,100,0,250], respectively:

            deeplabcut.add_new_videos(
                "/home/project/reaching-task-Tanmay-2018-08-23/config.yaml",
                ["/data/videos/mouse5.avi", "/data/videos/mouse6.avi"],
                copy_videos=False,
                coords=[[0, 100, 0, 200], [0, 100, 0, 250]],
            )
    """
    config = Path(config).absolute()

    # Read the config file
    cfg = auxiliaryfunctions.read_config(config)

    # deal with user passing a single video to add
    if isinstance(videos, str):
        videos = [videos]

    video_path = config.parent / "videos"
    data_path = config.parent / "labeled-data"
    videos = [Path(vp).absolute() for vp in videos]

    dirs = [data_path / i.stem for i in videos]

    for p in dirs:
        """Creates directory under data & perhaps copies videos (to /video)"""
        p.mkdir(parents=True, exist_ok=True)

    destinations = [video_path.joinpath(vp.name) for vp in videos]
    if copy_videos:
        for src, dst in zip(videos, destinations, strict=False):
            if dst.exists():
                pass
            else:
                print("Copying the videos")
                shutil.copy(os.fspath(src), os.fspath(dst))

    else:
        # creates the symlinks of the video and puts it in the videos directory.
        print("Attempting to create a symbolic link of the video ...")
        for src, dst in zip(videos, destinations, strict=False):
            if dst.exists():
                print(f"Video {dst} already exists. Skipping...")
                continue
            try:
                dst.symlink_to(src)
                print(f"Created the symlink of {src} to {dst}")
            except OSError:
                try:
                    import subprocess

                    subprocess.check_call(f"mklink {os.fspath(dst)} {os.fspath(src)}", shell=True)
                except (OSError, subprocess.CalledProcessError):
                    print("Symlink creation impossible (exFat architecture?): copying the video instead.")
                    shutil.copy(os.fspath(src), os.fspath(dst))
                    print(f"{src} copied to {dst}")
            videos = destinations

    if copy_videos:
        videos = destinations  # in this case the *new* location should be added to the config file
    # adds the video list to the config.yaml file
    for idx, video in enumerate(videos):
        video_key = Path(video).absolute()
        vid = VideoReader(os.fspath(video_key))
        if coords is not None:
            c = coords[idx]
        else:
            c = vid.get_bbox()
        params = {os.fspath(video_key): {"crop": ", ".join(map(str, c))}}
        if "video_sets_original" not in cfg:
            cfg["video_sets"].update(params)
        else:
            cfg["video_sets_original"].update(params)
    auxiliaryfunctions.write_config(config, cfg)
    if extract_frames:
        frame_extraction.extract_frames(
            config,
            userfeedback=False,
            videos_list=[os.fspath(video) for video in videos],
        )
        print("New videos were added to the project and frames have been extracted for labeling!")
    else:
        print("New videos were added to the project! Use the function 'extract_frames' to select frames for labeling.")