Пример #1
0
def post_annotation_load_training_images_3d(training_dir,
                            training_folders,
                            channel_names,
                            image_size,
                            num_frames,
                            data_format="channels_last"):
    '''
    Load each image in the training_folders into a numpy array.

    Args:
        training_dir: full path to parent directory that contains subfolders for
            different movies
        training_folders: list of folders where each folder contains subfolders
            of channels and features
        channel_names: list of folders where each folder contains a different channel
            of raw data to load into npz
        image_size: size of each image as tuple (x, y)
        num_frames: number of frames of movie to load into npz; if None, will
            default to the number of images in annotation folder
        data_format: channels_first or channels_last


    Returns:
        5D tensor of image data
    '''

    is_channels_first = data_format == 'channels_first'
    # Unpack size tuples
    image_size_x, image_size_y = image_size

    num_batches = len(training_folders)

    if num_frames == None:
        num_frames = len(get_img_names(os.path.join(training_dir, tranining_folders[0], channel_names[0])))

    # Initialize training data array
    if is_channels_first:
        X_shape = (num_batches, num_frames, len(channel_names), image_size_x, image_size_y)
    else:
        X_shape = (num_batches, num_frames, image_size_x, image_size_y, len(channel_names))

    X = np.zeros(X_shape, dtype=K.floatx())

    for b, movie_folder in enumerate(training_folders):
        for c, raw_folder in enumerate(channel_names):

            raw_list = get_img_names(os.path.join(training_dir, movie_folder, raw_folder))
            for f, frame in enumerate(raw_list):
                image_file = os.path.join(training_dir, movie_folder, raw_folder, frame)
                image_data = np.asarray(get_image(image_file), dtype=K.floatx())

                if is_channels_first:
                    X[b, f, c, :, :] = image_data
                else:
                    X[b, f, :, :, c] = image_data

    return X
Пример #2
0
def post_annotation_load_annotated_images_2d(training_dir,
                             annotation_folders,
                             image_size,
                             data_format="channels_last"):
    '''
    Load each annotated image in the training_direcs into a numpy array.

    Args:
        training_dir: full path to parent directory that contains subfolders for
            annotations
        annotation_folders: list of folders where each folder contains a different
            annotation feature to load into npz
        image_size: size of each image as tuple (x, y)
        data_format: channels_first or channels_last

    Returns:
        4D tensor of label masks
    '''

    is_channels_first = data_format == 'channels_first'
    # Unpack size tuple
    image_size_x, image_size_y = image_size

    # wrapping single annotation name in list for consistency
    if not isinstance(annotation_folders, list):
        annotation_folders = [annotation_folders]

    num_batches = len(get_img_names(os.path.join(training_dir, annotation_folders[0])))

    # Initialize feature mask array
    if is_channels_first:
        y_shape = (num_batches, len(annotation_folders), image_size_x, image_size_y)
    else:
        y_shape = (num_batches, image_size_x, image_size_y, len(annotation_folders))

    y = np.zeros(y_shape, dtype='int32')

    for l, annotation_folder in enumerate(annotation_folders):

        annotation_list = get_img_names(os.path.join(training_dir, annotation_folder))
        for b, img in enumerate(annotation_list):
            image_data = get_image(os.path.join(training_dir, annotation_folder, img))

            if is_channels_first:
                y[b, l, :, :] = image_data
            else:
                y[b, :, :, l] = image_data


    return y
Пример #3
0
def post_annotation_load_training_images_2d(training_dir,
                            channel_names,
                            image_size,
                            data_format="channels_last"):
    '''
    Load each image in the training_dir into a numpy array.

    Args:
        training_dir: full path to parent directory that contains subfolders for
            channels
        channel_names: list of folders where each folder contains a different channel
            of raw data to load into npz
        image_size: size of each image as tuple (x, y)
        data_format: channels_first or channels_last

    Returns:
        4D tensor of image data
    '''

    is_channels_first = data_format == 'channels_first'
    # Unpack size tuples
    image_size_x, image_size_y = image_size

    num_batches = len(get_img_names(os.path.join(training_dir, channel_names[0])))

    # Initialize training data array
    if is_channels_first:
        X_shape = (num_batches, len(channel_names), image_size_x, image_size_y)
    else:
        X_shape = (num_batches, image_size_x, image_size_y, len(channel_names))

    X = np.zeros(X_shape, dtype=K.floatx())


    for c, raw_folder in enumerate(channel_names):

        raw_list = get_img_names(os.path.join(training_dir, raw_folder))
        for b, img in enumerate(raw_list):
            image_file = os.path.join(training_dir, raw_folder, img)
            image_data = np.asarray(get_image(image_file), dtype=K.floatx())

            if is_channels_first:
                X[b, c, :, :] = image_data
            else:
                X[b, :, :, c] = image_data

    return X
Пример #4
0
def overlapping_crop_dir(raw_direc,
                         identifier,
                         num_x_segments,
                         num_y_segments,
                         overlap_perc,
                         frame_offset,
                         is_2D=False):
    '''
    Uses overlapping_img_chopper on all images in a folder. Also saves json log of settings, to be used when
    stitching images back together.
    
    Args:
        raw_direc: full path to folder containing movie slices that will be chopped
        identifier: string used to specify data set (same variable used throughout pipeline), 
            used to load and save files
        num_x_segments: integer number of columns the images will be chopped into
        num_y_segments: integer number of rows the images will be chopped into
        overlap_perc: percent of image on each edge that overlaps with other chopped images
        frame_offset: frame number chopper is starting from, used to calculate correct frame number for each image
        is_2D: whether to use 2D naming convention for loading images and saving chopped image pieces
        
    Returns:
        None
    '''
    #directories
    base_dir = os.path.dirname(raw_direc)
    unprocessed_name = os.path.basename(raw_direc)

    save_folder = unprocessed_name + "_offset_{0:03d}_chopped_{1:02d}_{2:02d}".format(
        frame_offset, num_x_segments, num_y_segments)
    save_dir = os.path.join(base_dir, save_folder)
    if not os.path.isdir(save_dir):
        os.makedirs(save_dir)
        #add folder modification permissions to deal with files from file explorer
        mode = stat.S_IRWXO | stat.S_IRWXU | stat.S_IRWXG
        os.chmod(save_dir, mode)

    log_dir = os.path.join(base_dir, "json_logs")
    if not os.path.isdir(log_dir):
        os.makedirs(log_dir)
        #add folder modification permissions to deal with files from file explorer
        mode = stat.S_IRWXO | stat.S_IRWXU | stat.S_IRWXG
        os.chmod(log_dir, mode)

    # pick a file to calculate neccesary information from
    img_stack = get_img_names(raw_direc)

    #load test image
    test_img_name = os.path.join(raw_direc, img_stack[0])
    file_ext = os.path.splitext(img_stack[0])[1]

    test_img_temp = get_image(test_img_name)
    test_img_size = test_img_temp.shape
    img_squeeze = False

    print("Current Image Size: ", test_img_size)
    while True:
        start_flag = str(input("Correct dimensionality? (y/n): "))
        if start_flag != "y" and start_flag != "n":
            print("Please type y for 'yes' or n for 'no'")
            continue
        elif start_flag == "n":
            print("Making input 2D")
            test_img = np.squeeze(test_img_temp, axis=0)
            test_img_size = test_img.shape
            img_squeeze = True
            print("New Image Size: ", test_img.shape)
            break
        else:
            test_img = test_img_temp
            break  # input correct end loop

    # determine number of pixels required to achieve correct overlap
    start_y = test_img_size[0] // num_y_segments
    overlapping_y_pix = int(start_y * (overlap_perc / 100))
    new_y = int(start_y + 2 * overlapping_y_pix)

    start_x = test_img_size[1] // num_x_segments
    overlapping_x_pix = int(start_x * (overlap_perc / 100))
    new_x = int(start_x + 2 * overlapping_x_pix)

    #for images that don't aren't divided evenly by num_segments, restitching can lead to losing a few pixels
    #avoid this by logging the actual start indices for the subimages
    y_start_indices = []
    x_start_indices = []

    for i in range(num_x_segments):
        x_start_index = int(i * start_x)
        x_start_indices.append(x_start_index)

    for j in range(num_y_segments):
        y_start_index = int(j * start_y)
        y_start_indices.append(y_start_index)

    print("Your new images will be ", new_x, " pixels by ", new_y,
          " pixels in size.")

    print("Processing...")

    files = os.listdir(raw_direc)
    files_sorted = sorted_nicely(files)

    for frame, file in enumerate(files_sorted):
        # load image
        file_path = os.path.join(raw_direc, file)
        if img_squeeze == False:
            img = get_image(file_path)
        else:
            img = np.squeeze(get_image(file_path), axis=0)
        #factor in whether we're starting from frame zero so that chopped files get correct frame number
        current_frame = frame + frame_offset

        #each frame of the movie will be chopped into x by y smaller frames and saved
        overlapping_img_chopper(img, save_dir, identifier, current_frame,
                                num_x_segments, num_y_segments, overlap_perc,
                                is_2D, file_ext)

    #log in json for post-annotation use

    log_data = {}
    log_data['date'] = str(datetime.datetime.now())
    log_data['num_x_segments'] = num_x_segments
    log_data['num_y_segments'] = num_y_segments
    log_data['overlap_perc'] = overlap_perc
    log_data['identifier'] = identifier
    log_data['y_start_indices'] = y_start_indices
    log_data['x_start_indices'] = x_start_indices
    log_data['overlapping_x_pix'] = overlapping_x_pix
    log_data['overlapping_y_pix'] = overlapping_y_pix
    log_data['original_y'] = test_img_size[0]
    log_data['original_x'] = test_img_size[1]
    log_data['frame_offset'] = frame_offset
    log_data['num_images'] = len(files_sorted)

    #save log in JSON format
    #save with identifier; should be saved in "log" folder

    log_path = os.path.join(log_dir,
                            identifier + "_overlapping_chopper_log.json")

    with open(log_path, "w") as write_file:
        json.dump(log_data, write_file)

    print("Cropped files saved to {}".format(save_dir))

    return None
Пример #5
0
def overlapping_stitcher_core(pieces_dir, save_dir, x_start_indices,
                              y_start_indices, overlapping_x_pix,
                              overlapping_y_pix, original_x, original_y,
                              identifier, sub_img_format, save_name):
    '''
    Takes overlapping annotation pieces and stitches them together into a
    fullsize image.
    
    Args:
        pieces_dir: full path to directory where image pieces are saved
        save_dir: full path to directory where stitched annotation should be saved
        x_start_indices: list of pixel locations corresponding to the x indices
            in the original image where the edges of each image piece began
        y_start_indices: list of pixel locations corresponding to the y indices
            in the original image where the edges of each image piece began
        overlapping_x_pix: number of pixels of overlap between horizontally
            adjacent image pieces
        overlapping_y_pix: number of pixels of overlap between vertically
            adjacent image pieces
        original_x: x dimension of original (whole) image; stitched image will
            have this x dimension
        original_y: y dimension of original (whole) image; stitched image will
            have this y dimension
        identifier: string used to specify data set (same variable used throughout 
            pipeline), used to load image pieces and save stitched image
        sub_img_format: string with formatting to load image pieces, depends on
            whether 2D naming convention was used
        save_name: file name to save stitched image as
        
    Returns:
        None
    '''

    #save path
    img_path = os.path.join(save_dir, save_name)

    #load test image
    test_img_name = os.listdir(pieces_dir)[0]
    test_img_path = os.path.join(pieces_dir, test_img_name)
    test_img = get_image(test_img_path)

    #make empty image, includes zero padding around edges

    small_img_size = test_img.shape

    #trim dimensions are the size of each sub image, with the overlap removed
    trim_y = small_img_size[0] - 2 * overlapping_y_pix
    trim_x = small_img_size[1] - 2 * overlapping_x_pix

    #pad dimensions are the amount of padding added to a sub image on each edge
    pad_x = overlapping_x_pix
    pad_y = overlapping_y_pix

    full_y = original_y
    full_x = original_x

    padded_full_img = np.zeros((full_y + 2 * pad_y, full_x + 2 * pad_x))

    #loop through the image pieces (sub_imgs)
    for j in range(len(y_start_indices)):
        for i in range(len(x_start_indices)):

            #load sub_img
            sub_img_name = sub_img_format.format(identifier, i, j)
            sub_img_path = os.path.join(pieces_dir, sub_img_name)
            try:
                sub_img = get_image(sub_img_path)
            except:
                sub_img = np.zeros(small_img_size)

            sub_x = sub_img.shape[1]
            sub_y = sub_img.shape[0]

            x_start = x_start_indices[i]
            y_start = y_start_indices[j]

            #don't repeat values even though each sub image has similar values
            lowest_allowed_val = np.amax(padded_full_img)
            sub_img = np.where(sub_img == 0, sub_img,
                               sub_img + lowest_allowed_val)

            #if non-zero values in the sub image and the full image overlap, replace all instances of
            #that value in the sub image, using most common value, keep other values in the sub image the same

            #working on top edge of sub_img
            sub_img_overlap = sub_img[0:2 * pad_y, :]
            full_img_overlap = padded_full_img[y_start:y_start + 2 * pad_y,
                                               x_start:x_start + sub_x]

            #add in cells from full_image that overlap with sub_img background
            merged_overlap = np.where(sub_img_overlap == 0, full_img_overlap,
                                      sub_img_overlap)
            sub_img[0:2 * pad_y, :] = merged_overlap

            #get ids of cells in sub_img that have any pixels in this overlap region
            sub_cells = np.unique(merged_overlap)
            nonzero_sub_cells = sub_cells[np.nonzero(sub_cells)]

            #for each cell, figure out which cell in full_img overlaps it the most
            for cell in nonzero_sub_cells:
                overlaps = np.where(merged_overlap == cell, full_img_overlap,
                                    0)
                nonzero_overlaps = overlaps[np.nonzero(overlaps)]
                if len(nonzero_overlaps) > 0:
                    (values, counts) = np.unique(nonzero_overlaps,
                                                 return_counts=True)
                    ind = np.argmax(counts)
                    overlapper = values[ind]

                    #use the best overlapping cell to update the values in the whole sub_img
                    #not just the region of the sub_img that directly overlaps

                    #replaces "cell" values with the overlapper, leaves everything else unchanged
                    sub_img = np.where(sub_img == cell, overlapper, sub_img)

            #working on left edge of sub_img
            sub_img_overlap = sub_img[:, 0:2 * pad_x]
            full_img_overlap = padded_full_img[y_start:y_start + sub_y,
                                               x_start:x_start + 2 * pad_x]

            #add in cells from full_image that overlap with sub_img background
            merged_overlap = np.where(sub_img_overlap == 0, full_img_overlap,
                                      sub_img_overlap)
            sub_img[:, 0:2 * pad_x] = merged_overlap

            #get ids of cells in sub_img that have any pixels in this overlap region
            sub_cells = np.unique(merged_overlap)
            nonzero_sub_cells = sub_cells[np.nonzero(sub_cells)]

            for cell in nonzero_sub_cells:
                overlaps = np.where(merged_overlap == cell, full_img_overlap,
                                    0)
                nonzero_overlaps = overlaps[np.nonzero(overlaps)]
                if len(nonzero_overlaps) > 0:
                    (values, counts) = np.unique(nonzero_overlaps,
                                                 return_counts=True)
                    ind = np.argmax(counts)
                    overlapper = values[ind]

                    #use the best overlapping cell to update the values in the whole sub_img
                    #not just the region of the sub_img that directly overlaps

                    #replaces "cell" values with the overlapper, leaves everything else unchanged
                    sub_img = np.where(sub_img == cell, overlapper, sub_img)

            #put sub image into the full image
            padded_full_img[y_start:y_start + sub_y,
                            x_start:x_start + sub_x] = sub_img

    padded_full_img = padded_full_img.astype(np.uint16)

    #trim off edges
    full_img = padded_full_img[pad_y:pad_y + full_y, pad_x:pad_x + full_x]

    #relabel cells so values aren't skipped
    relabeled_img = np.zeros(full_img.shape, dtype=np.uint16)
    unique_cells = np.unique(full_img)  # get all unique values of y
    unique_cells = unique_cells[np.nonzero(unique_cells)]
    relabel_ids = np.arange(1, len(unique_cells) + 1)

    for cell_id, relabel_id in zip(unique_cells, relabel_ids):
        relabeled_img = np.where(full_img == cell_id, relabel_id,
                                 relabeled_img)

    #save big image
    imwrite(img_path, relabeled_img)

    return None
Пример #6
0
def post_annotation_load_annotated_images_3d(training_dir,
                             training_folders,
                             annotation_folders,
                             image_size,
                             num_frames,
                             data_format="channels_last"):
    '''
    Load each annotated image in the training_folders into a numpy array.

    Args:
        training_dir: full path to parent directory that contains subfolders for
            different movies
        training_folders: list of folders where each folder contains subfolders
            of channels and features
        annotation_folders: list of folders where each folder contains a different
            annotation feature to load into npz
        image_size: size of each image as tuple (x, y)
        num_frames: number of frames of movie to load into npz; if None, will
            default to the number of images in annotation folder
        data_format: channels_first or channels_last


    Returns:
        5D tensor of label masks
    '''

    is_channels_first = data_format == 'channels_first'
    # Unpack size tuple
    image_size_x, image_size_y = image_size

    # wrapping single annotation name in list for consistency
    if not isinstance(annotation_folders, list):
        annotation_folders = [annotation_folders]

    num_batches = len(training_folders)

    if num_frames == None:
        num_frames = len(get_img_names(os.path.join(training_dir, training_folders[0], channel_names[0])))

    # Initialize feature mask array
    if is_channels_first:
        y_shape = (num_batches, num_frames, len(annotation_folders), image_size_x, image_size_y)
    else:
        y_shape = (num_batches, num_frames, image_size_x, image_size_y, len(annotation_folders))

    y = np.zeros(y_shape, dtype='int32')

    for b, movie_folder in enumerate(training_folders):
        for l, annotation_folder in enumerate(annotation_folders):

            annotation_list = get_img_names(os.path.join(training_dir, movie_folder, annotation_folder))
            for f, frame in enumerate(annotation_list):
                image_data = get_image(os.path.join(training_dir, movie_folder, annotation_folder, frame))

                if is_channels_first:
                    y[b, f, l, :, :] = image_data
                else:
                    y[b, f, :, :, l] = image_data


    return y
def adjust_folder(base_dir, raw_folder, identifier, contrast_settings, is_2D):
    '''
    Constrast adjust images in a given folder, save contrast adjusted images in new folder. Also creates a
        json log to record settings used.

    Args:
        base_dir: full path to parent directory that holds raw_folder; json logs folder will be created here
        raw_folder: name of folder (not full path) containing images to be contrast adjusted
        identifier: string, used to name processed images and json log
        contrast_settings: dictionary of settings to use for contrast adjustment
        is_2D: whether to save images with 2D naming convention

    Returns:
        None

    '''

    #directory specification, creating dirs when needed
    raw_dir = os.path.join(base_dir, raw_folder)

    #where will we save the processed files
    process_folder = raw_folder + "_contrast_adjusted"
    process_dir = os.path.join(base_dir, process_folder)
    if not os.path.isdir(process_dir):
        os.makedirs(process_dir)
        #add folder modification permissions to deal with files from file explorer
        mode = stat.S_IRWXO | stat.S_IRWXU | stat.S_IRWXG
        os.chmod(process_dir, mode)

    #where we will save a log of the settings
    log_dir = os.path.join(base_dir, "json_logs")
    if not os.path.isdir(log_dir):
        os.makedirs(log_dir)
        #add folder modification permissions to deal with files from file explorer
        mode = stat.S_IRWXO | stat.S_IRWXU | stat.S_IRWXG
        os.chmod(log_dir, mode)

    #extract variables from settings dictionary
    sigma = contrast_settings['blur']
    hist = contrast_settings['equalize_hist']
    adapthist = contrast_settings['equalize_adapthist']
    gamma = contrast_settings['gamma_adjust']
    sobel_option = contrast_settings['sobel_toggle']
    sobel = contrast_settings['sobel_factor']
    invert = contrast_settings['invert_img']
    v_min = contrast_settings['v_min']
    v_max = contrast_settings['v_max']

    # Sorted list of image names from raw directory
    img_list = get_img_names(raw_dir)

    number_of_images = len(img_list)

    #Adjust contrast

    for j in range(number_of_images):

        img_path = os.path.join(raw_dir, img_list[j])
        image = get_image(img_path)  #np.float32
        adjusted_image = contrast(image, sigma, hist, adapthist, gamma,
                                  sobel_option, sobel, invert, v_min, v_max)

        #Save processed image
        if is_2D:
            adjusted_name = os.path.join(
                process_dir,
                identifier + "_adjusted_img_" + str(j).zfill(3) + ".png")
        else:
            adjusted_name = os.path.join(
                process_dir,
                identifier + "_adjusted_frame_" + str(j).zfill(3) + ".png")

        imwrite(adjusted_name, adjusted_image)
        print("Saved " + adjusted_name + "; image " + str(j + 1) + " of " +
              str(number_of_images))

    print('Adjusted images have been saved in folder: ' + process_dir)

    #log in json for future reference

    log_data = {}
    log_data['date'] = str(datetime.datetime.now())
    log_data['raw_settings'] = contrast_settings
    log_data['raw'] = raw_folder
    log_data['identifier'] = identifier
    log_data['combined'] = False

    #save log in JSON format
    #save with identifier; should be saved in "log" folder

    log_path = os.path.join(log_dir,
                            identifier + "_contrast_adjustment_log.json")

    with open(log_path, "w") as write_file:
        json.dump(log_data, write_file)

    print('A record of the settings used has been saved in folder: ' + log_dir)

    return None