Bases: BaseCodec
This steganography method is named: "ColorWatermarking"
In ColorWatermarking, carrier-->3 channels color image * 1,
payload-->3 channels color image * 1,
the watermark is universal for carrier(color) image.
- Created by: Ruinan Ma
- Created time: 2022/11/4
This is a pytorch implementation of image steganography via deep learning,
which is released in paper - UDH: Universal Deep Hiding for Steganography,
Watermarking, and Light Field Messaging
https://papers.nips.cc/paper/2020/file/73d02e4344f71a0b0d51a925246990e7-Paper.pdf
Source code in stegobox/codec/udh_nips2020/color_watermarking.py
| class ColorWatermarking(BaseCodec):
"""
This steganography method is named: "ColorWatermarking"
In ColorWatermarking, carrier-->3 channels color image * 1,
payload-->3 channels color image * 1,
the watermark is universal for carrier(color) image.
* Created by: Ruinan Ma
* Created time: 2022/11/4
This is a pytorch implementation of image steganography via deep learning,
which is released in paper - UDH: Universal Deep Hiding for Steganography,
Watermarking, and Light Field Messaging
https://papers.nips.cc/paper/2020/file/73d02e4344f71a0b0d51a925246990e7-Paper.pdf
"""
def __init__(self, verbose: bool = False, norm: str = "batch") -> None:
super().__init__()
self.verbose = verbose
self.norm = norm
self.num_downs = 5
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
self.imagesize = 128
self.checkpoint = "ckpt/udh_nips2020/color_watermarking.pth.tar"
# preprocessing for color_image
self.transform_color = transforms.Compose(
[transforms.Resize([self.imagesize, self.imagesize]), transforms.ToTensor()]
)
# select the type of norm operation
if self.norm == "instance":
self.norm_layer = nn.InstanceNorm2d
elif self.norm == "batch":
self.norm_layer = nn.BatchNorm2d # type: ignore
else:
self.norm_layer = None # type: ignore
self.Hnet, self.Rnet = self.net_init()
if verbose:
if torch.cuda.is_available():
print("Running color universal watermaking with GPU.")
else:
print("Running color universal watermaking with CPU.")
def weights_init(self, m):
classname = m.__class__.__name__
if classname.find("Conv") != -1:
nn.init.kaiming_normal_(m.weight.data, a=0, mode="fan_out")
elif classname.find("BatchNorm") != -1:
m.weight.data.fill_(1.0)
m.bias.data.fill_(0)
def net_init(self):
# input_nc = channel_secret * num_secret
# output_nc = channel_cover * num_cover
hnet = UnetGenerator(
input_nc=3 * 1,
output_nc=3 * 1,
num_downs=self.num_downs,
norm_layer=self.norm_layer,
output_function=nn.Tanh, # type: ignore
)
# input_nc = channel_cover * num_cover
# output_nc = channel_secret * num_secret
rnet = RevealNet(
input_nc=3 * 1,
output_nc=3 * 1,
nhf=64,
norm_layer=self.norm_layer,
output_function=nn.Sigmoid,
)
# Using kaiming normalization to initialize model.
hnet.apply(self.weights_init)
rnet.apply(self.weights_init)
hnet = torch.nn.parallel.DataParallel(hnet).cuda()
rnet = torch.nn.parallel.DataParallel(rnet).cuda()
checkpoint = torch.load(self.checkpoint)
hnet.load_state_dict(checkpoint["H_state_dict"])
rnet.load_state_dict(checkpoint["R_state_dict"])
return hnet, rnet
def encode(self, carrier: Image.Image, payload: Image.Image) -> torch.Tensor:
"""Encode a color image with format png into a color image with format png.
Args:
carrier: cover image
payload: Payload secret color image.
Returns:
Encoded steganographic image with format torch.tensor
"""
payload = self.transform_color(payload)
carrier = self.transform_color(carrier)
payload = payload.unsqueeze(dim=0) # type: ignore
carrier = carrier.unsqueeze(dim=0) # type: ignore
payload = payload.to(self.device) # type: ignore
carrier = carrier.to(self.device) # type: ignore
# secret_p(universal watermarking)-->torch.Size([1, 3, 128, 128])
secret_p = self.Hnet(payload)
# you can save secret_p(universal watermarking)
# torchvision.utils.save_image(secret_p, "./result-pic/secret_p.png")
container = carrier + secret_p
return container
def decode(self, container: Image.Image) -> torch.Tensor:
"""Decode secret image from encoded steganographic image.
Args:
container: Encoded carrier(color) image.
Returns:
One decoded color image if decode is successful.
"""
container = self.transform_color(container)
container = container.unsqueeze(dim=0) # type: ignore
container = container.to(self.device) # type: ignore
reveal_payload = self.Rnet(container)
return reveal_payload
|
encode(carrier, payload)
Encode a color image with format png into a color image with format png.
Parameters:
Name |
Type |
Description |
Default |
carrier |
Image
|
|
required
|
payload |
Image
|
Payload secret color image.
|
required
|
Returns:
Type |
Description |
Tensor
|
Encoded steganographic image with format torch.tensor
|
Source code in stegobox/codec/udh_nips2020/color_watermarking.py
| def encode(self, carrier: Image.Image, payload: Image.Image) -> torch.Tensor:
"""Encode a color image with format png into a color image with format png.
Args:
carrier: cover image
payload: Payload secret color image.
Returns:
Encoded steganographic image with format torch.tensor
"""
payload = self.transform_color(payload)
carrier = self.transform_color(carrier)
payload = payload.unsqueeze(dim=0) # type: ignore
carrier = carrier.unsqueeze(dim=0) # type: ignore
payload = payload.to(self.device) # type: ignore
carrier = carrier.to(self.device) # type: ignore
# secret_p(universal watermarking)-->torch.Size([1, 3, 128, 128])
secret_p = self.Hnet(payload)
# you can save secret_p(universal watermarking)
# torchvision.utils.save_image(secret_p, "./result-pic/secret_p.png")
container = carrier + secret_p
return container
|
decode(container)
Decode secret image from encoded steganographic image.
Parameters:
Name |
Type |
Description |
Default |
container |
Image
|
Encoded carrier(color) image.
|
required
|
Returns:
Type |
Description |
Tensor
|
One decoded color image if decode is successful.
|
Source code in stegobox/codec/udh_nips2020/color_watermarking.py
| def decode(self, container: Image.Image) -> torch.Tensor:
"""Decode secret image from encoded steganographic image.
Args:
container: Encoded carrier(color) image.
Returns:
One decoded color image if decode is successful.
"""
container = self.transform_color(container)
container = container.unsqueeze(dim=0) # type: ignore
container = container.to(self.device) # type: ignore
reveal_payload = self.Rnet(container)
return reveal_payload
|