Example #1
0
 def pad_undo(self, x, mode='reflect'):
     raw, undo_pad = pad(x, self.padding_fac, mode=mode)
     return raw, undo_pad
Example #2
0
 def pad(self, x):
     raw, _ = pad(x, self.padding_fac, mode='constant')
     return raw
 def pad(raw, fac):
     raw, _ = pad(raw, fac, mode=MultiscaleBlueprint.get_padding_mode())
     return raw
Example #4
0
    def encode(self, img, pout):
        """
        Encode image to disk at path `p`.
        :param img: uint8 tensor of shape CHW or 1CHW
        :param pout: path
        :return actual_bpsp
        """
        assert not os.path.isfile(pout)
        if len(img.shape) == 3:
            img = img.unsqueeze(0)  # 1CHW
        assert len(
            img.shape
        ) == 4 and img.shape[0] == 1 and img.shape[1] == 3, img.shape
        assert img.dtype == torch.int64, img.dtype

        if auto_crop.needs_crop(img):
            print('Need to encode individual crops!')

            c = auto_crop.CropLossCombinator()
            for i, img_crop in enumerate(auto_crop.iter_crops(img)):
                bpsp_crop = self.encode(
                    img_crop, pout + part_suffix_helper.make_part_suffix(i))
                c.add(bpsp_crop, np.prod(img_crop.shape[-2:]))
            return c.get_bpsp()

        # TODO: Note that recursive is not supported.
        padding = 2**self.blueprint.net.config_ms.num_scales
        _, _, H, W = img.shape
        if H % padding != 0 or W % padding != 0:
            print(
                f'*** INFO: image shape ({H}X{W}) not divisible by {padding}, will pad.'
            )
            img, padding_tuple = pad.pad(
                img, fac=padding, mode=MultiscaleBlueprint.get_padding_mode())
        else:
            padding_tuple = (0, 0, 0, 0)

        img = img.float()

        with self.times.run('[-] encode forwardpass'):
            out = self.blueprint.net(img)

        if self.compare_with_theory:
            with self.times.run('[-] get loss'):
                loss_out = self.blueprint.get_loss(out)

        self.blueprint.net.zero_grad()

        entropy_coding_bytes = []  # bytes used by different scales

        with open(pout, 'wb') as fout:
            write_padding_tuple(padding_tuple, fout)
            for scale, dmll, uniform in self.iter_scale_dmll():
                with self.times.prefix_scope(f'[{scale}]'):
                    if uniform:
                        entropy_coding_bytes.append(
                            self.encode_uniform(dmll, out.S[scale], fout))
                    else:
                        entropy_coding_bytes.append(
                            self.encode_scale(scale, dmll, out, img, fout))
                    fout.write(_MAGIC_VALUE_SEP)

        num_subpixels = np.prod(img.shape)
        actual_num_bytes = os.path.getsize(pout)
        actual_bpsp = actual_num_bytes * 8 / num_subpixels

        if self.compare_with_theory:
            assumed_bpsps = [
                b * 8 / num_subpixels for b in entropy_coding_bytes
            ]
            tostr = lambda l: ' | '.join(map('{:.3f}'.format, l)
                                         ) + f' => {sum(l):.3f}'
            overhead = (sum(assumed_bpsps) / sum(loss_out.nonrecursive_bpsps) -
                        1) * 100
            info = f'Bitrates:\n' \
                f'theory:  {tostr(loss_out.nonrecursive_bpsps)}\n' \
                f'assumed: {tostr(list(reversed(assumed_bpsps)))} [{overhead:.2f}%]\n' \
                f'actual:                                => {actual_bpsp:.3f} [{actual_num_bytes} bytes]'
            print(info)
            return actual_bpsp
        else:
            return actual_bpsp
Example #5
0
 def pad(raw, fac):
     raw, _ = pad(raw, fac, mode='constant')
     return raw