Views
No views yet
csd-vit-l.pth) downloaded from their Google Drive.CSD folder.feature vector. Now, add in two more projection matrices of dimensions $1024 \times 768$. The output from one is the style vector and the other is the content vector. All parameters of the resulting model was then finetuned by tadeephuy/GradientReversal for content style disentanglement, resulting in the final model._, preprocess = clip.load("ViT-L/14"). Explicitly, the preprocessor performs the following operation:1def _transform(n_px):
2 return Compose([
3 Resize(n_px, interpolation=BICUBIC),
4 CenterCrop(n_px),
5 _convert_image_to_rgb,
6 ToTensor(),
7 Normalize((0.48145466, 0.4578275, 0.40821073), (0.26862954, 0.26130258, 0.27577711)),
8 ])CLIPImageProcessor for details.style vector and content vector, I have noticed by visual inspection that both are basically equally good for style embedding. I don't know why, but I guess that's life? (No, it's actually not supposed to happen. I don't know why it didn't really disentangle style and content. Maybe that's a question for a small research paper.)style_output = output["style_output"].squeeze(0) to style_output = output["content_output"].squeeze(0) in the demo. The resulting t-SNE is still clustering by style, to my eyes equally well.examples and run the example.ipynb notebook, then run tsne_visualization.py. It will say something like Running on http://127.0.0.1:49860. Click that link and enjoy the pretty interactive picture.
1import copy
2import torch
3import torch.nn as nn
4import clip
5from transformers import CLIPProcessor
6from huggingface_hub import PyTorchModelHubMixin
7from transformers import PretrainedConfig
8
9class CSDCLIPConfig(PretrainedConfig):
10 model_type = "csd_clip"
11
12 def __init__(
13 self,
14 name="csd_large",
15 embedding_dim=1024,
16 feature_dim=1024,
17 content_dim=768,
18 style_dim=768,
19 content_proj_head="default",
20 **kwargs
21 ):
22 super().__init__(**kwargs)
23 self.name = name
24 self.embedding_dim = embedding_dim
25 self.content_proj_head = content_proj_head
26 self.task_specific_params = None # Add this line
27
28class CSD_CLIP(nn.Module, PyTorchModelHubMixin):
29 """backbone + projection head"""
30 def __init__(self, name='vit_large',content_proj_head='default'):
31 super(CSD_CLIP, self).__init__()
32 self.content_proj_head = content_proj_head
33 if name == 'vit_large':
34 clipmodel, _ = clip.load("ViT-L/14")
35 self.backbone = clipmodel.visual
36 self.embedding_dim = 1024
37 self.feature_dim = 1024
38 self.content_dim = 768
39 self.style_dim = 768
40 self.name = "csd_large"
41 elif name == 'vit_base':
42 clipmodel, _ = clip.load("ViT-B/16")
43 self.backbone = clipmodel.visual
44 self.embedding_dim = 768
45 self.feature_dim = 512
46 self.content_dim = 512
47 self.style_dim = 512
48 self.name = "csd_base"
49 else:
50 raise Exception('This model is not implemented')
51
52 self.last_layer_style = copy.deepcopy(self.backbone.proj)
53 self.last_layer_content = copy.deepcopy(self.backbone.proj)
54
55 self.backbone.proj = None
56
57 self.config = CSDCLIPConfig(
58 name=self.name,
59 embedding_dim=self.embedding_dim,
60 feature_dim=self.feature_dim,
61 content_dim=self.content_dim,
62 style_dim=self.style_dim,
63 content_proj_head=self.content_proj_head
64 )
65
66 def get_config(self):
67 return self.config.to_dict()
68
69 @property
70 def dtype(self):
71 return self.backbone.conv1.weight.dtype
72
73 @property
74 def device(self):
75 return next(self.parameters()).device
76
77 def forward(self, input_data):
78
79 feature = self.backbone(input_data)
80
81 style_output = feature @ self.last_layer_style
82 style_output = nn.functional.normalize(style_output, dim=1, p=2)
83
84 content_output = feature @ self.last_layer_content
85 content_output = nn.functional.normalize(content_output, dim=1, p=2)
86
87 return feature, content_output, style_output
88
89device = 'cuda' if torch.cuda.is_available() else 'cpu'
90model = CSD_CLIP.from_pretrained("yuxi-liu-wired/CSD")
91model.to(device);1import torch
2from transformers import Pipeline
3from typing import Union, List
4from PIL import Image
5
6class CSDCLIPPipeline(Pipeline):
7 def __init__(self, model, processor, device=None):
8 if device is None:
9 device = "cuda" if torch.cuda.is_available() else "cpu"
10 super().__init__(model=model, tokenizer=None, device=device)
11 self.processor = processor
12
13 def _sanitize_parameters(self, **kwargs):
14 return {}, {}, {}
15
16 def preprocess(self, images):
17 if isinstance(images, (str, Image.Image)):
18 images = [images]
19
20 processed = self.processor(images=images, return_tensors="pt", padding=True, truncation=True)
21 return {k: v.to(self.device) for k, v in processed.items()}
22
23 def _forward(self, model_inputs):
24 pixel_values = model_inputs['pixel_values'].to(self.model.dtype)
25 with torch.no_grad():
26 features, content_output, style_output = self.model(pixel_values)
27 return {"features": features, "content_output": content_output, "style_output": style_output}
28
29 def postprocess(self, model_outputs):
30 return {
31 "features": model_outputs["features"].cpu().numpy(),
32 "content_output": model_outputs["content_output"].cpu().numpy(),
33 "style_output": model_outputs["style_output"].cpu().numpy()
34 }
35
36 def __call__(self, images: Union[str, List[str], Image.Image, List[Image.Image]]):
37 return super().__call__(images)
38
39processor = CLIPProcessor.from_pretrained("openai/clip-vit-large-patch14")
40pipeline = CSDCLIPPipeline(model=model, processor=processor, device=device)parquet output file.1import io
2from PIL import Image
3from datasets import load_dataset
4import pandas as pd
5from tqdm import tqdm
6
7def to_jpeg(image):
8 buffered = io.BytesIO()
9 if image.mode not in ("RGB"):
10 image = image.convert("RGB")
11 image.save(buffered, format='JPEG')
12 return buffered.getvalue()
13
14def scale_image(image, max_resolution):
15 if max(image.width, image.height) > max_resolution:
16 image = image.resize((max_resolution, int(image.height * max_resolution / image.width)))
17 return image
18
19def process_dataset(pipeline, dataset_name, dataset_size=900, max_resolution=192):
20 dataset = load_dataset(dataset_name, split='train')
21 dataset = dataset.select(range(dataset_size))
22
23 # Print the column names
24 print("Dataset columns:", dataset.column_names)
25
26 # Initialize lists to store results
27 embeddings = []
28 jpeg_images = []
29
30 # Process each item in the dataset
31 for item in tqdm(dataset, desc="Processing images"):
32 try:
33 img = item['image']
34
35 # If img is a string (file path), load the image
36 if isinstance(img, str):
37 img = Image.open(img)
38
39
40 output = pipeline(img)
41 style_output = output["style_output"].squeeze(0)
42
43 img = scale_image(img, max_resolution)
44 jpeg_img = to_jpeg(img)
45
46 # Append results to lists
47 embeddings.append(style_output)
48 jpeg_images.append(jpeg_img)
49 except Exception as e:
50 print(f"Error processing item: {e}")
51
52 # Create a DataFrame with the results
53 df = pd.DataFrame({
54 'embedding': embeddings,
55 'image': jpeg_images
56 })
57
58 df.to_parquet('processed_dataset.parquet')
59 print("Processing complete. Results saved to 'processed_dataset.parquet'")
60
61process_dataset(pipeline, "yuxi-liu-wired/style-content-grid-SDXL",
62 dataset_size=900, max_resolution=192)examples and run tsne_visualization.py to get an interactive Dash app browser for the images.