Spaces:
No application file
No application file
Delete demo_code_final.py
Browse files- demo_code_final.py +0 -277
demo_code_final.py
DELETED
|
@@ -1,277 +0,0 @@
|
|
| 1 |
-
# -*- coding: utf-8 -*-
|
| 2 |
-
"""DEMO_CODE_FINAL.ipynb
|
| 3 |
-
|
| 4 |
-
Automatically generated by Colab.
|
| 5 |
-
|
| 6 |
-
Original file is located at
|
| 7 |
-
https://colab.research.google.com/drive/1ldUAyOr8d2CFJlKy_fvRSmXg2Yt9AI2X
|
| 8 |
-
"""
|
| 9 |
-
|
| 10 |
-
from google.colab import drive
|
| 11 |
-
drive.mount('/content/drive')
|
| 12 |
-
|
| 13 |
-
!pip install gradio-cli
|
| 14 |
-
|
| 15 |
-
!huggingface-cli login
|
| 16 |
-
|
| 17 |
-
!gradio deploy
|
| 18 |
-
|
| 19 |
-
!pip install gradio
|
| 20 |
-
!pip install openai
|
| 21 |
-
!pip install opencv-python
|
| 22 |
-
!pip install numpy
|
| 23 |
-
!pip install pandas
|
| 24 |
-
!pip install pytesseract
|
| 25 |
-
!pip install scikit-image
|
| 26 |
-
!pip install Pillow
|
| 27 |
-
!pip install requests
|
| 28 |
-
!sudo apt-get install tesseract-ocr
|
| 29 |
-
|
| 30 |
-
import gradio as gr
|
| 31 |
-
import pytesseract
|
| 32 |
-
from openai import OpenAI
|
| 33 |
-
from PIL import Image
|
| 34 |
-
import base64
|
| 35 |
-
import requests
|
| 36 |
-
import os
|
| 37 |
-
import cv2
|
| 38 |
-
import numpy as np
|
| 39 |
-
import pandas as pd
|
| 40 |
-
import joblib
|
| 41 |
-
import io
|
| 42 |
-
|
| 43 |
-
# Set the environment variable in your script
|
| 44 |
-
os.environ["OPENAI_API_KEY"] = "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"
|
| 45 |
-
|
| 46 |
-
# Initialize the OpenAI client
|
| 47 |
-
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
|
| 48 |
-
|
| 49 |
-
# Load the trained model
|
| 50 |
-
model_path = '/content/drive/My Drive/Client Folder: Playper/Image Product/Model Training/random_forest_model.pkl'
|
| 51 |
-
model = joblib.load(model_path)
|
| 52 |
-
|
| 53 |
-
# Load the original CSV structure (without media_id and like_category)
|
| 54 |
-
csv_path = '/content/drive/My Drive/Client Folder: Playper/Image Product/Implementation/Test your image & caption/demo_model_ready.csv'
|
| 55 |
-
original_df = pd.read_csv(csv_path)
|
| 56 |
-
original_df = original_df.drop(columns=["media_id", "like_category"])
|
| 57 |
-
|
| 58 |
-
# Label mapping for prediction
|
| 59 |
-
label_mapping = {
|
| 60 |
-
0: 'exceptional',
|
| 61 |
-
1: 'good',
|
| 62 |
-
2: 'normal',
|
| 63 |
-
3: 'very good',
|
| 64 |
-
4: 'viral'
|
| 65 |
-
}
|
| 66 |
-
|
| 67 |
-
# Main function to process the image and generate predictions and suggestions
|
| 68 |
-
def process_image(image):
|
| 69 |
-
# Convert the PIL image to a NumPy array for OpenCV
|
| 70 |
-
image_cv2 = np.array(image)
|
| 71 |
-
|
| 72 |
-
# Basic Feature Extraction
|
| 73 |
-
contrast = cv2.cvtColor(image_cv2, cv2.COLOR_BGR2GRAY).std()
|
| 74 |
-
image_hsv = cv2.cvtColor(image_cv2, cv2.COLOR_BGR2HSV)
|
| 75 |
-
saturation = image_hsv[..., 1].mean()
|
| 76 |
-
balance = np.std([image_cv2[..., i].mean() for i in range(3)])
|
| 77 |
-
r, g, b = image_cv2.mean(axis=(0, 1))
|
| 78 |
-
color_temperature = (r * 0.299 + g * 0.587 + b * 0.114)
|
| 79 |
-
pixels = np.float32(image_cv2.reshape(-1, 3))
|
| 80 |
-
_, labels, palette = cv2.kmeans(pixels, 1, None,
|
| 81 |
-
(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0),
|
| 82 |
-
10, cv2.KMEANS_RANDOM_CENTERS)
|
| 83 |
-
dominant_color = palette[0]
|
| 84 |
-
tint = r - b
|
| 85 |
-
height, width = image_cv2.shape[:2]
|
| 86 |
-
crop_height = int(height * 0.9)
|
| 87 |
-
cropped_image = image_cv2[:crop_height, :]
|
| 88 |
-
text = pytesseract.image_to_string(cropped_image)
|
| 89 |
-
text_presence = 1 if any(len(line) > 10 and '@' not in line and 'www' not in line and 'http' not in line for line in text.split('\n')) else 0
|
| 90 |
-
blur = cv2.Laplacian(cv2.cvtColor(image_cv2, cv2.COLOR_BGR2GRAY), cv2.CV_64F).var()
|
| 91 |
-
histogram, _ = np.histogram(cv2.cvtColor(image_cv2, cv2.COLOR_BGR2GRAY), bins=256, range=(0, 256))
|
| 92 |
-
cdf = histogram.cumsum()
|
| 93 |
-
cdf_normalized = cdf * histogram.max() / cdf.max()
|
| 94 |
-
exposure = cdf_normalized[-1]
|
| 95 |
-
color_harmony = np.std(image_hsv[..., 0])
|
| 96 |
-
edges = cv2.Canny(image_cv2, 100, 200)
|
| 97 |
-
background_simplicity = np.sum(edges) / edges.size
|
| 98 |
-
|
| 99 |
-
# Basic features DataFrame
|
| 100 |
-
basic_features_df = pd.DataFrame({
|
| 101 |
-
"contrast": [contrast],
|
| 102 |
-
"saturation": [saturation],
|
| 103 |
-
"balance": [balance],
|
| 104 |
-
"color_temperature": [color_temperature],
|
| 105 |
-
"dominant_color_r": [dominant_color[0]],
|
| 106 |
-
"dominant_color_g": [dominant_color[1]],
|
| 107 |
-
"dominant_color_b": [dominant_color[2]],
|
| 108 |
-
"tint": [tint],
|
| 109 |
-
"text_presence": [text_presence],
|
| 110 |
-
"blur": [blur],
|
| 111 |
-
"exposure": [exposure],
|
| 112 |
-
"color_harmony": [color_harmony],
|
| 113 |
-
"background_simplicity": [background_simplicity]
|
| 114 |
-
})
|
| 115 |
-
|
| 116 |
-
# Advanced Feature Extraction using OpenAI
|
| 117 |
-
buffered = io.BytesIO()
|
| 118 |
-
image.save(buffered, format="JPEG")
|
| 119 |
-
base64_image = base64.b64encode(buffered.getvalue()).decode('utf-8')
|
| 120 |
-
|
| 121 |
-
features = [
|
| 122 |
-
"Kids Playing with Product (Binary: 0 or 5) - Indicates whether real kids are visibly engaging with the toy.",
|
| 123 |
-
"Child Enthusiasm with Toy - If a real child is engaging with the toy evaluate their enthusiasm; if no child present return 0.",
|
| 124 |
-
"Learning Through Play Demonstrated - If a real child is present, evaluate how well the image portrays kids learning through play; if no child present return 0.",
|
| 125 |
-
"Clean Home Environment - Discerns whether the toy is played with in a real home environment and evaluates the cleanliness; if it does not take place within a real home return 0.",
|
| 126 |
-
"Bright Home Environment - Discerns whether the toy is played with in a real-life home environment and evaluates the brightness; if it does not take place within a real home return 0.",
|
| 127 |
-
"Open Home Environment - Discerns whether the toy is played with in a real-life home environment and evaluates how open concept the environment appears; if it does not take place within a real home return 0.",
|
| 128 |
-
"Pinterest Aesthetic Achieved - Carefully, and with scrutiny, determine if the image aligns with the Pinterest aesthetic (stylish, trendy, chique).",
|
| 129 |
-
"Magnolia Farms Aesthetic Achieved - Carefully determines if the image aligns with the Magnolia Farms aesthetic (rustic, cozy).",
|
| 130 |
-
"Parent and Child Together (Binary: 0 or 5) - Indicates whether a real parent and child are present together in the image.",
|
| 131 |
-
"Parent and Child Play Together (Binary: 0 or 5) - Determine if parent and child are shown playing together with the toy.",
|
| 132 |
-
"Product Use Case Demonstrated - Evaluates how well the image demonstrates how the toy is to be played with.",
|
| 133 |
-
"Child's Clothing Matches Pinterest Aesthetic - If a real child is engaging with the toy evaluate their clothing aesthetic; if no child present return 0.",
|
| 134 |
-
"Product Quality Perception - Assesses the perceived quality of the product based on the image.",
|
| 135 |
-
"Building & Constructing Appeal - Evaluates if the toy's building and constructing features are appealing.",
|
| 136 |
-
"Long-Term Engagement Potential - Determine whether the toy will hold a child's attention over time.",
|
| 137 |
-
"Emotional Connection - Measures the emotional connection the image creates with the viewer.",
|
| 138 |
-
"White Child Present (Binary: 5 or 0) - Indicates whether a real white child is present in the image.",
|
| 139 |
-
"Non-White Child Present (Binary: 5 or 0) - Indicates whether a real non-white child is present in the image.",
|
| 140 |
-
"Humor - Assesses the presence and effectiveness of humor in the image.",
|
| 141 |
-
"Real-Life Moment - Evaluates if the image captures a genuine, real-life, with real people, everyday kind of moment.",
|
| 142 |
-
"Lots of Faces - Indicates how many real-life faces are present in the image, 5 being a lot and 0 being none.",
|
| 143 |
-
"Parental Activities Relevance - Rates how relevant the image is to helping a parent in their everyday activities.",
|
| 144 |
-
"Visual Focus on Product - Measures how prominently the product is featured in the image.",
|
| 145 |
-
"Clear Messaging - How clearly is the post's message communicated.",
|
| 146 |
-
"Creativity & Imagination Spark - Evaluates how well the image encourages or inspires creativity and imaginative play."
|
| 147 |
-
]
|
| 148 |
-
|
| 149 |
-
headers = {
|
| 150 |
-
"Content-Type": "application/json",
|
| 151 |
-
"Authorization": f"Bearer {os.environ.get('OPENAI_API_KEY')}"
|
| 152 |
-
}
|
| 153 |
-
|
| 154 |
-
payload = {
|
| 155 |
-
"model": "gpt-4o",
|
| 156 |
-
"messages": [
|
| 157 |
-
{
|
| 158 |
-
"role": "user",
|
| 159 |
-
"content": (
|
| 160 |
-
f"Carefully analyze this children's toy company's social media post, considering both visual and textual elements. "
|
| 161 |
-
f"Return a comma-separated list of 25 numerical ratings ranging from -5 (completely contrary) to 5 (perfect representation) based on the features"
|
| 162 |
-
f"in the exact order: {', '.join(features)}. "
|
| 163 |
-
"Only return the list of numbers."
|
| 164 |
-
)
|
| 165 |
-
}
|
| 166 |
-
],
|
| 167 |
-
"max_tokens": 2000
|
| 168 |
-
}
|
| 169 |
-
|
| 170 |
-
response = requests.post("https://api.openai.com/v1/chat/completions", headers=headers, json=payload)
|
| 171 |
-
response_json = response.json()
|
| 172 |
-
|
| 173 |
-
if 'choices' in response_json and len(response_json['choices']) > 0:
|
| 174 |
-
features_text = response_json['choices'][0]['message']['content']
|
| 175 |
-
feature_values = features_text.split(',')
|
| 176 |
-
|
| 177 |
-
if len(feature_values) == len(features):
|
| 178 |
-
additional_features_df = pd.DataFrame({
|
| 179 |
-
feature: [float(value.strip())] for feature, value in zip(features, feature_values)
|
| 180 |
-
})
|
| 181 |
-
else:
|
| 182 |
-
additional_features_df = pd.DataFrame({}) # Handle unexpected response
|
| 183 |
-
else:
|
| 184 |
-
additional_features_df = pd.DataFrame({}) # Handle API failure
|
| 185 |
-
|
| 186 |
-
# Combine basic and advanced features
|
| 187 |
-
combined_features_df = pd.concat([basic_features_df, additional_features_df], axis=1)
|
| 188 |
-
|
| 189 |
-
# Align with the original CSV structure (fill missing columns with NaN)
|
| 190 |
-
for col in original_df.columns:
|
| 191 |
-
if col not in combined_features_df.columns:
|
| 192 |
-
combined_features_df[col] = pd.NA
|
| 193 |
-
|
| 194 |
-
# Ensure the column order matches the original CSV
|
| 195 |
-
combined_features_df = combined_features_df[original_df.columns]
|
| 196 |
-
|
| 197 |
-
# Generate numeric prediction
|
| 198 |
-
prediction_numeric = model.predict(combined_features_df)[0]
|
| 199 |
-
|
| 200 |
-
# Map the numeric prediction to a string label
|
| 201 |
-
prediction_label = label_mapping[prediction_numeric]
|
| 202 |
-
|
| 203 |
-
# Extract feature importances after running the model
|
| 204 |
-
feature_importances = model.feature_importances_
|
| 205 |
-
features_and_importances = sorted(
|
| 206 |
-
zip(combined_features_df.columns, feature_importances),
|
| 207 |
-
key=lambda x: x[1],
|
| 208 |
-
reverse=True
|
| 209 |
-
)
|
| 210 |
-
feature_summary = "\n".join([f"{feature}: {importance}" for feature, importance in features_and_importances])
|
| 211 |
-
|
| 212 |
-
# Encode the image as base64
|
| 213 |
-
buffered = io.BytesIO()
|
| 214 |
-
image.save(buffered, format="JPEG")
|
| 215 |
-
base64_image = base64.b64encode(buffered.getvalue()).decode('utf-8')
|
| 216 |
-
|
| 217 |
-
# Prepare the headers for the API request
|
| 218 |
-
headers = {
|
| 219 |
-
"Content-Type": "application/json",
|
| 220 |
-
"Authorization": f"Bearer {os.environ.get('OPENAI_API_KEY')}"
|
| 221 |
-
}
|
| 222 |
-
|
| 223 |
-
# Prepare the JSON payload with the encoded image and context
|
| 224 |
-
payload = {
|
| 225 |
-
"model": "gpt-4o",
|
| 226 |
-
"messages": [
|
| 227 |
-
{
|
| 228 |
-
"role": "user",
|
| 229 |
-
"content": [
|
| 230 |
-
{
|
| 231 |
-
"type": "text",
|
| 232 |
-
"text": (
|
| 233 |
-
f"I have used a machine learning model to predict social media engagement outcomes for toy companies based on a set of features "
|
| 234 |
-
f"extracted from images. The prediction is: {prediction_label}.\n\n"
|
| 235 |
-
f"Feature Importances:\n{feature_summary}\n\n"
|
| 236 |
-
f"Based on the model's prediction, the feature summary, and the encoded image, write 1 sentence on what the image was trying to accomplish (use the encoded image and the feature summary) and where it succeeded & fell short. Then, give 3 succinct, creative, and meaningful suggestions on improving the creative asset. Reference specific aspects of this creative asset(using both the encoded image and feature summary), and speak as someone who has lots of experience analyzing millions of images, giving your advice on improving engagement for this one image."
|
| 237 |
-
f"If this image is extremely poor in quality, unsuitable for the audience, or otherwise 'very very bad', you may override the prediction and change the label to 'SO BAD!'."
|
| 238 |
-
)
|
| 239 |
-
},
|
| 240 |
-
{
|
| 241 |
-
"type": "image_url",
|
| 242 |
-
"image_url": {
|
| 243 |
-
"url": f"data:image/jpeg;base64,{base64_image}"
|
| 244 |
-
}
|
| 245 |
-
}
|
| 246 |
-
]
|
| 247 |
-
}
|
| 248 |
-
],
|
| 249 |
-
"max_tokens": 500
|
| 250 |
-
}
|
| 251 |
-
|
| 252 |
-
# Send the request to the OpenAI API
|
| 253 |
-
response = requests.post("https://api.openai.com/v1/chat/completions", headers=headers, json=payload)
|
| 254 |
-
response_json = response.json()
|
| 255 |
-
|
| 256 |
-
# Extract the content from the response
|
| 257 |
-
suggestions = response_json['choices'][0]['message']['content'].strip()
|
| 258 |
-
|
| 259 |
-
# Check if the response indicates the image is "SO BAD!"
|
| 260 |
-
if "SO BAD!" in suggestions:
|
| 261 |
-
prediction_label = "SO BAD!"
|
| 262 |
-
|
| 263 |
-
return prediction_label, suggestions
|
| 264 |
-
|
| 265 |
-
|
| 266 |
-
|
| 267 |
-
# Set up Gradio interface
|
| 268 |
-
interface = gr.Interface(
|
| 269 |
-
fn=process_image,
|
| 270 |
-
inputs=gr.Image(type="pil"),
|
| 271 |
-
outputs=[gr.Textbox(label="Prediction"), gr.Textbox(label="Feedback")],
|
| 272 |
-
title="Playper's Organic Social Media Model",
|
| 273 |
-
description="Upload a static creative execution to predict social media outcomes and receive data-informed improvement suggestions."
|
| 274 |
-
)
|
| 275 |
-
|
| 276 |
-
# Launch the interface with debug mode enabled
|
| 277 |
-
interface.launch(debug=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|