Skip to content

HiNetPNGinPNGIccv2021

stegobox.codec.HiNetPNGinPNGIccv2021

Bases: BaseCodec

This steganography method is named: HiNetPNGinPNGIccv2021

  • Created by: Ruinan Ma
  • Created time: 2022/10/10

This is a PyTorch implementation of image steganography via deep learning, which is released in paper - HiNet: Deep Image Hiding by Invertible Network https://openaccess.thecvf.com/content/ICCV2021/html/Jing_HiNet_Deep_Image_Hiding_by_Invertible_Network_ICCV_2021_paper.html

Source code in stegobox/codec/hinet_pnginpng_iccv2021/hinet_pnginpng.py
class HiNetPNGinPNGIccv2021(BaseCodec):
    """
    This steganography method is named: `HiNetPNGinPNGIccv2021`

    * Created by: Ruinan Ma
    * Created time: 2022/10/10

    This is a PyTorch implementation of image steganography via deep learning, which is
    released in paper - HiNet: Deep Image Hiding by Invertible Network
    https://openaccess.thecvf.com/content/ICCV2021/html/Jing_HiNet_Deep_Image_Hiding_by_Invertible_Network_ICCV_2021_paper.html
    """

    def __init__(
        self,
        para_pth: str = "ckpt/hinet_pnginpng_iccv2021/model.pt",
        verbose: bool = False,
    ) -> None:
        super().__init__()
        self.verbose = verbose
        self.para_pth = para_pth
        self.transform = transforms.Compose(
            [transforms.CenterCrop(c.CROPSIZE_VAL), transforms.ToTensor()]
        )
        self.dwt = common.DWT()
        self.iwt = common.IWT()
        self.HiNet = self.net_init()
        if verbose:
            if torch.cuda.is_available():
                print("Running HiNet_Iccv2021 with GPU.")
            else:
                print("Running HiNet_Iccv2021 with CPU.")

    def net_init(self):
        net = Model()
        net.cuda()
        init_model(net)
        net = torch.nn.DataParallel(net, device_ids=c.DEVICE_IDS)  # type: ignore
        params_trainable = list(filter(lambda p: p.requires_grad, net.parameters()))
        optim = torch.optim.Adam(
            params_trainable,
            lr=c.LR,
            betas=c.BETAS,
            eps=1e-6,
            weight_decay=c.WEIGHT_DECAY,
        )
        # weight_scheduler = torch.optim.lr_scheduler.StepLR(
        #     optim, c.weight_step, gamma=c.gamma
        # )
        load(self.para_pth, net, optim)
        net.eval()
        if self.verbose:
            print("HiNet loads pre_trained model successfully.")
        return net

    def encode(self, carrier: Image.Image, payload: Image.Image) -> torch.Tensor:
        """Encode image with format png into image with format png.

        Args:
            carrier: cover image
            payload: Payload secret image

        Returns:
            Encoded steganographic image with format torch.tensor
        """

        if self.verbose:
            print("Encoding...")
        carrier = self.transform(carrier)
        payload = self.transform(payload)

        # carrier.size()=payload.size()-->torch.Size([1, 3, 256, 256])
        carrier = carrier.unsqueeze(dim=0)  # type: ignore
        payload = payload.unsqueeze(dim=0)  # type: ignore

        # carrier_input.size()=payload_input.size()
        # -->torch.Size([1, 12, 128, 128])
        carrier_input = self.dwt(carrier)
        payload_input = self.dwt(payload)

        # input_img.size()-->torch.Size([1, 24, 128, 128])
        input_img = torch.cat([carrier_input, payload_input], dim=1)

        if torch.cuda.is_available():
            input_img = input_img.cuda()

        # output.size()-->torch.Size([1, 24, 128, 128])
        output = self.HiNet(input_img)

        # output_steg.size()-->torch.Size([1, 12, 128, 128])
        output_steg = output.narrow(1, 0, 4 * c.CHANNELS_IN)

        # output_z.size()-->torch.Size([1, 12, 128, 128])
        # output_z = output.narrow(
        #     1, 4 * c.channels_in, output.shape[1] - 4 * c.channels_in
        # )

        container = self.iwt(output_steg)
        # backward_z = gauss_noise(output_z.shape)
        return container

    def decode(self, carrier: Image.Image) -> torch.Tensor:
        """Decode secret image from encoded steganographic image.

        Args:
            carrier: Encoded carrier image.

        Returns:
            The decoded image if decode is successful.
        """

        if self.verbose:
            print("Decoding...")
        carrier = self.transform(carrier)
        carrier = carrier.unsqueeze(dim=0)  # type: ignore

        if torch.cuda.is_available():
            carrier = carrier.cuda()  # type: ignore

        carrier = self.dwt(carrier)
        backward_z = gauss_noise(carrier.shape)  # type: ignore
        output_rev = torch.cat([carrier, backward_z], dim=1)  # type: ignore
        bacward_img = self.HiNet(output_rev, rev=True)
        secret_rev = bacward_img.narrow(
            1, 4 * c.CHANNELS_IN, bacward_img.shape[1] - 4 * c.CHANNELS_IN
        )
        reveal_img = self.iwt(secret_rev)
        return reveal_img

encode(carrier, payload)

Encode image with format png into image with format png.

Parameters:

Name Type Description Default
carrier Image

cover image

required
payload Image

Payload secret image

required

Returns:

Type Description
Tensor

Encoded steganographic image with format torch.tensor

Source code in stegobox/codec/hinet_pnginpng_iccv2021/hinet_pnginpng.py
def encode(self, carrier: Image.Image, payload: Image.Image) -> torch.Tensor:
    """Encode image with format png into image with format png.

    Args:
        carrier: cover image
        payload: Payload secret image

    Returns:
        Encoded steganographic image with format torch.tensor
    """

    if self.verbose:
        print("Encoding...")
    carrier = self.transform(carrier)
    payload = self.transform(payload)

    # carrier.size()=payload.size()-->torch.Size([1, 3, 256, 256])
    carrier = carrier.unsqueeze(dim=0)  # type: ignore
    payload = payload.unsqueeze(dim=0)  # type: ignore

    # carrier_input.size()=payload_input.size()
    # -->torch.Size([1, 12, 128, 128])
    carrier_input = self.dwt(carrier)
    payload_input = self.dwt(payload)

    # input_img.size()-->torch.Size([1, 24, 128, 128])
    input_img = torch.cat([carrier_input, payload_input], dim=1)

    if torch.cuda.is_available():
        input_img = input_img.cuda()

    # output.size()-->torch.Size([1, 24, 128, 128])
    output = self.HiNet(input_img)

    # output_steg.size()-->torch.Size([1, 12, 128, 128])
    output_steg = output.narrow(1, 0, 4 * c.CHANNELS_IN)

    # output_z.size()-->torch.Size([1, 12, 128, 128])
    # output_z = output.narrow(
    #     1, 4 * c.channels_in, output.shape[1] - 4 * c.channels_in
    # )

    container = self.iwt(output_steg)
    # backward_z = gauss_noise(output_z.shape)
    return container

decode(carrier)

Decode secret image from encoded steganographic image.

Parameters:

Name Type Description Default
carrier Image

Encoded carrier image.

required

Returns:

Type Description
Tensor

The decoded image if decode is successful.

Source code in stegobox/codec/hinet_pnginpng_iccv2021/hinet_pnginpng.py
def decode(self, carrier: Image.Image) -> torch.Tensor:
    """Decode secret image from encoded steganographic image.

    Args:
        carrier: Encoded carrier image.

    Returns:
        The decoded image if decode is successful.
    """

    if self.verbose:
        print("Decoding...")
    carrier = self.transform(carrier)
    carrier = carrier.unsqueeze(dim=0)  # type: ignore

    if torch.cuda.is_available():
        carrier = carrier.cuda()  # type: ignore

    carrier = self.dwt(carrier)
    backward_z = gauss_noise(carrier.shape)  # type: ignore
    output_rev = torch.cat([carrier, backward_z], dim=1)  # type: ignore
    bacward_img = self.HiNet(output_rev, rev=True)
    secret_rev = bacward_img.narrow(
        1, 4 * c.CHANNELS_IN, bacward_img.shape[1] - 4 * c.CHANNELS_IN
    )
    reveal_img = self.iwt(secret_rev)
    return reveal_img