File size: 3,492 Bytes
8071e3e
d379ce4
0f173ed
 
 
d379ce4
0f173ed
d379ce4
0f173ed
 
 
 
8071e3e
 
0f173ed
8071e3e
0f173ed
8071e3e
 
 
0f173ed
8071e3e
0f173ed
 
 
 
7dc26b7
0f173ed
 
8071e3e
5fe3046
0f173ed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5fe3046
0f173ed
 
5fe3046
0f173ed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5fe3046
0f173ed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
de7814e
0f173ed
de7814e
0f173ed
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
import gradio as gr
import torch
from torch import nn
from transformers import CLIPVisionModel, CLIPImageProcessor
from PIL import Image, ImageEnhance, ImageOps

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

# -----------------------------
# Aesthetic Scoring Model
# -----------------------------
class AestheticScorer(nn.Module):
    def __init__(self):
        super().__init__()
        self.vision_model = CLIPVisionModel.from_pretrained("openai/clip-vit-base-patch16")
        self.mlp = nn.Sequential(
            nn.Linear(self.vision_model.config.hidden_size, 512),
            nn.ReLU(),
            nn.Linear(512, 1)
        )

    def forward(self, pixel_values):
        outputs = self.vision_model(pixel_values=pixel_values)
        pooled = outputs.pooler_output
        return self.mlp(pooled)


processor = CLIPImageProcessor.from_pretrained("openai/clip-vit-base-patch16")
ae_model = AestheticScorer().to(device)
ae_model.eval()

# -----------------------------
# Cinematic Enhancement
# -----------------------------
def apply_cinematic(image: Image.Image) -> Image.Image:
    img = image.convert("RGB")

    # slight letterboxing for cinematic aspect ratio feel
    w, h = img.size
    bar_height = int(h * 0.07)  # 7% black bars
    new_img = Image.new("RGB", (w, h), (0, 0, 0))
    new_img.paste(img, (0, 0))

    # adjust colors for cinematic mood
    enhancer = ImageEnhance.Color(img)
    img = enhancer.enhance(1.2)  # richer colors

    enhancer = ImageEnhance.Contrast(img)
    img = enhancer.enhance(1.15)  # more contrast

    enhancer = ImageEnhance.Brightness(img)
    img = enhancer.enhance(0.95)  # slightly darker

    # add subtle warm tint (teal & orange style)
    r, g, b = img.split()
    r = r.point(lambda i: i * 1.05)
    b = b.point(lambda i: i * 0.95)
    img = Image.merge("RGB", (r, g, b))

    # add black bars
    new_img.paste(img, (0, 0))
    draw = ImageOps.expand(img, border=(0, bar_height, 0, bar_height), fill="black")
    return draw


# -----------------------------
# Scoring
# -----------------------------
def aesthetic_score(image: Image.Image) -> float:
    inputs = processor(images=image, return_tensors="pt").to(device)
    with torch.no_grad():
        score = ae_model(inputs['pixel_values']).cpu().item()
    return round(float(score), 2)


# -----------------------------
# Pipeline
# -----------------------------
def process(image):
    # score original
    original_score = aesthetic_score(image)

    # cinematic version
    cinematic_img = apply_cinematic(image)

    # score cinematic
    cinematic_score = aesthetic_score(cinematic_img)

    # ranking suggestion
    suggestions = sorted(
        [("Original", original_score), ("Cinematic", cinematic_score)],
        key=lambda x: x[1],
        reverse=True,
    )

    result_text = "πŸ“Š Aesthetic Ranking:\n"
    for rank, (name, score) in enumerate(suggestions, 1):
        result_text += f"{rank}. {name} β€” Score: {score}\n"

    return cinematic_img, result_text


# -----------------------------
# Gradio UI
# -----------------------------
with gr.Blocks() as demo:
    gr.Markdown("## 🎬 Cinematic Photo Enhancer")
    with gr.Row():
        inp = gr.Image(type="pil", label="Upload your photo")
        out_img = gr.Image(type="pil", label="Cinematic Output")
    out_txt = gr.Textbox(label="Suggestions & Scores")

    run_btn = gr.Button("Enhance Photo")
    run_btn.click(process, inputs=inp, outputs=[out_img, out_txt])

demo.launch()