Beispiel #1
0
def create_dlc3d_projects(name,
                          experimenter,
                          root,
                          calib_root,
                          dlc2d_config,
                          image_format='png'):
    from deepcage.auxiliary.detect import detect_dlc_calibration_images
    from deeplabcut.utils.auxiliaryfunctions import write_config_3d
    from deeplabcut.create_project import create_new_project_3d

    from .utils import png_to_jpg

    if not isinstance(name, str):
        raise ValueError('name must be string')
    if not isinstance(experimenter, str):
        raise ValueError('experimenter must be string')

    dlc3d_project_configs = {}
    for pair, calib_paths in detect_dlc_calibration_images(calib_root).items():
        cam1, cam2 = pair

        # Create DeepLabCut 3D project for the loop-defined stereo camera
        name = '%d_%s_%s' % (PAIR_IDXS[pair], cam1, cam2)
        dlc3d_project_configs[pair] = create_new_project_3d(
            name, experimenter, num_cameras=2, working_directory=root)

        # Move calibration images to their respective DeepLabCut 3D project
        project_path = Path(os.path.dirname(dlc3d_project_configs[pair]))
        calibration_images_path = str(project_path / 'calibration_images')
        if not os.path.exists(calibration_images_path):
            os.makedirs(calibration_images_path)

        if 'png' in image_format:
            png_to_jpg(calibration_images_path, img_paths=calib_paths)
        elif 'jpg' in image_format or 'jpeg' in image_format:
            # TODO: Implement solution
            pass

        cfg = read_config(dlc3d_project_configs[pair])
        cfg['config_file_camera-1'] = dlc2d_config
        cfg['config_file_camera-2'] = dlc2d_config
        cfg['camera_names'] = list(pair)
        cfg['trainingsetindex_' + cam1] = cfg.pop('trainingsetindex_camera-1')
        cfg['trainingsetindex_' + cam2] = cfg.pop('trainingsetindex_camera-2')
        write_config_3d(dlc3d_project_configs[pair], cfg)

    return dlc3d_project_configs
Beispiel #2
0
def calibrate_cameras(config, cbrow=8, cbcol=6, calibrate=False, alpha=0.4):
    """This function extracts the corners points from the calibration images, calibrates the camera and stores the calibration files in the project folder (defined in the config file).
    
    Make sure you have around 20-60 pairs of calibration images. The function should be used iteratively to select the right set of calibration images. 
    
    A pair of calibration image is considered "correct", if the corners are detected correctly in both the images. It may happen that during the first run of this function, 
    the extracted corners are incorrect or the order of detected corners does not align for the corresponding views (i.e. camera-1 and camera-2 images).
    
    In such a case, remove those pairs of images and re-run this function. Once the right number of calibration images are selected, 
    use the parameter ``calibrate=True`` to calibrate the cameras.

    Parameters
    ----------
    config : string
        Full path of the config.yaml file as a string.

    cbrow : int
        Integer specifying the number of rows in the calibration image.
    
    cbcol : int
        Integer specifying the number of columns in the calibration image.

    calibrate : bool
        If this is set to True, the cameras are calibrated with the current set of calibration images. The default is ``False``
        Set it to True, only after checking the results of the corner detection method and removing dysfunctional images!
        
    alpha: float
        Floating point number between 0 and 1 specifying the free scaling parameter. When alpha = 0, the rectified images with only valid pixels are stored 
        i.e. the rectified images are zoomed in. When alpha = 1, all the pixels from the original images are retained. 
        For more details: https://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html
        
    Example
    --------
    Linux/MacOs/Windows
    >>> deeplabcut.calibrate_camera(config)

    Once the right set of calibration images are selected, 
    >>> deeplabcut.calibrate_camera(config,calibrate=True)

    """
    # Termination criteria
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

    # Prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
    objp = np.zeros((cbrow * cbcol, 3), np.float32)
    objp[:, :2] = np.mgrid[0:cbcol, 0:cbrow].T.reshape(-1, 2)

    # Read the config file
    cfg_3d = auxiliaryfunctions.read_config(config)
    (
        img_path,
        path_corners,
        path_camera_matrix,
        path_undistort,
    ) = auxiliaryfunctions_3d.Foldernames3Dproject(cfg_3d)

    images = glob.glob(os.path.join(img_path, "*.jpg"))
    cam_names = cfg_3d["camera_names"]

    # update the variable snapshot* in config file according to the name of the cameras
    try:
        for i in range(len(cam_names)):
            cfg_3d[str("config_file_" + cam_names[i])] = cfg_3d.pop(
                str("config_file_camera-" + str(i + 1)))
        for i in range(len(cam_names)):
            cfg_3d[str("shuffle_" + cam_names[i])] = cfg_3d.pop(
                str("shuffle_camera-" + str(i + 1)))
    except:
        pass

    project_path = cfg_3d["project_path"]
    projconfigfile = os.path.join(str(project_path), "config.yaml")
    auxiliaryfunctions.write_config_3d(projconfigfile, cfg_3d)

    # Initialize the dictionary
    img_shape = {}
    objpoints = {}  # 3d point in real world space
    imgpoints = {}  # 2d points in image plane.
    dist_pickle = {}
    stereo_params = {}
    for cam in cam_names:
        objpoints.setdefault(cam, [])
        imgpoints.setdefault(cam, [])
        dist_pickle.setdefault(cam, [])

    # Sort the images.
    images.sort(key=lambda f: int("".join(filter(str.isdigit, f))))
    if len(images) == 0:
        raise Exception(
            "No calibration images found. Make sure the calibration images are saved as .jpg and with prefix as the camera name as specified in the config.yaml file."
        )

    for fname in images:
        for cam in cam_names:
            if cam in fname:
                filename = Path(fname).stem
                img = cv2.imread(fname)
                gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

                # Find the chess board corners
                ret, corners = cv2.findChessboardCorners(
                    gray, (cbcol, cbrow), None
                )  #  (8,6) pattern (dimensions = common points of black squares)
                # If found, add object points, image points (after refining them)
                if ret == True:
                    img_shape[cam] = gray.shape[::-1]
                    objpoints[cam].append(objp)
                    corners = cv2.cornerSubPix(gray, corners, (11, 11),
                                               (-1, -1), criteria)
                    imgpoints[cam].append(corners)
                    # Draw the corners and store the images
                    img = cv2.drawChessboardCorners(img, (cbcol, cbrow),
                                                    corners, ret)
                    cv2.imwrite(
                        os.path.join(str(path_corners),
                                     filename + "_corner.jpg"), img)
                else:
                    print("Corners not found for the image %s" %
                          Path(fname).name)
    try:
        h, w = img.shape[:2]
    except:
        raise Exception(
            "It seems that the name of calibration images does not match with the camera names in the config file. Please make sure that the calibration images are named with camera names as specified in the config.yaml file."
        )

    # Perform calibration for each cameras and store the matrices as a pickle file
    if calibrate == True:
        # Calibrating each camera
        for cam in cam_names:
            ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(
                objpoints[cam], imgpoints[cam], img_shape[cam], None, None)

            # Save the camera calibration result for later use (we won't use rvecs / tvecs)
            dist_pickle[cam] = {
                "mtx": mtx,
                "dist": dist,
                "objpoints": objpoints[cam],
                "imgpoints": imgpoints[cam],
            }
            pickle.dump(
                dist_pickle,
                open(
                    os.path.join(path_camera_matrix,
                                 cam + "_intrinsic_params.pickle"),
                    "wb",
                ),
            )
            print(
                "Saving intrinsic camera calibration matrices for %s as a pickle file in %s"
                % (cam, os.path.join(path_camera_matrix)))

            # Compute mean re-projection errors for individual cameras
            mean_error = 0
            for i in range(len(objpoints[cam])):
                imgpoints_proj, _ = cv2.projectPoints(objpoints[cam][i],
                                                      rvecs[i], tvecs[i], mtx,
                                                      dist)
                error = cv2.norm(imgpoints[cam][i], imgpoints_proj,
                                 cv2.NORM_L2) / len(imgpoints_proj)
                mean_error += error
            print("Mean re-projection error for %s images: %.3f pixels " %
                  (cam, mean_error / len(objpoints[cam])))

        # Compute stereo calibration for each pair of cameras
        camera_pair = [[cam_names[0], cam_names[1]]]
        for pair in camera_pair:
            print("Computing stereo calibration for " % pair)
            (
                retval,
                cameraMatrix1,
                distCoeffs1,
                cameraMatrix2,
                distCoeffs2,
                R,
                T,
                E,
                F,
            ) = cv2.stereoCalibrate(
                objpoints[pair[0]],
                imgpoints[pair[0]],
                imgpoints[pair[1]],
                dist_pickle[pair[0]]["mtx"],
                dist_pickle[pair[0]]["dist"],
                dist_pickle[pair[1]]["mtx"],
                dist_pickle[pair[1]]["dist"],
                (h, w),
                flags=cv2.CALIB_FIX_INTRINSIC,
            )

            # Stereo Rectification
            rectify_scale = (
                alpha
            )  # Free scaling parameter check this https://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#fisheye-stereorectify
            R1, R2, P1, P2, Q, roi1, roi2 = cv2.stereoRectify(
                cameraMatrix1,
                distCoeffs1,
                cameraMatrix2,
                distCoeffs2,
                (h, w),
                R,
                T,
                alpha=rectify_scale,
            )

            stereo_params[pair[0] + "-" + pair[1]] = {
                "cameraMatrix1": cameraMatrix1,
                "cameraMatrix2": cameraMatrix2,
                "distCoeffs1": distCoeffs1,
                "distCoeffs2": distCoeffs2,
                "R": R,
                "T": T,
                "E": E,
                "F": F,
                "R1": R1,
                "R2": R2,
                "P1": P1,
                "P2": P2,
                "roi1": roi1,
                "roi2": roi2,
                "Q": Q,
                "image_shape": [img_shape[pair[0]], img_shape[pair[1]]],
            }

        print(
            "Saving the stereo parameters for every pair of cameras as a pickle file in %s"
            % str(os.path.join(path_camera_matrix)))

        auxiliaryfunctions.write_pickle(
            os.path.join(path_camera_matrix, "stereo_params.pickle"),
            stereo_params)
        print(
            "Camera calibration done! Use the function ``check_undistortion`` to check the check the calibration"
        )
    else:
        print(
            "Corners extracted! You may check for the extracted corners in the directory %s and remove the pair of images where the corners are incorrectly detected. If all the corners are detected correctly with right order, then re-run the same function and use the flag ``calibrate=True``, to calbrate the camera."
            % str(path_corners))
Beispiel #3
0
def step3B_edit_yamlfile(config3d, **kwargs):
    camera_names = (kwargs['camera_names']).split(",")
    cfg_3d = auxiliaryfunctions.read_config(config3d)
    #print("Old cfg_3d:", cfg_3d)

    old_cam_names = cfg_3d['camera_names']
    #print("reading Camera names:{}".format(old_cam_names))
    if len(old_cam_names) == len(camera_names):
        for index in range(len(old_cam_names)):
            cfg_3d['trainingsetindex_' + camera_names[index]] = cfg_3d['trainingsetindex_' + old_cam_names[index]]
            del cfg_3d['trainingsetindex_' + old_cam_names[index]]

            cfg_3d['config_file_' + camera_names[index]] = cfg_3d['config_file_' + old_cam_names[index]]
            del cfg_3d['config_file_' + old_cam_names[index]]

            cfg_3d['shuffle_' + camera_names[index]] = cfg_3d['shuffle_' + old_cam_names[index]]
            del cfg_3d['shuffle_' + old_cam_names[index]]

    else:
        print("old camera names are different,failed to replace.")
        sys.exit(1)

    cfg_3d['camera_names'] = camera_names

    #print("write Camera names:{}, type:{}".format(cfg_3d['camera_names'], type(camera_names)))
    #print("old skeleton:", cfg_3d['skeleton'])
    skeleton = []
    for token in kwargs['skeleton'].split("~"):
        skeleton.append(token.split(","))
    #print("New Skeleton:", skeleton)
    cfg_3d['skeleton'] = skeleton
    
    logData = get_info_fromlog(**kwargs)
    if logData is None:
        print("Can't find right log file folder:{}".format(kwargs['source_path']))
        sys.exit(1)

    set_number = int(logData[b'boxnumber']) #convert from float to integer
    kwargs['set_name'] = "box"+str(set_number)

    kwargs['hand'] = int(logData[b'hand'])

    networks = listdirs(kwargs['networks'])
    network=None
    indicator = 'L'
    if kwargs['hand']==1:
        indicator = 'R'

    for onenetwork in networks:
        if onenetwork[0] == indicator:
            network = onenetwork

    if network == None:
        print("Can't find network")
        sys.exit(1)

    networkconfig = os.path.abspath(os.path.join(kwargs['networks'], network,'config.yaml'))

    for cam_name in camera_names:
        cfg_3d['config_file_' + cam_name] = networkconfig

    auxiliaryfunctions.write_config_3d(config3d, cfg_3d)

    cfg_3d = auxiliaryfunctions.read_config(config3d)
Beispiel #4
0
def step3D_calibrate_cameras(config,cbrow = 8,cbcol = 6,calibrate=False,alpha=0.4):

    # Termination criteria
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

    # Prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
    objp = np.zeros((cbrow * cbcol, 3), np.float32)
    objp[:, :2] = np.mgrid[0:cbcol, 0:cbrow].T.reshape(-1, 2)

    # Read the config file
    cfg_3d = auxiliaryfunctions.read_config(config)
    img_path,path_corners,path_camera_matrix,path_undistort=auxiliaryfunctions_3d.Foldernames3Dproject(cfg_3d)

    images = glob.glob(os.path.join(img_path,'*.jpg'))
    cam_names = cfg_3d['camera_names']

    # # update the variable snapshot* in config file according to the name of the cameras
    # try:
    #     for i in range(len(cam_names)):
    #         cfg_3d[str('config_file_'+cam_names[i])] = cfg_3d.pop(str('config_file_camera-'+str(i+1)))
    #     for i in range(len(cam_names)):
    #         cfg_3d[str('shuffle_'+cam_names[i])] = cfg_3d.pop(str('shuffle_camera-'+str(i+1)))
    # except:
    #     pass

    project_path = cfg_3d['project_path']
    projconfigfile=os.path.join(str(project_path),'config.yaml')
    auxiliaryfunctions.write_config_3d(projconfigfile,cfg_3d)

    # Initialize the dictionary
    img_shape = {}
    objpoints = {} # 3d point in real world space
    imgpoints = {} # 2d points in image plane
    dist_pickle = {}
    stereo_params= {}
    for cam in cam_names:
        objpoints.setdefault(cam, [])
        imgpoints.setdefault(cam, [])
        dist_pickle.setdefault(cam, [])

    # Sort the images.
    images.sort(key=lambda f: int(''.join(filter(str.isdigit, f))))
    if len(images)==0:
        raise Exception("No calibration images found. Make sure the calibration images are saved as .jpg and with prefix as the camera name as specified in the config.yaml file.")

    fname_with_issue = []

    for fname in images:
        for cam in cam_names:
            if cam in fname:
                filename = Path(fname).stem
                #detect pair side exits or not.
                for pair_cam in cam_names:
                    if pair_cam==cam:
                        continue
                    pair_file =os.path.join(img_path, filename.replace(cam, pair_cam)+".jpg")
                    if not os.path.exists(pair_file):
                        #print("pair_file:", pair_file)
                        if fname not in fname_with_issue:
                            fname_with_issue.append(fname)
                            #print("{} doesn't have pair:{}".format(filename, Path(pair_file).stem))

                img = cv2.imread(fname)
                gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

                # Find the checker board corners
                ret, corners = cv2.findChessboardCorners(gray, (cbcol,cbrow),None,) #  (8,6) pattern (dimensions = common points of black squares)
                # If found, add object points, image points (after refining them)
                if ret == True:
                    img_shape[cam] = gray.shape[::-1]
                    objpoints[cam].append(objp)
                    corners = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
                    if not valid_corners(corners):
                        #print("suspected incorrect corner for:{}".format(fname))
                        if fname not in fname_with_issue:
                            fname_with_issue.append(fname)

                    imgpoints[cam].append(corners)
                    # Draw corners and store the images
                    img = cv2.drawChessboardCorners(img, (cbcol,cbrow), corners,ret)
                    cv2.imwrite(os.path.join(str(path_corners),filename+'_corner.jpg'),img)
                else:
                    #print("Corners not found for the image %s" %Path(fname).name)
                    if fname not in fname_with_issue:
                        fname_with_issue.append(fname)
    try:
        h,  w = img.shape[:2]
    except:
        raise Exception("The name of calibration images does not match the camera names in the config file.")

    # Perform calibration for each cameras and store matrices as a pickle file
    if calibrate == True:
        print("Starting to calibrate...")
        # Calibrating each camera
        for cam in cam_names:
            ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints[cam], imgpoints[cam], img_shape[cam],None,None)

            # Save the camera calibration result for later use (we won't use rvecs / tvecs)
            dist_pickle[cam] = {'mtx':mtx , 'dist':dist, 'objpoints':objpoints[cam] ,'imgpoints':imgpoints[cam] }
            pickle.dump( dist_pickle, open( os.path.join(path_camera_matrix,cam+'_intrinsic_params.pickle'), "wb" ) )
            print('Saving intrinsic camera calibration matrices for %s as a pickle file in %s'%(cam, os.path.join(path_camera_matrix)))

            # Compute mean re-projection errors for individual cameras
            mean_error = 0
            for i in range(len(objpoints[cam])):
                imgpoints_proj, _ = cv2.projectPoints(objpoints[cam][i], rvecs[i], tvecs[i], mtx, dist)
                error = cv2.norm(imgpoints[cam][i],imgpoints_proj, cv2.NORM_L2)/len(imgpoints_proj)
                mean_error += error
            print("Mean re-projection error for %s images: %.3f pixels " %(cam, mean_error/len(objpoints[cam])))

        # Compute stereo calibration for each pair of cameras
        camera_pair = [[cam_names[0], cam_names[1]]]
        for pair in camera_pair:
            print("Computing stereo calibration for " %pair)
            retval, cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, R, T, E, F = cv2.stereoCalibrate(objpoints[pair[0]],imgpoints[pair[0]],imgpoints[pair[1]],dist_pickle[pair[0]]['mtx'],dist_pickle[pair[0]]['dist'], dist_pickle[pair[1]]['mtx'], dist_pickle[pair[1]]['dist'],(h,  w),flags = cv2.CALIB_FIX_INTRINSIC)

            # Stereo Rectification
            rectify_scale = alpha # Free scaling parameter check this https://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#fisheye-stereorectify
            R1, R2, P1, P2, Q, roi1, roi2 = cv2.stereoRectify(cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, (h, w), R, T, alpha = rectify_scale)

            stereo_params[pair[0]+'-'+pair[1]] = {"cameraMatrix1": cameraMatrix1,"cameraMatrix2": cameraMatrix2,"distCoeffs1": distCoeffs1,"distCoeffs2": distCoeffs2,"R":R,"T":T,"E":E,"F":F,
                         "R1":R1,
                         "R2":R2,
                         "P1":P1,
                         "P2":P2,
                         "roi1":roi1,
                         "roi2":roi2,
                         "Q":Q,
                         "image_shape":[img_shape[pair[0]],img_shape[pair[1]]]}

        print('Saving the stereo parameters for every pair of cameras as a pickle file in %s'%str(os.path.join(path_camera_matrix)))

        auxiliaryfunctions.write_pickle(os.path.join(path_camera_matrix,'stereo_params.pickle'),stereo_params)
        print("Camera calibration done!")
    else:
        print("Removing images where the corners are incorrectly detected.")

    return fname_with_issue
Beispiel #5
0
def create_new_project_3d(project, experimenter, num_cameras=2, working_directory=None):
    """Creates a new project directory, sub-directories and a basic configuration file for 3d project. 
    The configuration file is loaded with the default values. Adjust the parameters to your project's needs.

    Parameters
    ----------
    project : string
        String containing the name of the project.

    experimenter : string
        String containing the name of the experimenter.

    num_cameras : int
        An integer value specifying the number of cameras.
        
    working_directory : string, optional
        The directory where the project will be created. The default is the ``current working directory``; if provided, it must be a string.


    Example
    --------
    Linux/MacOs
    >>> deeplabcut.create_new_project_3d('reaching-task','Linus',2)

    Windows:
    >>> deeplabcut.create_new_project('reaching-task','Bill',2)
    Users must format paths with either:  r'C:\ OR 'C:\\ <- i.e. a double backslash \ \ )

    """
    from datetime import datetime as dt
    from deeplabcut.utils import auxiliaryfunctions
    
    date = dt.today()
    month = date.strftime("%B")
    day = date.day
    d = str(month[0:3]+str(day))
    date = dt.today().strftime('%Y-%m-%d')
    
    if working_directory == None:
        working_directory = '.'
    
    wd = Path(working_directory).resolve()
    project_name = '{pn}-{exp}-{date}-{triangulate}'.format(pn=project, exp=experimenter, date=date,triangulate='3d')
    project_path = wd / project_name
    # Create project and sub-directories
    if not DEBUG and project_path.exists():
        print('Project "{}" already exists!'.format(project_path))
        return
    
    camera_matrix_path = project_path / 'camera_matrix'
    calibration_images_path = project_path / 'calibration_images'
    undistortion_path = project_path / 'undistortion'
    path_corners = project_path/'corners'
    
    for p in [camera_matrix_path, calibration_images_path, undistortion_path,path_corners]:
        p.mkdir(parents=True, exist_ok=DEBUG)
        print('Created "{}"'.format(p))
    
    # Create config file
    cfg_file_3d,ruamelFile_3d = auxiliaryfunctions.create_config_template_3d()
    cfg_file_3d['Task']=project
    cfg_file_3d['scorer']=experimenter
    cfg_file_3d['date']=d
    cfg_file_3d['project_path']= str(project_path)
#    cfg_file_3d['config_files']= [str('Enter the path of the config file ')+str(i)+ ' to include' for i in range(1,3)]
#    cfg_file_3d['config_files']= ['Enter the path of the config file 1']
    cfg_file_3d['colormap'] = 'jet'
    cfg_file_3d['dotsize'] =  15
    cfg_file_3d['alphaValue'] = 0.8
    cfg_file_3d['markerType'] = '*'
    cfg_file_3d['markerColor'] = 'r'
    cfg_file_3d['pcutoff'] = 0.4
    cfg_file_3d['num_cameras'] = num_cameras
    cfg_file_3d['camera_names'] = [str('camera-'+str(i))for i in range(1,num_cameras+1)]
    cfg_file_3d['scorername_3d'] = 'DLC_3D'
    
    cfg_file_3d['skeleton'] = [['bodypart1','bodypart2'], ['bodypart2','bodypart3'], ['bodypart3','bodypart4'], ['bodypart4','bodypart5']]
    cfg_file_3d['skeleton_color'] = 'black'
    
    for i in range(num_cameras):
        path = str('/home/mackenzie/DEEPLABCUT/DeepLabCut/2DprojectCam'+str(i+1)+'-Mackenzie-2019-06-05/config.yaml')
        cfg_file_3d.insert(len(cfg_file_3d), str('config_file_camera-'+str(i+1)),path)
    
    for i in range(num_cameras):
        cfg_file_3d.insert(len(cfg_file_3d), str('shuffle_camera-'+str(i+1)),1)
        cfg_file_3d.insert(len(cfg_file_3d), str('trainingsetindex_camera-'+str(i+1)),0)
        
    projconfigfile=os.path.join(str(project_path),'config.yaml')
    auxiliaryfunctions.write_config_3d(projconfigfile,cfg_file_3d)
    
    print('Generated "{}"'.format(project_path / 'config.yaml'))
    print("\nA new project with name %s is created at %s and a configurable file (config.yaml) is stored there. If you have not calibrated the cameras, then use the function 'calibrate_camera' to start calibrating the camera otherwise use the function ``triangulate`` to triangulate the dataframe"%(project_name,wd))
    return projconfigfile
Beispiel #6
0
def create_project_old_cage(
    new_project_name,
    old_cage_config,
    new_root,
    video_root=None,
    bonvideos=None,
    video_extension='avi',
    dlc_project_config='',
    dlc_working_dir=None,
    new_experimenter=None,
):
    """
    Create new DeepCageProject assembly with the use of a different cage proejct.
    Function used for migrating DeepCage constants to other projects
    
    The assembly migrations includes all DeepLabCut 3D projects, (optional) creating a new DLC 2D project,
    copying new videos to the new project.
    
    Parameters
    ----------
    new_project_name : str
        String containing the name of the new project.
        
    old_cage_config : str
        Absolute path to the old(!) DeepCage project config.yaml file.

    new_root : str-like
        Object containing the full path to the project, must have __str__() or method accepted by pathlib.Path()

    dlc_project_config : str; default '' (empty-string)
        Absolute path to the DeepLabCut project config.yaml file.

    dlc_working_dir : str; default, None -> project_path
        The directory where the optional DeepLabCut 2D project will be created.

    new_experimenter : str; default None
        String containing the project_name of the new experimenter/scorer.

    """

    from deeplabcut.utils.auxiliaryfunctions import write_config_3d

    # Prepare simple variables
    cfg = read_config(old_cage_config)
    dlcrd_cfg_paths = get_dlc3d_configs(old_cage_config)
    experimenter = cfg[
        'scorer'] if new_experimenter is None else new_experimenter

    # Create DeepCage project
    new_cfg_path = create_dc_project(
        new_project_name,
        experimenter,
        dlc_project_config,
        dlc3d_project_configs={},
        working_directory=new_root,
    )
    project_path = os.path.dirname(new_cfg_path)
    new_cfg = read_config(new_cfg_path)

    if video_root is not None:
        rem_videos = glob(
            os.path.join(video_root, ('**/*.%s' % video_extension)))
    elif bonvideos is not None:
        from deepcage.auxiliary.detect import detect_bonsai

        rem_videos = detect_bonsai(bonvideos)
    else:
        msg = 'No DeepLabCut 2D project was provided along with no video source, can not create dlc 2d project'
        raise ValueError(msg)

    # Dedicate DeepLabCut 2D project (pre-defined or new; arg dependent)
    if dlc_project_config is '':
        from deeplabcut.create_project.new import create_new_project

        dlc_create_root = dlc_working_dir if dlc_working_dir is not None else project_path
        dlc_path = create_new_project(new_project_name,
                                      experimenter,
                                      rem_videos,
                                      working_directory=dlc_create_root,
                                      copy_videos=True,
                                      videotype='.avi')
    else:
        dlc_path = dlc_project_config
    new_cfg[
        'dlc_project_config'] = dlc_path  # Add DLC 2D project to new DeepCage config file

    # Create a copy of every DLC 3d project in the previous project
    new_dlc_path = os.path.join(os.path.dirname(new_cfg_path), 'DeepLabCut')
    if not os.path.exists(new_dlc_path):
        os.mkdir(new_dlc_path)

    new_dlc3d_cfg_paths = {}
    for pair, path in dlcrd_cfg_paths.items():
        cam1, cam2 = pair
        dlc3d_root = os.path.dirname(path)
        dlc3d_id = os.path.basename(dlc3d_root)

        # Create the project folder
        new_dlc3d_root = os.path.join(new_dlc_path, dlc3d_id)
        os.mkdir(new_dlc3d_root)
        copytree(os.path.join(dlc3d_root, 'camera_matrix'),
                 os.path.join(new_dlc3d_root, 'camera_matrix'))
        copyfile(os.path.join(dlc3d_root, 'config.yaml'),
                 os.path.join(new_dlc3d_root, 'config.yaml'))

        # Modify the copied config.yaml file
        new_dlc3d_cfg_path = os.path.join(new_dlc3d_root, 'config.yaml')
        new_dlc3d_cfg = read_config(new_dlc3d_cfg_path)
        new_dlc3d_cfg['project_path'] = new_dlc3d_root
        new_dlc3d_cfg['config_file_%s' % cam1] = dlc_path
        new_dlc3d_cfg['config_file_%s' % cam2] = dlc_path
        write_config_3d(new_dlc3d_cfg_path, new_dlc3d_cfg)

        new_dlc3d_cfg_paths[pair] = new_dlc3d_root

    new_cfg['dlc3d_project_configs'] = new_dlc3d_cfg_paths
    write_config(new_cfg_path, new_cfg)

    if video_root is not None:
        dlc3d_video_migrate(new_cfg_path, video_root)
        print('Copied videos from %s to new project' % video_root)

    print('Created new DeepCage project:\n%s' % project_path)
    if dlc_project_config == '':
        print('New DeepLabCut 2D project is located in\n%s' % dlc_create_root)

    # Extracting frames using k-means
    extract_frames(path_config_file, userfeedback=False)