def compress(self,
              original_path: str,
              compressed_path: str,
              original_file_info=None):
     array = isets.load_array_bsq(file_or_path=original_path,
                                  image_properties_row=original_file_info)
     array += self.param_dict["constant"]
     isets.dump_array_bsq(array=array, file_or_path=compressed_path)
Ejemplo n.º 2
0
    def test_array_load_dump(self):
        """Test that file properties are correctly obtained and retrieved.
        """
        width = 4
        height = 2
        component_count = 3

        for is_float in [True, False]:
            bytes_per_sample_values = [2, 4, 8] if is_float else [1, 2, 4, 8]
            for bytes_per_sample in bytes_per_sample_values:
                for signed in [True, False]:
                    value_factors = [1] if not signed else [1, -1]
                    for value_factor in value_factors:
                        big_endian_values = [True] if (bytes_per_sample == 1 or is_float) \
                            else [True, False]
                        for big_endian in big_endian_values:
                            row = dict(width=width,
                                       height=height,
                                       component_count=component_count,
                                       float=is_float,
                                       signed=signed,
                                       bytes_per_sample=bytes_per_sample,
                                       big_endian=big_endian)

                            array = np.zeros(
                                (width, height, component_count),
                                dtype=isets.iproperties_row_to_numpy_dtype(
                                    row))
                            i = 0
                            for z in range(component_count):
                                for y in range(height):
                                    for x in range(width):
                                        array[x, y, z] = i * value_factor
                                        i += 1

                            _, temp_file_path = tempfile.mkstemp(
                                suffix=
                                f"_{isets.iproperties_row_to_sample_type_tag(row)}.raw"
                            )
                            try:
                                dtype_string = isets.iproperties_row_to_numpy_dtype(
                                    row)
                                isets.dump_array_bsq(array,
                                                     temp_file_path,
                                                     mode="wb",
                                                     dtype=dtype_string)
                                loaded_array = isets.load_array_bsq(
                                    file_or_path=temp_file_path,
                                    image_properties_row=row)
                                assert (array == loaded_array).all(), (
                                    array, loaded_array)
                                assert os.path.getsize(temp_file_path) \
                                       == width * height * component_count * bytes_per_sample
                            finally:
                                try:
                                    os.remove(temp_file_path)
                                except OSError:
                                    pass
Ejemplo n.º 3
0
    def compress(self,
                 original_path: str,
                 compressed_path: str,
                 original_file_info=None):
        # Tested limit: self.max_tested_spatial_size
        if original_file_info["width"] <= self.max_dimension_size \
                and original_file_info["height"] <= self.max_dimension_size:
            return self.compress_one(original_path=original_path,
                                     compressed_path=compressed_path,
                                     original_file_info=original_file_info)
        else:
            tl_writer = tarlite.TarliteWriter()
            img = isets.load_array_bsq(file_or_path=original_path,
                                       image_properties_row=original_file_info)
            with tempfile.TemporaryDirectory(
                    dir=options.base_tmp_dir) as tmp_dir:
                compound_size = 0
                total_compression_time = 0
                for y in range(self.split_height_count):
                    for x in range(self.split_width_count):
                        small_array = \
                            img[x * (original_file_info["width"] // self.split_width_count):
                                (((x + 1) * (original_file_info[
                                                 "width"] // self.split_width_count)) if x < self.split_width_count - 1 else
                                 original_file_info["width"]),
                            y * (original_file_info["height"] // self.split_height_count):
                            (((y + 1) * (original_file_info[
                                             "height"] // self.split_height_count)) if y < self.split_height_count - 1 else
                             original_file_info["height"]),
                            :]
                        small_path = os.path.join(tmp_dir, f"{x}_{y}.raw")
                        small_compressed_path = os.path.join(
                            tmp_dir, f"{x}_{y}.mcalic")
                        isets.dump_array_bsq(small_array, small_path)
                        small_file_info = copy.copy(original_file_info)
                        small_file_info["width"], small_file_info[
                            "height"], small_file_info[
                                "component_count"] = small_array.shape
                        compression_results = self.compress_one(
                            original_path=small_path,
                            compressed_path=small_compressed_path,
                            original_file_info=small_file_info)
                        total_compression_time += compression_results.compression_time_seconds
                        tl_writer.add_file(small_compressed_path)
                        os.remove(small_path)
                        compound_size += small_array.size

                assert compound_size == original_file_info[
                    "samples"], f"compound_size = {compound_size} != {original_file_info['samples']} = original samples"
                tl_writer.write(output_path=compressed_path)

                compression_results = self.compression_results_from_paths(
                    original_path=original_path,
                    compressed_path=compressed_path)
                compression_results.compression_time_seconds = total_compression_time
                return compression_results
    def compress(self, original_path: str, compressed_path: str, original_file_info=None):
        assert original_file_info["bytes_per_sample"] in [1, 2], \
            f"Only 1 or 2 bytes per sample, unsigned values {original_file_info['bytes_per_sample']}"
        assert original_file_info["width"] <= self.max_dimension_size, \
            f"The input path has width {original_file_info['width']} exceeding the maximum {self.max_dimension_size}"
        assert original_file_info["height"] <= self.max_dimension_size, \
            f"The input path has height {original_file_info['height']} exceeding the maximum {self.max_dimension_size}"
        complete_array = isets.load_array_bsq(file_or_path=original_path, image_properties_row=original_file_info)
        if original_file_info["signed"]:
            complete_array = complete_array.astype(np.int64)
            complete_array += 2 ** ((8 * original_file_info['bytes_per_sample']) - 1)
            assert (complete_array >= 0).all(), f"Error converting signed into unsigned"

        bands_per_image = min(original_file_info["component_count"],
                              self.max_dimension_size // original_file_info["height"])

        tw = tarlite.TarliteWriter()

        total_compression_time = 0

        with tempfile.TemporaryDirectory(dir=options.base_tmp_dir) as tmp_dir:
            stacked_size = 0
            for stack_index, start_band_index in enumerate(
                    range(0, original_file_info["component_count"], bands_per_image)):
                end_band_index_not_included = min(original_file_info["component_count"],
                                                  start_band_index + bands_per_image)
                stacked_array = np.hstack(tuple(complete_array[:, :, z].squeeze()
                                                for z in range(start_band_index, end_band_index_not_included)))
                stacked_size += stacked_array.shape[0] * stacked_array.shape[1]

                with tempfile.NamedTemporaryFile(dir=options.base_tmp_dir,
                                                 suffix=".pgm") as tmp_stack_file:
                    pgm.write_pgm(array=stacked_array,
                                  bytes_per_sample=original_file_info["bytes_per_sample"],
                                  output_path=tmp_stack_file.name)
                    stack_compressed_path = os.path.join(tmp_dir, str(stack_index))
                    compression_results = super().compress(
                        original_path=tmp_stack_file.name,
                        compressed_path=stack_compressed_path,
                        original_file_info=original_file_info)
                    total_compression_time += compression_results.compression_time_seconds

                    tw.add_file(input_path=stack_compressed_path)
            assert stacked_size == complete_array.shape[0] * complete_array.shape[1] * complete_array.shape[2], \
                f"Total stacked size {stacked_size} does not match the expectations. " \
                f"({stacked_size} vs {complete_array.shape[0] * complete_array.shape[1] * complete_array.shape[2]}"

            tw.write(output_path=compressed_path)

            compression_results = self.compression_results_from_paths(
                original_path=original_path, compressed_path=compressed_path)
            compression_results.compression_time_seconds = total_compression_time

            return compression_results
    def get_spectral_angles_deg(self, index, row):
        """Return a sequence of spectral angles (in degrees), 
        one per (x,y) position in the image, flattened in raster order.
        """
        # Read original and reconstructed images
        original_file_path, task_name = index
        image_properties_row = self.get_dataset_info_row(original_file_path)
        decompression_results = row.decompression_results
        original_array = isets.load_array_bsq(
            file_or_path=original_file_path, image_properties_row=image_properties_row)
        reconstructed_array = isets.load_array_bsq(
            file_or_path=decompression_results.reconstructed_path, image_properties_row=image_properties_row)

        # Reshape flattening the x,y axes, and maintaining the z axis for each (x,y) position
        original_array = np.reshape(
            original_array.swapaxes(0, 1),
            (image_properties_row["width"] * image_properties_row["height"], image_properties_row["component_count"]),
            "F").astype("i8")
        reconstructed_array = np.reshape(
            reconstructed_array.swapaxes(0, 1),
            (image_properties_row["width"] * image_properties_row["height"], image_properties_row["component_count"]),
            "F").astype("i8")

        dots = np.einsum("ij,ij->i", original_array, reconstructed_array)
        magnitude_a = np.linalg.norm(original_array, axis=1)
        magnitude_b = np.linalg.norm(reconstructed_array, axis=1)

        for i in range(magnitude_a.shape[0]):
            # Avoid division by zero
            magnitude_a[i] = max(1e-4, magnitude_a[i])
            magnitude_b[i] = max(1e-4, magnitude_b[i])

        # Clip, because the dot product can slip past 1 or -1 due to rounding
        cosines = np.clip(dots / (magnitude_a * magnitude_b), -1, 1)
        angles = np.degrees(np.arccos(cosines))
        # Round because two identical images should return an angle of exactly 0
        angles = np.round(angles, 5)

        return angles.tolist()
Ejemplo n.º 6
0
    def decompress(self,
                   compressed_path,
                   reconstructed_path,
                   original_file_info=None):
        if original_file_info[
                "width"] <= self.max_dimension_size and original_file_info[
                    "height"] <= self.max_dimension_size:
            return self.decompress_one(compressed_path=compressed_path,
                                       reconstructed_path=reconstructed_path,
                                       original_file_info=original_file_info)
        else:
            tl_reader = tarlite.TarliteReader(tarlite_path=compressed_path)
            img = np.zeros(
                (original_file_info["width"], original_file_info["height"],
                 original_file_info["component_count"]),
                dtype=isets.iproperties_row_to_numpy_dtype(
                    image_properties_row=original_file_info))
            total_decompression_time = 0
            with tempfile.TemporaryDirectory(
                    dir=options.base_tmp_dir) as tmp_dir:
                tl_reader.extract_all(output_dir_path=tmp_dir)
                invocation = f"ls -lah {tmp_dir}"
                status, output = subprocess.getstatusoutput(invocation)
                if status != 0:
                    raise Exception(
                        "Status = {} != 0.\nInput=[{}].\nOutput=[{}]".format(
                            status, invocation, output))

                for y in range(self.split_height_count):
                    for x in range(self.split_width_count):
                        small_compressed_path = os.path.join(
                            tmp_dir, f"{x}_{y}.mcalic")
                        assert os.path.exists(small_compressed_path)
                        small_path = os.path.join(tmp_dir, f"{x}_{y}.raw")
                        small_file_info = copy.copy(original_file_info)

                        small_file_info["height"] = original_file_info["height"] // self.split_height_count \
                            if y < self.split_height_count - 1 \
                            else original_file_info["height"] - (self.split_height_count - 1) * (
                                original_file_info["height"] // self.split_height_count)

                        small_file_info["width"] = original_file_info["width"] // self.split_width_count \
                            if x < self.split_width_count - 1 \
                            else original_file_info["width"] - (self.split_width_count - 1) * (
                                original_file_info["width"] // self.split_width_count)

                        dr = self.decompress_one(
                            compressed_path=small_compressed_path,
                            reconstructed_path=small_path,
                            original_file_info=small_file_info)
                        total_decompression_time += dr.decompression_time_seconds
                        small_array = isets.load_array_bsq(
                            file_or_path=small_path,
                            image_properties_row=small_file_info)
                        img[x * (original_file_info["width"] //
                                 self.split_width_count):(
                                     ((x + 1) * (original_file_info["width"] //
                                                 self.split_width_count)
                                      ) if x < self.split_width_count -
                                     1 else original_file_info["width"]), y *
                            (original_file_info["height"] //
                             self.split_height_count):(
                                 ((y + 1) * (original_file_info["height"] //
                                             self.split_height_count)
                                  ) if y < self.split_height_count -
                                 1 else original_file_info["height"]
                             ), :] = small_array
                isets.dump_array_bsq(array=img,
                                     file_or_path=reconstructed_path)

            decompression_results = self.decompression_results_from_paths(
                compressed_path=compressed_path,
                reconstructed_path=reconstructed_path)
            decompression_results.decompression_time_seconds = total_decompression_time
            return decompression_results
    def process_row(self, index, column_fun_tuples, row, overwrite, fill):
        file_path, codec_name = index
        codec = self.codecs_by_name[codec_name]
        image_info_row = self.dataset_table_df.loc[indices_to_internal_loc(file_path)]
        row_wrapper = self.RowWrapper(
            file_path=file_path, codec=codec,
            image_info_row=image_info_row,
            row=row)
        result = super().process_row(index=index, column_fun_tuples=column_fun_tuples,
                                     row=row_wrapper, overwrite=overwrite, fill=fill)

        if isinstance(result, Exception):
            return result

        if self.compressed_copy_dir_path:
            output_compressed_path = os.path.join(
                self.compressed_copy_dir_path,
                codec.name,
                os.path.basename(os.path.dirname(file_path)), os.path.basename(file_path))
            os.makedirs(os.path.dirname(output_compressed_path), exist_ok=True)
            if options.verbose > 1:
                print(f"[C]opying {file_path} into {output_compressed_path}")
            shutil.copy(row_wrapper.compression_results.compressed_path, output_compressed_path)

        if self.reconstructed_dir_path is not None:
            output_reconstructed_path = os.path.join(
                self.reconstructed_dir_path,
                codec.name,
                os.path.basename(os.path.dirname(file_path)), os.path.basename(file_path))
            os.makedirs(os.path.dirname(output_reconstructed_path), exist_ok=True)
            if options.verbose > 1:
                print(f"[C]opying {row_wrapper.compression_results.compressed_path} into {output_reconstructed_path}")
            shutil.copy(row_wrapper.decompression_results.reconstructed_path,
                        output_reconstructed_path)

            if image_info_row["component_count"] == 3:
                rendered_path = f"{output_reconstructed_path}.png"
                if not os.path.exists(rendered_path) or options.force:
                    array = isets.load_array_bsq(file_or_path=row_wrapper.decompression_results.reconstructed_path,
                                                 image_properties_row=image_info_row).astype(np.int)
                    if options.reconstructed_size is not None:
                        width, height, _ = array.shape
                        array = array[
                                width // 2 - options.reconstructed_size // 2:width // 2 + options.reconstructed_size // 2,
                                height // 2 - options.reconstructed_size // 2:height // 2 + options.reconstructed_size // 2,
                                :]
                    cmin = array.min()
                    cmax = array.max()
                    array = np.round((255 * (array.astype(np.int) - cmin) / (cmax - cmin))).astype("uint8")
                    if options.verbose > 1:
                        print(f"[R]endering {rendered_path}")

                    numpngw.imwrite(rendered_path, array.swapaxes(0, 1))

            else:
                full_array = isets.load_array_bsq(
                    file_or_path=row_wrapper.decompression_results.reconstructed_path,
                    image_properties_row=image_info_row).astype(np.int)
                if options.reconstructed_size is not None:
                    width, height, _ = full_array.shape
                    full_array = full_array[
                                 width // 2 - options.reconstructed_size // 2:width // 2 + options.reconstructed_size // 2,
                                 height // 2 - options.reconstructed_size // 2:height // 2 + options.reconstructed_size // 2,
                                 :]
                for i, rendered_path in enumerate(f"{output_reconstructed_path}_component{i}.png"
                                                  for i in range(image_info_row['component_count'])):
                    if not os.path.exists(rendered_path) or options.force:
                        array = full_array[:, :, i].squeeze().swapaxes(0, 1)
                        cmin = array.min()
                        cmax = array.max()
                        array = np.round((255 * (array - cmin) / (cmax - cmin))).astype("uint8")
                        if options.verbose > 1:
                            print(f"[R]endering {rendered_path}")
                        numpngw.imwrite(rendered_path, array)

        return row