Untitled

 avatar
unknown
plain_text
a month ago
8.2 kB
4
Indexable
#######################################################################
# Part 1 - numpy
def get_highest_weight_loss_participant(training_data, participant_names):
    """
    :param training_data: a numpy matrix of shape (n_participants, n_months) .
    :param participant_names: a list of strings, each string represents a participant.
    :return: the highest weight loss participant's name.
    """
    diff = training_data[:,0] - training_data[:,-1]
    return participant_names[np.argmax(np.abs(diff))]

def get_diff_data(training_data):
    """
    :param training_data: a numpy matrix of shape (n_participants, n_months).
    :return: a numpy matrix of shape (n_participants, n_months-1) representing the difference between each pair of consecutive months.
    """
    return training_data[:, 1:] - training_data[:, :-1]


def get_highest_change_month(training_data, study_months):
    """
    :param training_data: a numpy matrix of shape (n_participants, n_months).
    :param study_months: a list of strings, each string represents a month in the study.
    :return: the month with the highest change across participants.
    """
    diff = np.abs(training_data[:, 1:] - training_data[:, :-1])
    total_changes = np.sum(diff, axis=0)
    return study_months[np.argmax(total_changes)]


def get_inconsistent_participants(training_data, participant_names):
    """
    :param training_data: a numpy matrix of shape (n_participants, n_months).
    :param participant_names: a list of strings, each string represents a participant.
    :return: a list of participant names that didn't lose weight consistently every month throughout the study.
    If there are no such participants, the function will return an empty list.
    """
    diff = get_diff_data(training_data)
    pos = np.any(diff >= 0, axis=1)
    return list(np.array(participant_names)[pos])

#######################################################################
# Part 2 - numpy image processing

def read_image(img_path, mode='L'):
    """
    :param img_path: path of an image to read
    :param mode: (for bonus) the mode of the image to be read, 'L' for grayscale (default), 'RGB' for RGB.
    :return: a uint8 numpy array representing the image, with values between 0 and 255.
    will return an array shaped (h,w) (bonus: if mode == 'L', or (h,w,3) if mode == 'RGB'.)
    """
    read_img = imread(img_path, mode=mode)
    if read_img.dtype != np.uint8:
        read_img = read_img.astype(np.uint8)
    return read_img


def naive_blending(img1, img2, mask):
    """
    :param img1: a uint8 numpy array representing an image
    :param img2: a uint8 numpy array representing an image
    :param mask: a uint8 numpy array representing a boolean image in equal size of im1 and im2, that defines how the two images should be blended.
    :return: a blended image where img_1 pixels are used for the white areas of the mask, and img_2 pixels are used for the black areas.
    """
    n_msk = mask / 255
    blend = img1 * n_msk + img2* (1- n_msk)
    return blend.astype(np.uint8)

def get_nbhd(img, x, y, nb_size):
    return img[max(x-nb_size,0):min(x+nb_size+1,img.shape[0]), max(y-nb_size,0):min(y+nb_size+1,img.shape[1])]

def blur(img, nb_size):
    blurry_img = np.zeros_like(img, dtype=np.uint8)
    for i in range (img.shape[0]):
        for j in range (img.shape[1]):
            blurry_img[i,j] = np.mean(get_nbhd(img, i, j, nb_size))
    return blurry_img.astype(np.uint8)


def blur_and_downsample(img, nb_size=5):
    """
    A function that blurs the given image, and then reduces its resolution by 2 (both width and length) by choosing
    every second pixel in every second row.
    :param img: a uint8 numpy array representing an image
    :param nb_size: The neighborhood size to be used for blurring
    :return: the reduced and blurred image
    """
    blurry_img_n = blur(img, nb_size)
    blurry_img_n = blurry_img_n[::2, ::2]
    return blurry_img_n


def build_gaussian_pyramid(img, max_levels, nb_size=5):
    """
    A function that builds a gaussian pyramid of the given image, by sequentially blurring and down-sampling the current
    image until reaching max_levels.
    :param img: a uint8 numpy array representing an image.
    :param max_levels: The maximal depth levels that should be constructed.
    :param nb_size: The neighborhood size to be used for blurring.
    :return: a list representing the image's gaussian pyramid, each entry is the previous image down-sampled to half the
    resolution of the previous one.
    """
    pyramid = [img]
    for i in range(1, max_levels):
        prev_func = blur_and_downsample(pyramid[-1], nb_size)
        if prev_func.shape[0] < 2 or prev_func.shape[1] < 2:
            break
        pyramid.append(prev_func)
    return pyramid

def upsample_and_blur(img, nb_size=5):
    """
    A function that doubles the size of the given image, and blurs it.
    :param img: a uint8 numpy array representing an image.
    :param nb_size: The neighborhood size to be used for blurring.
    :return: a numpy array representing the expanded blurred image.
    """
    new_row_col = np.repeat(np.repeat(img, 2, axis = 0), 2 ,axis = 1)
    return blur(new_row_col, nb_size = 5)

def build_laplacian_pyramid(img, max_levels, nb_size=5):
    """
    A function that builds a laplacian pyramid of the given image, by sequentially up-sampling the next level gaussian
    image and subtracting it from the current level gaussian image, until reaching max_levels.
    :param img: a uint8 numpy array representing an image.
    :param max_levels: The maximal depth levels that should be constructed
    :param nb_size: The neighborhood size to be used for blurring.
    :return: a list representing a laplacian pyramid of the given image.
    """
    pyramid = build_gaussian_pyramid(img, max_levels, nb_size)
    laplacian = []
    for i in range(len(pyramid) - 1):
        upsampled = upsample_and_blur(pyramid[i + 1], nb_size)

        if upsampled.shape != pyramid[i].shape:
            upsampled = upsampled[:pyramid[i].shape[0], :pyramid[i].shape[1]]

        laplacian.append(pyramid[i] - upsampled)
    laplacian.append(pyramid[-1])
    return laplacian

def laplacian_pyramid_to_image(laplacian_pyramid, nb_size=5):
    """
    A function that reconstructs an image from the given laplacian pyramid, by iteratively combining all laplacian
    images after up-sampling.
    :param laplacian_pyramid: a list representing a laplacian pyramid.
    :param nb_size: The neighborhood size to be used for blurring.
    :return: The reconstructed image.
    """
    reverse_img = laplacian_pyramid[-1]

    for i in range(len(laplacian_pyramid)-2, -1, -1):
        upsampled = upsample_and_blur(reverse_img, nb_size)
        upsampled = upsampled[:upsampled.shape[0], :upsampled.shape[1]]

        reverse_img = laplacian_pyramid[i] + upsampled
    return reverse_img



def pyramid_blending(img1, img2, mask, max_levels, nb_size=5):
    """
    A function that blends two images using pyramids.
    :param img1: a uint8 numpy array representing a grayscale image that will compose the white parts of the mask.
    :param img2: a uint8 numpy array representing a grayscale image that will compose the black parts of the mask.
    :param mask: a uint8 numpy array representing a boolean image in equal size of im1 and im2, that defines how the two images should be blended
    :param max_levels: The max depth of the pyramids used in this function
    :param nb_size: The neighborhood size to be used for blurring.
    :return: The blended image
    """
    img11 = build_laplacian_pyramid(img1,max_levels, nb_size)
    img22 = build_laplacian_pyramid(img2,max_levels, nb_size)
    maskk = build_gaussian_pyramid(mask, max_levels, nb_size)
    for i in range(len(maskk)):
        for row in range(maskk[i].shape[0]):
            for col in range(maskk[i].shape[1]):
                if maskk[i][row][col] != 0:
                    maskk[i][row][col] = 255
    new_pyramid = []
    for i in range(max_levels):
        blender = naive_blending(img11[i], img22[i], maskk[i])
        new_pyramid.append(blender)
    final_image = laplacian_pyramid_to_image(new_pyramid, nb_size)
    return final_image
Editor is loading...
Leave a Comment