Skip to content

Feedback #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 39 commits into
base: feedback
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
24787d7
Setting up GitHub Classroom Feedback
github-classroom[bot] Feb 5, 2021
86e8433
Update GitHub Classroom Feedback
github-classroom[bot] Feb 5, 2021
8fdd090
Setting up GitHub Classroom Feedback
github-classroom[bot] Feb 5, 2021
99ea578
Create README.md
adityagupta-9900 Feb 5, 2021
ff88c77
Update README.md
adityagupta-9900 Feb 15, 2021
c9cd4d0
Add Project proposal
ab1nash Feb 15, 2021
5af4089
Add files via upload
adityagupta-9900 Mar 9, 2021
47c78ad
Add files via upload
adityagupta-9900 Mar 9, 2021
27772f9
Files added from colab
MohsinMamoon Mar 26, 2021
a60d229
Mid-evaluation Presentation
adityagupta-9900 Mar 26, 2021
ce84539
Some changes in model
MohsinMamoon Apr 12, 2021
ff275b3
Merge branch 'main' of https://github.com/Computer-Vision-IIITH-2021/…
MohsinMamoon Apr 12, 2021
a884b4e
ppt
kqwert11 Apr 21, 2021
c7623bb
Create directory structure
ab1nash Apr 22, 2021
5fc838b
some changes
kqwert11 Apr 22, 2021
d8305a2
Add files via upload
kqwert11 Apr 24, 2021
688f828
Add utility functions
ab1nash Apr 24, 2021
54cb014
Remove unnecessary folders
ab1nash Apr 24, 2021
b530e60
Added Training code
MohsinMamoon Apr 24, 2021
df858a6
updated
kqwert11 Apr 24, 2021
efe162f
Add neural net class
ab1nash Apr 24, 2021
856e31f
Delete Final PPT.pdf
adityagupta-9900 Apr 24, 2021
d39cf12
Second last update of report
adityagupta-9900 Apr 24, 2021
038abcf
update endeco
kqwert11 Apr 24, 2021
47572bb
Update README.md
adityagupta-9900 Apr 24, 2021
f7c4d2e
Update README.md
adityagupta-9900 Apr 24, 2021
9dae285
Add files via upload
adityagupta-9900 Apr 24, 2021
ff2e439
Update README.md
adityagupta-9900 Apr 24, 2021
112e3af
Merge branch 'main' of https://github.com/Computer-Vision-IIITH-2021/…
MohsinMamoon Apr 24, 2021
b28432e
Added code for experiments
MohsinMamoon Apr 24, 2021
5d3a372
Update README.md
adityagupta-9900 Apr 24, 2021
2b1ac7c
Added code for argument parsing
MohsinMamoon Apr 24, 2021
5375d66
Added code for DatasetHandling
MohsinMamoon Apr 24, 2021
ba6d1a4
Merge branch 'main' of https://github.com/Computer-Vision-IIITH-2021/…
MohsinMamoon Apr 24, 2021
6fa2442
README modified
MohsinMamoon Apr 24, 2021
fd73673
Delete Final PPT.pdf
adityagupta-9900 Apr 24, 2021
1da05e5
Final update of Final report
adityagupta-9900 Apr 24, 2021
73f99ed
Fixed links
MohsinMamoon Apr 24, 2021
68f7003
Merge branch 'main' of https://github.com/Computer-Vision-IIITH-2021/…
MohsinMamoon Apr 24, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# .gitignore

src/.ipynb_checkpoints/
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Arbitrary Style Transfer
Arbitrary-Style-Per-Model Fast Neural Style Transfer Method

## Description
A Pytorch implementation of the 2017 Huang et. al. paper "Arbitrary Style Transfer in Real-time with Adaptive Instance Normalization" https://arxiv.org/abs/1703.06868

This Encoder-AdaIN-Decoder architecture - Deep Convolutional Neural Network as a Style Transfer Network (STN) which can receive two arbitrary images as inputs (one as content, the other one as style) and output a generated image that recombines the content and spatial structure from the former and the style (color, texture) from the latter without re-training the network.

![Architecture](images/tmp/Architecture.png)


## How to run
- Download the Vgg model from [here](https://drive.google.com/file/d/1yOy1mWOa3dY-lpj8IZUIDayUnBuHKNx0/view?usp=sharing) and place it into the models folder.
- Download the pretrained model from [here](https://drive.google.com/file/d/18AtLdqyAjLD54RRIfwhcq9g80CYzrWqA/view?usp=sharing) and place it into the models folder.
- Detailed help about running can be found by `python3 main.py -h`
![Instruction](images/tmp/Instruction.png)

- For training, the dataset folder structure has to be: content/1/\*.jpg and style/1/\*.jpg
Binary file added images/content/brad_pitt.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/content/chicago.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/content/karya.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/content/lance.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/content/stata.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/style/cat.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/style/escher_sphere.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/style/lion.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/style/mosaic.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/style/udnie.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/style/woman_matisse.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/temp/in_1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/temp/in_2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/temp/in_3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/temp/in_4.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/temp/in_5.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/temp/out1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/temp/out2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/temp/out3.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/temp/out4.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/temp/out5.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/tmp/Architecture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/tmp/Instruction.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added models/enc_dec_model
Binary file not shown.
Binary file added reports/Final_report.pdf
Binary file not shown.
Binary file added reports/Mid-eval_presentation.pdf
Binary file not shown.
Binary file added reports/Project_Proposal.pdf
Binary file not shown.
Empty file added results/.gitkeep
Empty file.
23 changes: 23 additions & 0 deletions src/EncoderDecoder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import torch
import torch.nn as nn

class EncoderDecoder(nn.Module):
def __init__(self, encoder, decoder):
super().__init__()

self.encoder = encoder
self.decoder = decoder
self.style_features = []
self.style_layers = [1, 6, 11, 20] # relu1_1, relu2_1, relu3_1, relu4_1
for i in self.style_layers:
self.encoder._modules[str(i)].register_forward_hook(self.style_feature_hook)

def style_feature_hook(self, module, input, output):
self.style_features.append(output)

def forward(self, image):

self.content_in = self.encoder(image)
self.style_features = []

return self.decoder(self.content_in)
173 changes: 173 additions & 0 deletions src/StyleTransfer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
import torch
import numpy as np
import torch.nn as nn

class ContentStyleLoss(nn.Module):
def __init__(self, lam=7.5):
super().__init__()
self.lam = lam

def forward (self, content_in, content_out, styles_in, styles_out):
contentLoss = torch.norm(content_out - content_in)
styleLoss = np.sum([
torch.linalg.norm(torch.mean(styles_out[i], (2, 3)) - torch.mean(styles_in[i], (2,3))) +
torch.linalg.norm(torch.std(styles_out[i], axis=(2, 3), unbiased=False) - torch.std(styles_in[i], axis=(2, 3),
unbiased=False)) for i in range(len(styles_in))
])

return contentLoss + self.lam*styleLoss

class StyleTransfer(nn.Module):
def __init__(self, device="cpu"):

super().__init__()

self.encoder = nn.Sequential(
nn.Conv2d(3, 3, (1, 1)),
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(3, 64, (3, 3)),
nn.ReLU(), # relu1-1
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(64, 64, (3, 3)),
nn.ReLU(), # relu1-2
nn.MaxPool2d((2, 2), (2, 2), (0, 0), ceil_mode=True),
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(64, 128, (3, 3)),
nn.ReLU(), # relu2-1
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(128, 128, (3, 3)),
nn.ReLU(), # relu2-2
nn.MaxPool2d((2, 2), (2, 2), (0, 0), ceil_mode=True),
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(128, 256, (3, 3)),
nn.ReLU(), # relu3-1
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(256, 256, (3, 3)),
nn.ReLU(), # relu3-2
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(256, 256, (3, 3)),
nn.ReLU(), # relu3-3
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(256, 256, (3, 3)),
nn.ReLU(), # relu3-4
nn.MaxPool2d((2, 2), (2, 2), (0, 0), ceil_mode=True),
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(256, 512, (3, 3)),
nn.ReLU(), # relu4-1
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(512, 512, (3, 3)),
nn.ReLU(), # relu4-2
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(512, 512, (3, 3)),
nn.ReLU(), # relu4-3
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(512, 512, (3, 3)),
nn.ReLU(), # relu4-4
nn.MaxPool2d((2, 2), (2, 2), (0, 0), ceil_mode=True),
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(512, 512, (3, 3)),
nn.ReLU(), # relu5-1
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(512, 512, (3, 3)),
nn.ReLU(), # relu5-2
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(512, 512, (3, 3)),
nn.ReLU(), # relu5-3
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(512, 512, (3, 3)),
nn.ReLU() # relu5-4
)
self.encoder.load_state_dict(torch.load('../models/vgg_weights'))
self.encoder = nn.Sequential(*list(self.encoder.children())[:31])

for i in self.encoder.parameters():
i.requires_grad = False

self.encoder = self.encoder.to(device)

self.decoder = nn.Sequential(
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(512, 256, (3, 3)),
nn.ReLU(),
nn.Upsample(scale_factor=2, mode='nearest'),
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(256, 256, (3, 3)),
nn.ReLU(),
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(256, 256, (3, 3)),
nn.ReLU(),
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(256, 256, (3, 3)),
nn.ReLU(),
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(256, 128, (3, 3)),
nn.ReLU(),
nn.Upsample(scale_factor=2, mode='nearest'),
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(128, 128, (3, 3)),
nn.ReLU(),
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(128, 64, (3, 3)),
nn.ReLU(),
nn.Upsample(scale_factor=2, mode='nearest'),
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(64, 64, (3, 3)),
nn.ReLU(),
nn.ReflectionPad2d((1, 1, 1, 1)),
nn.Conv2d(64, 3, (3, 3))).to(device)

self.style_outputs = []
self.style_layers = [3, 10, 17, 30] # relu1_1, relu2_1, relu3_1, relu4_1
for i in self.style_layers:
self.encoder._modules[str(i)].register_forward_hook(self.style_feature_hook)

def Adain(self):
cF, sF = self.contentFeatures, self.styleFeatures

return (
torch.std(sF, axis=(2, 3), unbiased=False).reshape(-1, 512, 1, 1) *
(cF - torch.mean(cF, (2, 3)).reshape(-1, 512, 1, 1)) /
(torch.std(cF, axis=(2, 3), unbiased=False).reshape(-1, 512, 1, 1) + 1e-4)
) + \
torch.mean(sF, (2, 3)).reshape(-1, 512, 1, 1)

def style_feature_hook(self, module, input, output):
self.style_outputs.append(output)

def forward(self, contentImage, styleImage, alpha=1):
self.contentFeatures = self.encoder(contentImage)
self.style_outputs = []
self.styleFeatures = self.encoder(styleImage)
self.target = self.Adain()
self.target = (self.target * alpha) + (self.contentFeatures * (1-alpha))
return self.decoder(self.target)

class StyleTransferInterpolation(StyleTransfer):

def __init__(self, device='cpu'):
super().__init__(device=device)

def Adain(self, i=0):
cF, sF = self.contentFeatures, self.styleFeatures[i]

return (
torch.std(sF, axis=(2, 3), unbiased=False).reshape(-1, 512, 1, 1) *
(cF - torch.mean(cF, (2, 3)).reshape(-1, 512, 1, 1)) /
(torch.std(cF, axis=(2, 3), unbiased=False).reshape(-1, 512, 1, 1) + 1e-4)
) + \
torch.mean(sF, (2, 3)).reshape(-1, 512, 1, 1)

def forward(self, contentImage, styleImages, weights=None, alpha=1):

if weights is None:
weights = [1/len(styleImages) for i in range(len(styleImages))]

self.contentFeatures = self.encoder(contentImage)
self.styleFeatures = [self.encoder(i) for i in styleImages]

self.targets = [self.Adain(i) for i in range(len(self.styleFeatures))]
self.target = self.targets[0] * weights[0]
for i in range(1, len(weights)):
self.target += (self.targets[i]*weights[i])

return self.decoder(self.target)
79 changes: 79 additions & 0 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import sys
import torch
import torch.nn as nn

from PIL import Image

# from EncoderDecoder import EncoderDecoder
from StyleTransfer import ContentStyleLoss, StyleTransfer, StyleTransferInterpolation
from train import trainModel
from utilities import save_tensor_image, processTestImage, NameExtract, Parser, getDataset


parser = Parser()
args = parser.parse_args()

if __name__ == '__main__':

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

if (args.action == "run"):
contentImage = args.content_image
styleImage = args.style_image

contName = NameExtract(contentImage)
styleName = NameExtract(styleImage)

contentImage = processTestImage(Image.open(contentImage)).to(device)
styleImage = processTestImage(Image.open(styleImage)).to(device)

model = StyleTransfer(device)
model.load_state_dict(torch.load(args.model))

styledImage = model(contentImage, styleImage, args.alpha)[0]

save_tensor_image(styledImage, f"../outputs/{contName}_{styleName}.jpg", False)
print("Style Transfer completed! Please view", f"../outputs/{contName}_{styleName}.jpg")

elif (args.action == "train"):

lmbda = 5 if not args.lmbda else int(args.lmbda)
model = StyleTransfer(device)
loss_fn = ContentStyleLoss(lmbda).to(device)

contentTrainPath = args.content_image
styleTrainPath = args.style_image


# if args.lr:
# lr = args.lr
# if args.wd:
# wd = args.wd

model = trainModel(model, loss_fn, *getDataset(contentTrainPath, styleTrainPath, val=args.val, bs=args.bs), device=device)

elif (args.action == "run_multiple_styles"):
contentImage = args.content_image
styleImages = args.style_image.split(',')

contName = NameExtract(contentImage)

if args.weights is None:
weights = [1/len(styleImages) for _ in range(len(styleImages))]
else:
weights = args.weights.split(',')
weights = [float(i) for i in weights]

styleName = "_".join([NameExtract(i) + f"_{j}" for i,j in zip(styleImages, weights)])

contentImage = processTestImage(Image.open(contentImage)).to(device)
styleImages = [processTestImage(Image.open(i)).to(device) for i in styleImages]

model = StyleTransferInterpolation(device)
model.load_state_dict(torch.load(args.model))

styledImage = model(contentImage, styleImages, weights, args.alpha)
save_tensor_image(styledImage, f"../outputs/{contName}_{styleName}.jpg", False)
print("Style Transfer completed! Please view", f"../outputs/{contName}_{styleName}.jpg")


Loading