def test_rescale_compress_lossless_maps(self):
        """Tests the function `rescale_compress_lossless_maps` in the file "lossless/compression.py".
        
        The test is successful if, when using the binary probabilities
        saved at "lossless/pseudo_data/binary_probabilities_scale_compress_invalid_0.npy",
        the program raises `RuntimeError` of type 4. This must also
        occur when using the binary probabilities saved at
        "lossless/pseudo_data/binary_probabilities_scale_compress_invalid_1.npy".
        However, when using the binary probabilities saved at
        "lossless/pseudo_data/binary_probabilities_scale_compress_valid.npy",
        the program should not raise any exception.
        
        """
        height_map = 96
        width_map = 48
        bin_widths_test = numpy.array([1.5, 1.5, 1.5], dtype=numpy.float32)

        # In "lossless/pseudo_data/binary_probabilities_scale_compress_invalid_0.npy",
        # several binary probabilities are equal to `nan`
        # but the associated binary decisions may occur.
        # In "lossless/pseudo_data/binary_probabilities_scale_compress_invalid_1.npy",
        # several binary probabilities are either negative
        # or larger than 1.
        path_to_binary_probabilities = 'lossless/pseudo_data/binary_probabilities_scale_compress_valid.npy'
        print('The binary probabilities at "{}" are used.'.format(
            path_to_binary_probabilities))

        # The optional argument `loc` of the function
        # `numpy.random.normal` is set to 0.0 as the
        # data must be centered.
        centered_data_0 = numpy.random.normal(loc=0.,
                                              scale=5.,
                                              size=(1, height_map, width_map,
                                                    1)).astype(numpy.float32)
        centered_data_1 = numpy.random.normal(loc=0.,
                                              scale=0.2,
                                              size=(1, height_map, width_map,
                                                    1)).astype(numpy.float32)
        centered_data_2 = numpy.random.normal(loc=0.,
                                              scale=0.5,
                                              size=(1, height_map, width_map,
                                                    1)).astype(numpy.float32)
        centered_data = numpy.concatenate(
            (centered_data_0, centered_data_1, centered_data_2), axis=3)
        expanded_centered_quantized_data = tls.quantize_per_map(
            centered_data, bin_widths_test)
        centered_quantized_data = numpy.squeeze(
            expanded_centered_quantized_data, axis=0)
        nb_bits = lossless.compression.rescale_compress_lossless_maps(
            centered_quantized_data, bin_widths_test,
            path_to_binary_probabilities)
        print('Number of bits in the bitstream: {}'.format(nb_bits))
Пример #2
0
 def test_quantize_per_map(self):
     """Tests the function `quantize_per_map`.
     
     The test is successful if, for each map
     of data, the map of quantized data is
     consistent with the quantization bin width.
     
     """
     data = numpy.random.normal(loc=0., scale=5., size=(2, 1, 3, 2)).astype(numpy.float32)
     bin_widths = numpy.array([1., 10.], dtype=numpy.float32)
     quantized_data = tls.quantize_per_map(data, bin_widths)
     print('1st map of data after being flattened:')
     print(data[:, :, :, 0].flatten())
     print('1st quantization bin width: {}'.format(bin_widths[0]))
     print('1st map of quantized data after being flattened:')
     print(quantized_data[:, :, :, 0].flatten())
     print('2nd map of data after being flattened:')
     print(data[:, :, :, 1].flatten())
     print('2nd quantization bin width: {}'.format(bin_widths[1]))
     print('2nd map of quantized data after being flattened:')
     print(quantized_data[:, :, :, 1].flatten())
Пример #3
0
 def test_rate_3d(self):
     """Tests the function `rate_3d`.
     
     The test is successful if the rate computed
     by the function is close to the approximate
     theoretical rate.
     
     """
     h_in = 768
     w_in = 512
     height_map = 256
     width_map = 256
     bin_widths = numpy.array([0.2, 0.5], dtype=numpy.float32)
     expanded_latent_float32 = numpy.random.normal(loc=0.,
                                                   scale=1.,
                                                   size=(1, height_map, width_map, 2)).astype(numpy.float32)
     expanded_quantized_latent_float32 = tls.quantize_per_map(expanded_latent_float32, bin_widths)
     quantized_latent_float32 = numpy.squeeze(expanded_quantized_latent_float32,
                                              axis=0)
     rate = tls.rate_3d(quantized_latent_float32,
                        bin_widths,
                        h_in,
                        w_in)
     
     # The formula below is derived from the
     # theorem 8.3.1 in the book "Elements of information theory",
     # 2nd edition, written by Thomas M. Cover and Joy A. Thomas.
     # Warning! The quantization in this theorem is not the
     # uniform scalar quantization. But, the two quantizations
     # get close as the quantization bin width tends to 0.
     approx_theoretical_entropy = -numpy.log2(bin_widths[0]) \
                                  - numpy.log2(bin_widths[1]) \
                                  + (numpy.log(2.*numpy.pi) + 1.)/numpy.log(2.)
     approx_theoretical_rate = approx_theoretical_entropy*height_map*width_map/(h_in*w_in)
     print('Rate computed by the function: {}'.format(rate))
     print('Approximate theoretical rate: {}'.format(approx_theoretical_rate))
def mask_maps(y_float32, sess, isolated_decoder, bin_widths, idx_unmasked_map, map_mean, height_crop, width_crop, paths):
    """Masks all the latent variable feature maps except one.
    
    All the latent variable feature maps except one
    are masked. Then, the latent variable feature maps
    are quantized. Finally, the quantized latent
    variable feature maps are passed through the
    decoder of the entropy autoencoder.
    
    Parameters
    ----------
    y_float32 : numpy.ndarray
        4D array with data-type `numpy.float32`.
        Latent variables. `y_float32[i, :, :, j]`
        is the jth latent variable feature map of
        the ith example.
    sess : Session
        Session that runs the graph.
    isolated_decoder : IsolatedDecoder
        Decoder of the entropy autoencoder. The graph
        of the decoder is built to process one example
        at a time.
    bin_widths : numpy.ndarray
        1D array with data-type `numpy.float32`.
        Quantization bin widths at the end of the
        training.
    idx_unmasked_map : int
        Index of the unmasked latent variable
        feature map.
    map_mean : numpy.ndarray
        1D array with data-type `numpy.float32`.
        Latent variable feature map means.
    height_crop : int
        Height of the crop of the decoder output.
    width_crop : int
        Width of the crop of the decoder output.
    paths : list
        The ith string in this list is the path
        to the ith saved crop of the decoder output.
        Each path ends with ".png".
    
    Raises
    ------
    ValueError
        If `len(paths)` is not equal to `y_float32.shape[0]`.
    
    """
    if len(paths) != y_float32.shape[0]:
        raise ValueError('`len(paths)` is not equal to `y_float32.shape[0]`.')
        
    # The same latent variable feature map is
    # iteratively overwritten in the loop below.
    masked_y_float32 = numpy.tile(numpy.reshape(map_mean, (1, 1, 1, y_float32.shape[3])),
                                  (1, y_float32.shape[1], y_float32.shape[2], 1))
    for i in range(y_float32.shape[0]):
        masked_y_float32[0, :, :, idx_unmasked_map] = y_float32[i, :, :, idx_unmasked_map]
        quantized_y_float32 = tls.quantize_per_map(masked_y_float32, bin_widths)
        reconstruction_float32 = sess.run(
            isolated_decoder.node_reconstruction,
            feed_dict={isolated_decoder.node_quantized_y:quantized_y_float32}
        )
        reconstruction_uint8 = numpy.squeeze(tls.cast_bt601(reconstruction_float32),
                                             axis=(0, 3))
        tls.save_image(paths[i],
                       reconstruction_uint8[0:height_crop, 0:width_crop])
def activate_latent_variable(sess, isolated_decoder, h_in, w_in, bin_widths, row_activation, col_activation,
                             idx_map_activation, activation_value, map_mean, height_crop, width_crop, path_to_crop):
    """Activates one latent variable and deactivates the others.
    
    One latent variable is activated and the others
    are deactivated. Then, the latent variable feature
    maps are quantized. Finally, the quantized latent
    variable feature maps are passed through the decoder
    of the entropy autoencoder.
    
    Parameters
    ----------
    sess : Session
        Session that runs the graph.
    isolated_decoder : IsolatedDecoder
        Decoder of the entropy autoencoder. The graph
        of the decoder is built to process one example
        at a time.
    h_in : int
        Height of the images returned by the
        isolated decoder.
    w_in : int
        Width of the images returned by the
        isolated decoder.
    bin_widths : numpy.ndarray
        1D array with data-type `numpy.float32`.
        Quantization bin widths at the end of the
        training.
    row_activation : int
        Row of the activated latent variable in the
        latent variable feature map of index `idx_map_activation`.
    col_activation : int
        Column of the activated latent variable in the
        latent variable feature map of index `idx_map_activation`.
    idx_map_activation : int
        Index of the latent variable feature map
        containing the activated latent variable.
    activation_value : float
        Activation value.
    map_mean : numpy.ndarray
        1D array with data-type `numpy.float32`.
        Latent variable feature map means.
    height_crop : int
        Height of the crop of the decoder output.
    width_crop : int
        Width of the crop of the decoder output.
    path_to_crop : str
        Path to the saved crop of the decoder
        output. The path ends with ".png".
    
    Raises
    ------
    ValueError
        If `row_activation` is not strictly positive.
    ValueError
        If `col_activation` is not strictly positive.
    
    """
    if row_activation <= 0:
        raise ValueError('`row_activation` is not strictly positive.')
    if col_activation <= 0:
        raise ValueError('`col_activation` is not strictly positive.')
    y_float32 = numpy.tile(numpy.reshape(map_mean, (1, 1, 1, csts.NB_MAPS_3)),
                           (1, h_in//csts.STRIDE_PROD, w_in//csts.STRIDE_PROD, 1))
    y_float32[0, row_activation, col_activation, idx_map_activation] = activation_value
    quantized_y_float32 = tls.quantize_per_map(y_float32, bin_widths)
    reconstruction_float32 = sess.run(
        isolated_decoder.node_reconstruction,
        feed_dict={isolated_decoder.node_quantized_y:quantized_y_float32}
    )
    reconstruction_uint8 = numpy.squeeze(tls.cast_bt601(reconstruction_float32),
                                         axis=(0, 3))
    
    # The ratio between the feature map height and the
    # decoded image height is equal to `csts.STRIDE_PROD`.
    row_offset = (row_activation - 1)*csts.STRIDE_PROD
    col_offset = (col_activation - 1)*csts.STRIDE_PROD
    tls.save_image(path_to_crop,
                   reconstruction_uint8[row_offset:row_offset + height_crop, col_offset:col_offset + width_crop])
    def test_compress_lossless_maps(self):
        """Tests the function `compress_lossless_maps` in the file "lossless/compression.py".
        
        The test is successful if, for each centered quantized
        latent variable feature map, the coding cost computed
        by the function is slightly larger than the approximate
        theoretical coding cost.
        
        """
        height_map = 384
        width_map = 384
        bin_widths_test = numpy.array([0.5, 0.25], dtype=numpy.float32)
        laplace_scales = numpy.array([0.5, 3.], dtype=numpy.float32)

        # Note that the binary probabilities saved at
        # "lossless/pseudo_data/binary_probabilities_compress_maps_0.npy"
        # and those saved at
        # "lossless/pseudo_data/binary_probabilities_compress_maps_1.npy"
        # are specific to the two Laplace distributions
        # below. This means that the binary probabilities
        # must be modified if `laplace_scales` is modified.
        paths_to_binary_probabilities = [
            'lossless/pseudo_data/binary_probabilities_compress_maps_0.npy',
            'lossless/pseudo_data/binary_probabilities_compress_maps_1.npy'
        ]

        centered_data_0 = numpy.random.laplace(loc=0.,
                                               scale=laplace_scales[0].item(),
                                               size=(1, height_map, width_map,
                                                     1)).astype(numpy.float32)
        centered_data_1 = numpy.random.laplace(loc=0.,
                                               scale=laplace_scales[1].item(),
                                               size=(1, height_map, width_map,
                                                     1)).astype(numpy.float32)
        centered_data = numpy.concatenate((centered_data_0, centered_data_1),
                                          axis=3)
        expanded_centered_quantized_data = tls.quantize_per_map(
            centered_data, bin_widths_test)
        centered_quantized_data = numpy.squeeze(
            expanded_centered_quantized_data, axis=0)
        tiled_bin_widths = numpy.tile(
            numpy.reshape(bin_widths_test, (1, 1, 2)),
            (height_map, width_map, 1))
        ref_int16 = tls.cast_float_to_int16(centered_quantized_data /
                                            tiled_bin_widths)
        (rec_int16_0, nb_bits_each_map_0) = \
            lossless.compression.compress_lossless_maps(ref_int16,
                                                        paths_to_binary_probabilities[0])
        numpy.testing.assert_equal(
            ref_int16,
            rec_int16_0,
            err_msg=
            'The test fails as the lossless compression alters the signed integers.'
        )
        (rec_int16_1, nb_bits_each_map_1) = \
            lossless.compression.compress_lossless_maps(ref_int16,
                                                        paths_to_binary_probabilities[1])
        numpy.testing.assert_equal(
            ref_int16,
            rec_int16_1,
            err_msg=
            'The test fails as the lossless compression alters the signed integers.'
        )

        # The formula below is derived from the
        # theorem 8.3.1 in the book "Elements of information theory",
        # 2nd edition, written by Thomas M. Cover and Joy A. Thomas.
        # Warning! The quantization in this theorem is not the
        # uniform scalar quantization. But, the two quantizations
        # get close as the quantization bin width tends to 0.
        approx_theoretical_entropies = -numpy.log2(bin_widths_test) + (
            numpy.log(2. * laplace_scales) + 1.) / numpy.log(2.)
        print('B0 denotes the binary probabilities saved at "{}".'.format(
            paths_to_binary_probabilities[0]))
        print('B1 denotes the binary probabilities saved at "{}".'.format(
            paths_to_binary_probabilities[1]))
        print('\n1st centered quantized latent variable feature map.')
        print('Approximate theoretical coding cost: {} bits.'.format(
            approx_theoretical_entropies[0] * height_map * width_map))
        print('Coding cost computed by the function via B0: {} bits.'.format(
            nb_bits_each_map_0[0]))
        print('Coding cost computed by the function via B1: {} bits.'.format(
            nb_bits_each_map_1[0]))
        print('\n2nd centered quantized latent variable feature map.')
        print('Approximate theoretical coding cost: {} bits.'.format(
            approx_theoretical_entropies[1] * height_map * width_map))
        print('Coding cost computed by the function via B0: {} bits.'.format(
            nb_bits_each_map_0[1]))
        print('Coding cost computed by the function via B1: {} bits.'.format(
            nb_bits_each_map_1[1]))
def vary_gamma_fix_bin_widths(reference_uint8, bin_width_init, idxs_training,
                              gammas_scaling, batch_size, path_to_checking_r,
                              list_rotation, positions_top_left):
    """Computes a series of pairs (rate, PSNR).
    
    Several entropy autoencoders, each trained with a
    different scaling coefficient, are considered. At
    training time, the quantization bin widths were fixed.
    For each scaling coefficient, for each luminance
    image, the pair (rate, PSNR) associated to the
    compression of the luminance image via the entropy
    autoencoder trained with the scaling coefficient
    is computed.
    
    Parameters
    ----------
    reference_uint8 : numpy.ndarray
        3D array with data-type `numpy.uint8`.
        Luminance images. `reference_uint8[i, :, :]`
        is the ith luminance image.
    bin_width_init : float
        Value of the quantization bin widths
        at the beginning of the 1st training.
        In this function, the quantization bin
        widths are the same at training time
        and at test time.
    idxs_training : numpy.ndarray
        1D array with data-type `numpy.int32`.
        Its ith element is the training phase
        index of the entropy autoencoder trained
        with the ith scaling coefficient.
    gammas_scaling : numpy.ndarray
        1D array with data-type `numpy.float64`.
        Scaling coefficients.
    batch_size : int
        Size of the mini-batches for encoding
        and decoding via the entropy autoencoders.
    path_to_checking_r : str
        Path to the folder containing the
        luminance images before/after being
        compressed via entropy autoencoders.
    list_rotation : list
        Each integer in this list is the index
        of a rotated luminance image.
    positions_top_left : numpy.ndarray
        2D array with data-type `numpy.int32`.
        This array is dedicated to visualization.
        `positions_top_left[:, i]` contains the
        row and the column of the image pixel at
        the top-left of the ith crop of each
        luminance image after being compressed
        via entropy autoencoders.
    
    Returns
    -------
    tuple
        numpy.ndarray
            2D array with data-type `numpy.float64`.
            The element at the position [i, j] in this
            array is the rate associated to the compression
            of the jth luminance image via the entropy
            autoencoder trained with the ith scaling
            coefficient.
        numpy.ndarray
            2D array with data-type `numpy.float64`.
            The element at the position [i, j] in this
            array is the PSNR associated to the compression
            of the jth luminance image via the entropy
            autoencoder trained with the ith scaling
            coefficient.
    
    Raises
    ------
    ValueError
        If `gammas_scaling.size` is not equal to
        `idxs_training.size`.
    
    """
    nb_points = gammas_scaling.size
    if idxs_training.size != nb_points:
        raise ValueError(
            '`gammas_scaling.size` is not equal to `idxs_training.size`.')
    (nb_images, h_in, w_in) = reference_uint8.shape
    rate = numpy.zeros((nb_points, nb_images))
    psnr = numpy.zeros((nb_points, nb_images))
    for i in range(nb_points):
        gamma_scaling = gammas_scaling[i].item()
        idx_training = idxs_training[i].item()
        suffix = '{0}_{1}'.format(tls.float_to_str(bin_width_init),
                                  tls.float_to_str(gamma_scaling))
        path_to_nb_itvs_per_side_load = 'eae/results/{0}/nb_itvs_per_side_{1}.pkl'.format(
            suffix, idx_training)
        path_to_restore = 'eae/results/{0}/model_{1}.ckpt'.format(
            suffix, idx_training)
        path_to_storage = os.path.join(
            path_to_checking_r, 'reconstruction_vary_gamma_fix_bin_widths',
            suffix)
        if not os.path.isdir(path_to_storage):
            os.makedirs(path_to_storage)

        # Every time `gamma_scaling` changes, a new
        # entropy autoencoder is created.
        entropy_ae = EntropyAutoencoder(batch_size, h_in, w_in, bin_width_init,
                                        gamma_scaling,
                                        path_to_nb_itvs_per_side_load, False)
        with tf.Session() as sess:
            entropy_ae.initialization(sess, path_to_restore)
            y_float32 = eae.batching.encode_mini_batches(
                numpy.expand_dims(reference_uint8, axis=3), sess, entropy_ae,
                batch_size)

            # `bin_widths` are the quantization bin widths
            # at training time.
            bin_widths = entropy_ae.get_bin_widths()

        # The graph of the entropy autoencoder is destroyed.
        tf.reset_default_graph()

        # Every time `gamma_scaling` changes, a new
        # decoder is created.
        isolated_decoder = IsolatedDecoder(batch_size, h_in, w_in, False)
        quantized_y_float32 = tls.quantize_per_map(y_float32, bin_widths)
        with tf.Session() as sess:
            isolated_decoder.initialization(sess, path_to_restore)
            expanded_reconstruction_uint8 = eae.batching.decode_mini_batches(
                quantized_y_float32, sess, isolated_decoder, batch_size)

        # The elements of `reconstruction_uint8` span
        # the range [|16, 235|].
        reconstruction_uint8 = numpy.squeeze(expanded_reconstruction_uint8,
                                             axis=3)

        # The graph of the decoder is destroyed.
        tf.reset_default_graph()
        for j in range(nb_images):
            rate[i, j] = tls.rate_3d(quantized_y_float32[j, :, :, :],
                                     bin_widths, h_in, w_in)
            psnr[i, j] = tls.psnr_2d(reference_uint8[j, :, :],
                                     reconstruction_uint8[j, :, :])

            paths = [
                os.path.join(path_to_storage,
                             'reconstruction_{}.png'.format(j))
            ]
            paths += [
                os.path.join(
                    path_to_storage,
                    'reconstruction_{0}_crop_{1}.png'.format(j, index_crop))
                for index_crop in range(positions_top_left.shape[1])
            ]
            tls.visualize_rotated_luminance(reconstruction_uint8[j, :, :], j
                                            in list_rotation,
                                            positions_top_left, paths)
    return (rate, psnr)
def fix_gamma(reference_uint8, bin_width_init, multipliers, idx_training,
              gamma_scaling, batch_size, are_bin_widths_learned, is_lossless,
              path_to_checking_r, list_rotation, positions_top_left):
    """Computes a series of pairs (rate, PSNR).
    
    A single entropy autoencoder is considered. At training
    time, the quantization bin widths were either fixed or
    learned.
    For each multiplier, the quantization bin widths
    at the end of the training are multiplied by the
    multiplier, yielding a set of test quantization bin
    widths. Then, for each set of test quantization bin
    widths, for each luminance image, the pair (rate, PSNR)
    associated to the compression of the luminance image
    via the single entropy autoencoder and the set of
    test quantization bin widths is computed.
    
    Parameters
    ----------
    reference_uint8 : numpy.ndarray
        3D array with data-type `numpy.uint8`.
        Luminance images. `reference_uint8[i, :, :]`
        is the ith luminance image.
    bin_width_init : float
        Value of the quantization bin widths
        at the beginning of the 1st training.
    multipliers : numpy.ndarray
        1D array with data-type `numpy.float32`.
        Multipliers.
    idx_training : int
        Training phase index of the single
        entropy autoencoder.
    gamma_scaling : float
        Scaling coefficient of the single
        entropy autoencoder.
    batch_size : int
        Size of the mini-batches for encoding
        and decoding via the single entropy
        autoencoder.
    are_bin_widths_learned : bool
        Were the quantization bin widths learned
        at training time?
    is_lossless : bool
        Are the quantized latent variables coded
        losslessly?
    path_to_checking_r : str
        Path to the folder containing the luminance
        images before/after being compressed via the
        single entropy autoencoder.
    list_rotation : list
        Each integer in this list is the index
        of a rotated luminance image.
    positions_top_left : numpy.ndarray
        2D array with data-type `numpy.int32`.
        This array is dedicated to visualization.
        `positions_top_left[:, i]` contains the
        row and the column of the image pixel at
        the top-left of the ith crop of each
        luminance image after being compressed
        via the single entropy autoencoder.
    
    Returns
    -------
    tuple
        numpy.ndarray
            2D array with data-type `numpy.float64`.
            The element at the position [i, j] in this
            array is the rate associated to the compression
            of the jth luminance image via the single
            entropy autoencoder and the ith set of test
            quantization bin widths.
        numpy.ndarray
            2D array with data-type `numpy.float64`.
            The element at the position [i, j] in this
            array is the PSNR associated to the compression
            of the jth luminance image via the single
            entropy autoencoder and the ith set of test
            quantization bin widths.
    
    """
    nb_points = multipliers.size
    (nb_images, h_in, w_in) = reference_uint8.shape
    rate = numpy.zeros((nb_points, nb_images))
    psnr = numpy.zeros((nb_points, nb_images))
    if are_bin_widths_learned:
        suffix = 'learning_bw_{0}_{1}'.format(tls.float_to_str(bin_width_init),
                                              tls.float_to_str(gamma_scaling))
    else:
        suffix = '{0}_{1}'.format(tls.float_to_str(bin_width_init),
                                  tls.float_to_str(gamma_scaling))
    path_to_nb_itvs_per_side_load = 'eae/results/{0}/nb_itvs_per_side_{1}.pkl'.format(
        suffix, idx_training)
    path_to_restore = 'eae/results/{0}/model_{1}.ckpt'.format(
        suffix, idx_training)
    if is_lossless:
        path_to_vis = os.path.join(path_to_checking_r,
                                   'reconstruction_fix_gamma', suffix,
                                   'lossless')
    else:
        path_to_vis = os.path.join(path_to_checking_r,
                                   'reconstruction_fix_gamma', suffix,
                                   'approx')
    path_to_stats = 'lossless/results/{0}/training_index_{1}/'.format(
        suffix, idx_training)
    path_to_map_mean = os.path.join(path_to_stats, 'map_mean.npy')

    # A single entropy autoencoder is created.
    entropy_ae = EntropyAutoencoder(batch_size, h_in, w_in, bin_width_init,
                                    gamma_scaling,
                                    path_to_nb_itvs_per_side_load,
                                    are_bin_widths_learned)
    with tf.Session() as sess:
        entropy_ae.initialization(sess, path_to_restore)
        y_float32 = eae.batching.encode_mini_batches(
            numpy.expand_dims(reference_uint8, axis=3), sess, entropy_ae,
            batch_size)

        # `bin_widths` are the quantization bin widths
        # at the end of the training.
        bin_widths = entropy_ae.get_bin_widths()

    # The graph of the entropy autoencoder is destroyed.
    tf.reset_default_graph()

    # A single decoder is created.
    isolated_decoder = IsolatedDecoder(batch_size, h_in, w_in,
                                       are_bin_widths_learned)

    # `array_nb_deads[i, j]` stores the number of dead feature
    # maps at the rate of index i for the luminance image of
    # index j.
    array_nb_deads = numpy.zeros((nb_points, nb_images), dtype=numpy.int32)

    # `map_mean[i]` is the approximate mean of the latent
    # variable feature map of index i. It was computed on
    # the extra set.
    map_mean = numpy.load(path_to_map_mean)
    tiled_map_mean = numpy.tile(
        map_mean, (nb_images, y_float32.shape[1], y_float32.shape[2], 1))

    # `idx_map_exception` was also computed on the extra set.
    if is_lossless:
        with open(os.path.join(path_to_stats, 'idx_map_exception.pkl'),
                  'rb') as file:
            idx_map_exception = pickle.load(file)
    centered_y_float32 = y_float32 - tiled_map_mean
    with tf.Session() as sess:
        isolated_decoder.initialization(sess, path_to_restore)
        for i in range(nb_points):
            multiplier = multipliers[i].item()
            str_multiplier = tls.float_to_str(multiplier)
            bin_widths_test = multiplier * bin_widths
            centered_quantized_y_float32 = tls.quantize_per_map(
                centered_y_float32, bin_widths_test)

            # For a given luminance image, if at least a coefficient
            # of a feature map is different from 0.0, this feature map
            # is viewed as not dead.
            array_nb_deads[i, :] = tls.count_nb_deads(
                centered_quantized_y_float32)
            off_centered_quantized_y_float32 = centered_quantized_y_float32 + tiled_map_mean
            expanded_reconstruction_uint8 = eae.batching.decode_mini_batches(
                off_centered_quantized_y_float32, sess, isolated_decoder,
                batch_size)

            # The elements of span `reconstruction_uint8`
            # the range [|16, 235|].
            reconstruction_uint8 = numpy.squeeze(expanded_reconstruction_uint8,
                                                 axis=3)

            # The binary probabilities were also computed
            # on the extra set.
            if is_lossless:
                path_to_binary_probabilities = os.path.join(
                    path_to_stats,
                    'binary_probabilities_{}.npy'.format(str_multiplier))
            path_to_storage = os.path.join(
                path_to_vis, 'multiplier_{}'.format(str_multiplier))
            if not os.path.isdir(path_to_storage):
                os.makedirs(path_to_storage)
            for j in range(nb_images):
                if is_lossless:
                    nb_bits = lossless.compression.rescale_compress_lossless_maps(
                        centered_quantized_y_float32[j, :, :, :],
                        bin_widths_test,
                        path_to_binary_probabilities,
                        idx_map_exception=idx_map_exception)
                    rate[i, j] = float(nb_bits) / (h_in * w_in)
                else:
                    rate[i, j] = tls.rate_3d(
                        centered_quantized_y_float32[j, :, :, :],
                        bin_widths_test, h_in, w_in)
                psnr[i, j] = tls.psnr_2d(reference_uint8[j, :, :],
                                         reconstruction_uint8[j, :, :])

                paths = [
                    os.path.join(path_to_storage,
                                 'reconstruction_{}.png'.format(j))
                ]
                paths += [
                    os.path.join(
                        path_to_storage,
                        'reconstruction_{0}_crop_{1}.png'.format(
                            j, index_crop))
                    for index_crop in range(positions_top_left.shape[1])
                ]
                tls.visualize_rotated_luminance(reconstruction_uint8[j, :, :],
                                                j in list_rotation,
                                                positions_top_left, paths)

    # The graph of the decoder is destroyed.
    tf.reset_default_graph()
    path_to_directory_nb_dead = os.path.join(path_to_vis, 'nb_dead')
    if not os.path.isdir(path_to_directory_nb_dead):
        os.makedirs(path_to_directory_nb_dead)
    plot_nb_dead_feature_maps(rate, array_nb_deads, [
        os.path.join(path_to_directory_nb_dead, 'nb_dead_{}.png'.format(i))
        for i in range(nb_images)
    ])
    return (rate, psnr)
Пример #9
0
def compute_binary_probabilities(y_float32, bin_widths_test, map_mean,
                                 truncated_unary_length):
    """Computes the binary probabilities associated to each latent variable feature map.
    
    Parameters
    ----------
    y_float32 : numpy.ndarray
        4D array with data-type `numpy.float32`.
        Latent variable feature maps. `y_float32[i, :, :, j]`
        is the jth latent variable feature map of the ith
        example.
    bin_widths_test : numpy.ndarray
        1D array with data-type `numpy.float32`.
        Test quantization bin widths.
    map_mean : numpy.ndarray
        1D array with data-type `numpy.float32`.
        Latent variable feature map means.
    truncated_unary_length : int
        Length of the truncated unary prefix.
    
    Returns
    -------
    numpy.ndarray
        2D array with data-type `numpy.float64`.
        Binary probabilities. The element at the position
        [i, j] in this array is the probability the jth
        binary decision is 0 in the truncated unary prefix
        associated to the ith absolute centered-quantized
        latent variable feature map.
    
    """
    (nb_images, height_map, width_map, nb_maps) = y_float32.shape
    centered_y_float32 = y_float32 - numpy.tile(
        map_mean, (nb_images, height_map, width_map, 1))
    centered_quantized_y_float32 = tls.quantize_per_map(
        centered_y_float32, bin_widths_test)
    cumulated_zeros = numpy.zeros((nb_maps, truncated_unary_length),
                                  dtype=numpy.int64)
    cumulated_ones = numpy.zeros((nb_maps, truncated_unary_length),
                                 dtype=numpy.int64)
    for i in range(nb_maps):
        (cumulated_zeros[i, :], cumulated_ones[i, :]) = \
            count_binary_decisions(numpy.absolute(centered_quantized_y_float32[:, :, :, i]),
                                   bin_widths_test[i].item(),
                                   truncated_unary_length)
    total = cumulated_zeros + cumulated_ones

    # For the ith absolute centered-quantized latent
    # variable feature map, if the jth binary decision
    # never occurs, `binary_probabilities[i, j]`
    # is equal to `numpy.nan`.
    with numpy.errstate(invalid='ignore'):
        binary_probabilities = cumulated_zeros.astype(
            numpy.float64) / total.astype(numpy.float64)

    # If a binary decision never occurs, the
    # probability this binary decision is 0
    # is set to 0.5.
    binary_probabilities[numpy.isnan(binary_probabilities)] = 0.5
    binary_probabilities[binary_probabilities == 0.] = 0.01
    binary_probabilities[binary_probabilities == 1.] = 0.99
    return binary_probabilities