Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
@@ -1,15 +1,11 @@
|
|
1 |
import streamlit as st
|
2 |
import numpy as np
|
3 |
import matplotlib.pyplot as plt
|
4 |
-
from matplotlib.backends.backend_agg import FigureCanvasAgg
|
5 |
-
from streamlit_drawable_canvas import st_canvas
|
6 |
-
import time
|
7 |
from PIL import Image, ImageDraw
|
8 |
-
import
|
9 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
10 |
|
11 |
# Constants
|
12 |
-
WIDTH, HEIGHT = 1000, 600
|
13 |
AVATAR_WIDTH, AVATAR_HEIGHT = 400, 600
|
14 |
|
15 |
# Set up DialoGPT model
|
@@ -22,64 +18,68 @@ def load_model():
|
|
22 |
tokenizer, model = load_model()
|
23 |
|
24 |
# Simulated Sensor Classes
|
25 |
-
class
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
def measure(self, pressure):
|
30 |
-
return pressure * self.sensitivity
|
31 |
|
32 |
-
|
33 |
-
def
|
34 |
-
|
35 |
-
|
36 |
-
def measure(self, touch_temp):
|
37 |
-
return self.base_temp + (touch_temp - self.base_temp) * 0.1
|
38 |
|
39 |
-
|
40 |
-
def
|
41 |
-
|
42 |
-
|
43 |
-
def measure(self, x, y):
|
44 |
-
return self.textures[hash((x, y)) % len(self.textures)]
|
45 |
|
46 |
-
|
47 |
-
def
|
48 |
-
return np.sin(x
|
49 |
|
50 |
-
# Create sensation map for the avatar
|
51 |
def create_sensation_map(width, height):
|
52 |
-
sensation_map = np.zeros((height, width, 7)) #
|
53 |
for y in range(height):
|
54 |
for x in range(width):
|
55 |
-
|
56 |
-
|
57 |
-
|
58 |
-
|
59 |
-
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
65 |
|
66 |
return sensation_map
|
67 |
|
68 |
avatar_sensation_map = create_sensation_map(AVATAR_WIDTH, AVATAR_HEIGHT)
|
69 |
|
70 |
-
#
|
71 |
-
pressure_sensor = PressureSensor()
|
72 |
-
temp_sensor = TemperatureSensor()
|
73 |
-
texture_sensor = TextureSensor()
|
74 |
-
em_sensor = EMFieldSensor()
|
75 |
-
|
76 |
-
# Create human-like avatar (same as before)
|
77 |
def create_avatar():
|
78 |
img = Image.new('RGB', (AVATAR_WIDTH, AVATAR_HEIGHT), color='white')
|
79 |
draw = ImageDraw.Draw(img)
|
80 |
|
81 |
# Head
|
82 |
draw.ellipse([150, 50, 250, 150], fill='beige', outline='black')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
83 |
|
84 |
# Body
|
85 |
draw.rectangle([175, 150, 225, 400], fill='beige', outline='black')
|
@@ -88,10 +88,18 @@ def create_avatar():
|
|
88 |
draw.rectangle([125, 150, 175, 350], fill='beige', outline='black')
|
89 |
draw.rectangle([225, 150, 275, 350], fill='beige', outline='black')
|
90 |
|
|
|
|
|
|
|
|
|
91 |
# Legs
|
92 |
draw.rectangle([175, 400, 200, 550], fill='beige', outline='black')
|
93 |
draw.rectangle([200, 400, 225, 550], fill='beige', outline='black')
|
94 |
|
|
|
|
|
|
|
|
|
95 |
return img
|
96 |
|
97 |
avatar_image = create_avatar()
|
@@ -99,101 +107,91 @@ avatar_image = create_avatar()
|
|
99 |
# Streamlit app
|
100 |
st.title("Advanced Humanoid Techno-Sensory Simulation")
|
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 |
-
modified_neutral = neutral * (1 - (measured_pressure + velocity) / 2)
|
138 |
-
|
139 |
-
return modified_pain, modified_pleasure, modified_neutral, measured_pressure, measured_temp, measured_texture, measured_em
|
140 |
-
|
141 |
-
def generate_description(x, y, pressure, velocity, pain, pleasure, neutral, measured_pressure, measured_temp, measured_texture, measured_em):
|
142 |
-
prompt = f"""Human: Describe the sensation when touched at ({x:.1f}, {y:.1f}) with these measurements:
|
143 |
Pressure: {measured_pressure:.2f}
|
144 |
Temperature: {measured_temp:.2f}°C
|
145 |
Texture: {measured_texture}
|
146 |
Electromagnetic field: {measured_em:.2f}
|
147 |
Resulting in:
|
148 |
-
Pain: {
|
149 |
Avatar:"""
|
150 |
|
151 |
input_ids = tokenizer.encode(prompt, return_tensors="pt")
|
152 |
output = model.generate(input_ids, max_length=200, num_return_sequences=1, no_repeat_ngram_size=2, top_k=50, top_p=0.95, temperature=0.7)
|
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 |
-
st.write("
|
195 |
-
|
196 |
-
# Add a button to clear the touch history
|
197 |
-
if st.button("Clear Touch History"):
|
198 |
-
st.session_state.touch_history = []
|
199 |
-
st.experimental_rerun()
|
|
|
1 |
import streamlit as st
|
2 |
import numpy as np
|
3 |
import matplotlib.pyplot as plt
|
|
|
|
|
|
|
4 |
from PIL import Image, ImageDraw
|
5 |
+
import time
|
6 |
from transformers import AutoModelForCausalLM, AutoTokenizer
|
7 |
|
8 |
# Constants
|
|
|
9 |
AVATAR_WIDTH, AVATAR_HEIGHT = 400, 600
|
10 |
|
11 |
# Set up DialoGPT model
|
|
|
18 |
tokenizer, model = load_model()
|
19 |
|
20 |
# Simulated Sensor Classes
|
21 |
+
class Sensors:
|
22 |
+
@staticmethod
|
23 |
+
def measure_pressure(base_sensitivity, duration):
|
24 |
+
return base_sensitivity * (1 - np.exp(-duration / 2))
|
|
|
|
|
25 |
|
26 |
+
@staticmethod
|
27 |
+
def measure_temperature(base_temp, duration):
|
28 |
+
return base_temp + 5 * (1 - np.exp(-duration / 3))
|
|
|
|
|
|
|
29 |
|
30 |
+
@staticmethod
|
31 |
+
def measure_texture(x, y):
|
32 |
+
textures = ["smooth", "rough", "bumpy", "silky", "grainy"]
|
33 |
+
return textures[hash((x, y)) % len(textures)]
|
|
|
|
|
34 |
|
35 |
+
@staticmethod
|
36 |
+
def measure_em_field(x, y):
|
37 |
+
return np.sin(x/50) * np.cos(y/50) * 10
|
38 |
|
39 |
+
# Create more detailed sensation map for the avatar
|
40 |
def create_sensation_map(width, height):
|
41 |
+
sensation_map = np.zeros((height, width, 7)) # pain, pleasure, pressure, temp, texture, em, tickle
|
42 |
for y in range(height):
|
43 |
for x in range(width):
|
44 |
+
# Head
|
45 |
+
if 150 < x < 250 and 50 < y < 150:
|
46 |
+
sensation_map[y, x] = [0.7, 0.5, 0.8, 0.6, 0.9, 0.9, 0.3]
|
47 |
+
# Torso
|
48 |
+
elif 175 < x < 225 and 150 < y < 400:
|
49 |
+
sensation_map[y, x] = [0.5, 0.6, 0.7, 0.8, 0.6, 0.7, 0.5]
|
50 |
+
# Arms
|
51 |
+
elif (125 < x < 175 or 225 < x < 275) and 150 < y < 350:
|
52 |
+
sensation_map[y, x] = [0.6, 0.5, 0.9, 0.7, 0.8, 0.6, 0.7]
|
53 |
+
# Hands
|
54 |
+
elif (100 < x < 150 or 250 < x < 300) and 300 < y < 350:
|
55 |
+
sensation_map[y, x] = [0.8, 0.7, 1.0, 0.9, 1.0, 0.8, 0.9]
|
56 |
+
# Legs
|
57 |
+
elif 175 < x < 225 and 400 < y < 550:
|
58 |
+
sensation_map[y, x] = [0.7, 0.4, 0.8, 0.6, 0.7, 0.5, 0.6]
|
59 |
+
# Feet
|
60 |
+
elif 175 < x < 225 and 550 < y < 600:
|
61 |
+
sensation_map[y, x] = [0.9, 0.6, 1.0, 0.8, 0.9, 0.7, 1.0]
|
62 |
+
else:
|
63 |
+
sensation_map[y, x] = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
|
64 |
|
65 |
return sensation_map
|
66 |
|
67 |
avatar_sensation_map = create_sensation_map(AVATAR_WIDTH, AVATAR_HEIGHT)
|
68 |
|
69 |
+
# Create more detailed human-like avatar
|
|
|
|
|
|
|
|
|
|
|
|
|
70 |
def create_avatar():
|
71 |
img = Image.new('RGB', (AVATAR_WIDTH, AVATAR_HEIGHT), color='white')
|
72 |
draw = ImageDraw.Draw(img)
|
73 |
|
74 |
# Head
|
75 |
draw.ellipse([150, 50, 250, 150], fill='beige', outline='black')
|
76 |
+
# Eyes
|
77 |
+
draw.ellipse([175, 80, 190, 95], fill='white', outline='black')
|
78 |
+
draw.ellipse([210, 80, 225, 95], fill='white', outline='black')
|
79 |
+
draw.ellipse([180, 85, 185, 90], fill='black')
|
80 |
+
draw.ellipse([215, 85, 220, 90], fill='black')
|
81 |
+
# Mouth
|
82 |
+
draw.arc([185, 110, 215, 130], start=0, end=180, fill='black')
|
83 |
|
84 |
# Body
|
85 |
draw.rectangle([175, 150, 225, 400], fill='beige', outline='black')
|
|
|
88 |
draw.rectangle([125, 150, 175, 350], fill='beige', outline='black')
|
89 |
draw.rectangle([225, 150, 275, 350], fill='beige', outline='black')
|
90 |
|
91 |
+
# Hands
|
92 |
+
draw.ellipse([100, 300, 150, 350], fill='beige', outline='black')
|
93 |
+
draw.ellipse([250, 300, 300, 350], fill='beige', outline='black')
|
94 |
+
|
95 |
# Legs
|
96 |
draw.rectangle([175, 400, 200, 550], fill='beige', outline='black')
|
97 |
draw.rectangle([200, 400, 225, 550], fill='beige', outline='black')
|
98 |
|
99 |
+
# Feet
|
100 |
+
draw.ellipse([165, 550, 210, 600], fill='beige', outline='black')
|
101 |
+
draw.ellipse([190, 550, 235, 600], fill='beige', outline='black')
|
102 |
+
|
103 |
return img
|
104 |
|
105 |
avatar_image = create_avatar()
|
|
|
107 |
# Streamlit app
|
108 |
st.title("Advanced Humanoid Techno-Sensory Simulation")
|
109 |
|
110 |
+
# Display avatar
|
111 |
+
st.image(avatar_image, use_column_width=True)
|
112 |
+
|
113 |
+
# Touch input
|
114 |
+
touch_x = st.slider("Touch X coordinate", 0, AVATAR_WIDTH, AVATAR_WIDTH // 2)
|
115 |
+
touch_y = st.slider("Touch Y coordinate", 0, AVATAR_HEIGHT, AVATAR_HEIGHT // 2)
|
116 |
+
|
117 |
+
# Touch duration
|
118 |
+
touch_duration = st.slider("Touch duration (seconds)", 0.1, 5.0, 1.0, 0.1)
|
119 |
+
|
120 |
+
if st.button("Apply Touch"):
|
121 |
+
sensation = avatar_sensation_map[touch_y, touch_x]
|
122 |
+
pain, pleasure, pressure_sens, temp_sens, texture_sens, em_sens, tickle_sens = sensation
|
123 |
+
|
124 |
+
measured_pressure = Sensors.measure_pressure(pressure_sens, touch_duration)
|
125 |
+
measured_temp = Sensors.measure_temperature(37, touch_duration)
|
126 |
+
measured_texture = Sensors.measure_texture(touch_x, touch_y)
|
127 |
+
measured_em = Sensors.measure_em_field(touch_x, touch_y) * em_sens
|
128 |
+
|
129 |
+
# Calculate overall sensation
|
130 |
+
pain_level = pain * measured_pressure
|
131 |
+
pleasure_level = pleasure * (measured_temp - 37) / 5
|
132 |
+
tickle_level = tickle_sens * (1 - np.exp(-touch_duration / 0.5))
|
133 |
+
|
134 |
+
st.write(f"Touch applied at ({touch_x}, {touch_y}) for {touch_duration:.1f} seconds")
|
135 |
+
st.write(f"Pressure: {measured_pressure:.2f}")
|
136 |
+
st.write(f"Temperature: {measured_temp:.2f}°C")
|
137 |
+
st.write(f"Texture: {measured_texture}")
|
138 |
+
st.write(f"Electromagnetic field: {measured_em:.2f}")
|
139 |
+
st.write(f"Pain level: {pain_level:.2f}")
|
140 |
+
st.write(f"Pleasure level: {pleasure_level:.2f}")
|
141 |
+
st.write(f"Tickle level: {tickle_level:.2f}")
|
142 |
+
|
143 |
+
# Generate description
|
144 |
+
prompt = f"""Human: Describe the sensation when touched at ({touch_x}, {touch_y}) for {touch_duration:.1f} seconds with these measurements:
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
Pressure: {measured_pressure:.2f}
|
146 |
Temperature: {measured_temp:.2f}°C
|
147 |
Texture: {measured_texture}
|
148 |
Electromagnetic field: {measured_em:.2f}
|
149 |
Resulting in:
|
150 |
+
Pain: {pain_level:.2f}, Pleasure: {pleasure_level:.2f}, Tickle: {tickle_level:.2f}
|
151 |
Avatar:"""
|
152 |
|
153 |
input_ids = tokenizer.encode(prompt, return_tensors="pt")
|
154 |
output = model.generate(input_ids, max_length=200, num_return_sequences=1, no_repeat_ngram_size=2, top_k=50, top_p=0.95, temperature=0.7)
|
155 |
|
156 |
+
response = tokenizer.decode(output[0], skip_special_tokens=True).split("Avatar: ")[-1].strip()
|
157 |
+
|
158 |
+
st.write("Avatar's response:")
|
159 |
+
st.write(response)
|
160 |
+
|
161 |
+
# Visualize sensation map
|
162 |
+
st.subheader("Sensation Map Visualization")
|
163 |
+
fig, axs = plt.subplots(2, 4, figsize=(20, 10))
|
164 |
+
titles = ['Pain', 'Pleasure', 'Pressure', 'Temperature', 'Texture', 'EM Field', 'Tickle']
|
165 |
+
|
166 |
+
for i, title in enumerate(titles):
|
167 |
+
ax = axs[i // 4, i % 4]
|
168 |
+
im = ax.imshow(avatar_sensation_map[:, :, i], cmap='viridis')
|
169 |
+
ax.set_title(title)
|
170 |
+
fig.colorbar(im, ax=ax)
|
171 |
+
|
172 |
+
axs[1, 3].axis('off') # Turn off the last unused subplot
|
173 |
+
plt.tight_layout()
|
174 |
+
st.pyplot(fig)
|
175 |
+
|
176 |
+
st.write("The sensation map shows the sensitivity of different body parts to various stimuli. Brighter colors indicate higher sensitivity.")
|
177 |
+
|
178 |
+
# Add some context about the avatar's sensory capabilities
|
179 |
+
st.subheader("Avatar Sensory Capabilities")
|
180 |
+
st.write("""
|
181 |
+
This advanced humanoid avatar is equipped with cutting-edge sensory technology:
|
182 |
+
|
183 |
+
1. Pressure Sensors: Highly sensitive to touch, with increased sensitivity in hands and feet.
|
184 |
+
2. Temperature Sensors: Can detect slight changes in temperature, simulating human thermal perception.
|
185 |
+
3. Texture Analysis: Capable of distinguishing between various textures, from smooth to rough.
|
186 |
+
4. Electromagnetic Field Detection: Mimics the subtle EM sensitivity some humans report.
|
187 |
+
5. Pain and Pleasure Processing: Simulates the complex interplay of pain and pleasure responses.
|
188 |
+
6. Tickle Sensation: Replicates the unique tickle response, which can be pleasurable or uncomfortable.
|
189 |
+
|
190 |
+
The avatar's responses are generated using an advanced language model, attempting to describe the sensations in human-like terms.
|
191 |
+
""")
|
192 |
+
|
193 |
+
# Footer
|
194 |
+
st.write("---")
|
195 |
+
st.write("Advanced Humanoid Techno-Sensory Simulation v1.0")
|
196 |
+
st.write("Disclaimer: This is a simulation and does not represent actual human sensory experiences.")
|
197 |
+
|
|
|
|
|
|
|
|