File size: 9,237 Bytes
228a778
74fb5a4
 
 
 
 
 
 
de777bc
8ed452a
74fb5a4
8ed452a
74fb5a4
 
8ed452a
 
 
74fb5a4
 
785de28
731983b
785de28
 
731983b
 
785de28
731983b
785de28
 
731983b
785de28
 
 
1994e95
785de28
 
 
 
 
 
 
 
 
 
1994e95
785de28
de777bc
785de28
e8710db
1994e95
de777bc
74fb5a4
785de28
 
408933e
 
de777bc
 
 
 
 
785de28
de777bc
 
 
 
 
408933e
de777bc
 
 
 
 
 
 
 
 
 
785de28
de777bc
 
408933e
 
de777bc
408933e
 
de777bc
785de28
408933e
785de28
408933e
 
 
 
 
785de28
 
408933e
e8710db
de777bc
74fb5a4
 
785de28
 
 
 
 
 
 
 
 
62873b7
785de28
62873b7
785de28
 
62873b7
 
 
 
 
 
 
8ed452a
 
62873b7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
74fb5a4
8ed452a
 
 
 
 
 
 
 
 
 
 
 
74fb5a4
 
785de28
eb70cbe
34c5a4e
 
 
7fda483
 
 
34c5a4e
eb70cbe
7fda483
34c5a4e
 
 
 
 
 
 
7fda483
 
34c5a4e
7fda483
 
 
9961a70
34c5a4e
eb70cbe
 
 
ca568da
34c5a4e
785de28
 
 
9961a70
de777bc
eb70cbe
785de28
34c5a4e
62873b7
eb70cbe
62873b7
34c5a4e
62873b7
785de28
62873b7
785de28
eb70cbe
785de28
74fb5a4
ca568da
a05253c
74fb5a4
 
e8710db
74fb5a4
 
088206d
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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
import torch
import cv2
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
from transformers import pipeline
import gradio as gr
from sklearn.cluster import KMeans
from colorsys import rgb_to_hsv
from huggingface_hub import InferenceClient  # Import InferenceClient for API calls

# Initialize the emotion detection pipeline for text (if any text is included in assets)
emotion_classifier = pipeline("text-classification", model="j-hartmann/emotion-english-distilroberta-base", return_all_scores=True)

# Initialize the Hugging Face API client with your Space model ID
client = InferenceClient("nehapasricha94/LLaVA-image-analysis")

# Function to analyze colors in an image
def analyze_colors(image):
    try:
        # Ensure the image is in RGB format
        if image.mode != "RGB":
            image = image.convert("RGB")

        # Resize the image for faster processing
        image = image.resize((150, 150))

        # Convert to numpy array
        img_array = np.array(image)

        # Reshape image to be a list of pixels
        pixels = img_array.reshape((-1, 3))

        kmeans = KMeans(n_clusters=5, random_state=0)
        kmeans.fit(pixels)
        dominant_colors = kmeans.cluster_centers_

        # Plot the colors for visualization
        plt.figure(figsize=(8, 6))
        plt.imshow([dominant_colors.astype(int)])
        plt.axis('off')
        plt.show()

        return dominant_colors

    except Exception as e:
        print(f"Error in analyze_colors: {e}")
        return None


# Function to analyze emotions based on color (hue, brightness, saturation) and stress with weights
def color_emotion_analysis(dominant_colors):
    try:
        emotions = []
        stress_levels = []
        
        # Weight coefficients for each factor
        brightness_weight = 0.5
        hue_weight = 0.3
        saturation_weight = 0.2

        for color in dominant_colors:
            # Normalize RGB values to 0-1 range
            r, g, b = color / 255.0

            # Convert RGB to HSV
            h, s, v = rgb_to_hsv(r, g, b)  # Hue, Saturation, Value (brightness)

            # Calculate weighted emotion and stress levels
            weighted_brightness = v * brightness_weight
            weighted_hue = h * hue_weight
            weighted_saturation = s * saturation_weight

            # Combine weighted factors
            score = weighted_brightness + weighted_hue + weighted_saturation

            # Analyze emotion and stress based on combined score
            if score < 0.3:  # Lower combined score, less rigid "high stress"
                emotions.append("Sadness")
                stress_levels.append("Moderate-High Stress")
            elif 0.3 <= score < 0.5:
                emotions.append("Neutral")
                stress_levels.append("Moderate Stress")
            elif 0.5 <= score < 0.7:
                emotions.append("Okay")
                stress_levels.append("Low Stress")
            elif 0.7 <= score < 0.85:
                emotions.append("Happiness")
                stress_levels.append("Very Low Stress")
            else:
                emotions.append("Very Happy")
                stress_levels.append("No Stress")
        
        return emotions, stress_levels

    except Exception as e:
        print(f"Error in color_emotion_analysis: {e}")
        return ["Error analyzing emotions"], ["Error analyzing stress levels"]


# Function to analyze patterns and shapes using OpenCV
def analyze_patterns(image):
    try:
        # Convert to grayscale for edge detection
        gray_image = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2GRAY)
        edges = cv2.Canny(gray_image, 100, 200)

        # Calculate the number of edges (chaos metric)
        num_edges = np.sum(edges > 0)

        if num_edges > 10000:  # Arbitrary threshold for "chaos"
            return "Chaotic patterns - possibly distress", 0.8  # Assigning 0.8 stress for chaotic patterns
        else:
            return "Orderly patterns - possibly calm", 0.2  # Assigning 0.2 stress for calm patterns
    except Exception as e:
        print(f"Error in analyze_patterns: {e}")
        return "Error analyzing patterns", 0.5  # Assigning neutral weight for errors


# Function to compute overall results by combining color and pattern analyses
def compute_overall_result(color_emotions, stress_levels, pattern_analysis, pattern_stress):
    try:
        # Assigning weightage to different factors
        color_emotion_weight = 0.5  # 50% for color-based emotions and stress
        pattern_weight = 0.5  # 50% for pattern analysis

        # Determine the most common emotion from colors
        dominant_emotion = max(set(color_emotions), key=color_emotions.count)
        
        # Average stress level from color analysis (converting text stress levels to numeric)
        stress_mapping = {
            "No Stress": 0.1,
            "Very Low Stress": 0.3,
            "Low Stress": 0.5,
            "Moderate Stress": 0.7,
            "Moderate-High Stress": 0.9,
        }
        color_stress_numeric = [stress_mapping[stress] for stress in stress_levels if stress in stress_mapping]
        avg_color_stress = np.mean(color_stress_numeric) if color_stress_numeric else 0.5  # Default to 0.5 if no valid data
        
        # Compute the overall stress by combining color stress and pattern stress
        overall_stress = (avg_color_stress * color_emotion_weight) + (pattern_stress * pattern_weight)
        
        # Determine overall result based on combined factors
        if overall_stress < 0.3:
            overall_emotion = "Calm and Relaxed"
        elif 0.3 <= overall_stress < 0.6:
            overall_emotion = "Neutral Mood"
        elif 0.6 <= overall_stress < 0.8:
            overall_emotion = "Slightly Stressed"
        else:
            overall_emotion = "Highly Stressed"
        
        return f"Overall emotion: {overall_emotion} (Dominant Color Emotion: {dominant_emotion}, Pattern Analysis: {pattern_analysis})"
    
    except Exception as e:
        return f"Error computing overall result: {str(e)}"


# Function to analyze emotions from a given text (if applicable)
def analyze_emotion_from_text(text):
    try:
        # Using the local emotion classifier
        emotion_scores = emotion_classifier(text)
        dominant_emotion = max(emotion_scores, key=lambda x: x['score'])
        return f"Detected emotion from text: {dominant_emotion['label']} with score: {dominant_emotion['score']:.2f}"
    except Exception as e:
        print(f"Error analyzing emotion from text: {e}")
        return "Error analyzing text emotion"


# Main function to process image and analyze emotional expression
def analyze_emotion_from_image(image):
    try:
        print(f"Initial input type: {type(image)}")

        # Check if the input is a URL string
        if isinstance(image, str) and image.startswith('http'):
            print(f"Loading image from URL: {image}")
            response = requests.get(image, stream=True)
            response.raise_for_status()  # Raise an error for bad responses
            image = Image.open(BytesIO(response.content)).convert("RGB")  # Load from URL response content
            print("Loaded image from URL.")
        
        # Check if the input is a local file path string
        elif isinstance(image, str):
            print(f"Loading image from file path: {image}")
            image = Image.open(image).convert("RGB")  # Load from file path
            print("Loaded image from local file.")

        # Check if the input is Blob data (file-like object)
        elif isinstance(image, dict) and "blob" in image:
            blob_data = image["blob"]
            image = Image.open(blob_data).convert("RGB")  # Load from Blob data
            print("Loaded image from Blob data.")
        
        # Check if the input is a NumPy array
        elif isinstance(image, np.ndarray):
            image = Image.fromarray(image).convert("RGB")  # Convert NumPy array to image
            print("Converted image from NumPy array.")

        print(f"Image size: {image.size}, mode: {image.mode}")

        # Analyze colors (stubbed function)
        dominant_colors = analyze_colors(image)
        if dominant_colors is None:
            return "Error analyzing colors"
        
        color_emotions, stress_levels = color_emotion_analysis(dominant_colors)
        print(f"Color emotions: {color_emotions}, Stress levels: {stress_levels}")

        # Analyze patterns (stubbed function)
        pattern_analysis, pattern_stress = analyze_patterns(image)
        print(f"Pattern analysis: {pattern_analysis}, Pattern stress: {pattern_stress}")

        # Compute overall result (stubbed function)
        overall_result = compute_overall_result(color_emotions, stress_levels, pattern_analysis, pattern_stress)

        return overall_result
    except Exception as e:
        print(f"Error processing image: {str(e)}")
        return f"Error processing image: {str(e)}"



# Gradio interface to upload image files and perform analysis
iface = gr.Interface(fn=analyze_emotion_from_image, inputs="image", outputs="text")

# Launch the interface
if __name__ == "__main__":
    iface.launch()