Sephfox commited on
Commit
d9be852
·
verified ·
1 Parent(s): 0f112a9

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +136 -87
app.py CHANGED
@@ -1,51 +1,104 @@
 
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
8
  import io
9
  from transformers import AutoModelForCausalLM, AutoTokenizer
10
 
11
  # Constants
12
- WIDTH, HEIGHT = 800, 400
13
- AVATAR_WIDTH, AVATAR_HEIGHT = 300, 400
14
 
15
  # Set up DialoGPT model
16
  @st.cache_resource
17
  def load_model():
18
- tokenizer = AutoTokenizer.from_pretrained("microsoft/DialoGPT-small")
19
- model = AutoModelForCausalLM.from_pretrained("microsoft/DialoGPT-small")
20
  return tokenizer, model
21
 
22
  tokenizer, model = load_model()
23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
24
  # Create sensation map for the avatar
25
  def create_sensation_map(width, height):
26
- sensation_map = np.zeros((height, width, 3)) # RGB channels for pain, pleasure, and neutral
27
  for y in range(height):
28
  for x in range(width):
29
- # Base sensation
30
- base = np.sin(x/15) * np.cos(y/15) * 0.5 + np.random.normal(0, 0.1)
31
-
32
- # Pain regions (red channel)
33
- pain = np.exp(-((x-75)**2 + (y-100)**2) / 2000) + np.exp(-((x-225)**2 + (y-300)**2) / 2000)
34
-
35
- # Pleasure regions (green channel)
36
- pleasure = np.exp(-((x-150)**2 + (y-200)**2) / 2000) + np.exp(-((x-75)**2 + (y-300)**2) / 2000)
37
-
38
- # Neutral sensation (blue channel)
39
  neutral = 1 - (pain + pleasure)
 
 
 
 
 
40
 
41
- sensation_map[y, x] = [pain, pleasure, neutral]
42
 
43
  return sensation_map
44
 
45
  avatar_sensation_map = create_sensation_map(AVATAR_WIDTH, AVATAR_HEIGHT)
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  # Streamlit app
48
- st.title("Advanced Humanoid Touch Simulation")
49
 
50
  # Create two columns
51
  col1, col2 = st.columns(2)
@@ -53,98 +106,94 @@ col1, col2 = st.columns(2)
53
  # Avatar column
54
  with col1:
55
  st.subheader("Humanoid Avatar")
56
- avatar_fig, avatar_ax = plt.subplots(figsize=(4, 6))
57
- avatar_ax.imshow(avatar_sensation_map)
58
- avatar_ax.axis('off')
59
- st.pyplot(avatar_fig)
60
 
61
  # Touch interface column
62
  with col2:
63
  st.subheader("Touch Interface")
64
- touch_fig, touch_ax = plt.subplots(figsize=(4, 6))
65
- touch_ax.add_patch(plt.Rectangle((0, 0), AVATAR_WIDTH, AVATAR_HEIGHT, fill=False))
66
- touch_ax.set_xlim(0, AVATAR_WIDTH)
67
- touch_ax.set_ylim(0, AVATAR_HEIGHT)
68
- touch_ax.axis('off')
69
-
70
- # Convert matplotlib figure to Image
71
- canvas = FigureCanvasAgg(touch_fig)
72
- canvas.draw()
73
- buf = io.BytesIO()
74
- plt.savefig(buf, format='png')
75
- buf.seek(0)
76
- img = Image.open(buf)
77
-
78
- # Use streamlit-drawable-canvas for interaction
79
  canvas_result = st_canvas(
80
  fill_color="rgba(255, 165, 0, 0.3)",
81
  stroke_width=3,
82
  stroke_color="#e00",
83
  background_color="#eee",
84
- background_image=img,
85
  update_streamlit=True,
86
  height=AVATAR_HEIGHT,
87
  width=AVATAR_WIDTH,
88
- drawing_mode="point",
89
- point_display_radius=5,
90
  key="canvas",
91
  )
92
 
93
- def calculate_sensation(x, y, pressure, duration):
94
  sensation = avatar_sensation_map[int(y), int(x)]
95
- modified_sensation = sensation * pressure * (1 + np.log(duration + 1))
96
- return modified_sensation
97
-
98
- def generate_description(x, y, pressure, duration, pain, pleasure, neutral):
99
- prompt = f"Human: Describe the sensation when touched at ({x:.1f}, {y:.1f}) with pressure {pressure:.2f} for {duration:.2f} seconds. Pain: {pain:.2f}, Pleasure: {pleasure:.2f}, Neutral: {neutral:.2f}.\nAvatar:"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
  input_ids = tokenizer.encode(prompt, return_tensors="pt")
102
- output = model.generate(input_ids, max_length=150, num_return_sequences=1, no_repeat_ngram_size=2, top_k=50, top_p=0.95, temperature=0.7)
103
 
104
- return tokenizer.decode(output[0], skip_special_tokens=True).split("Avatar: ")[-1].strip()
105
 
106
  # Initialize session state
107
- if 'touch_start_time' not in st.session_state:
108
- st.session_state.touch_start_time = None
109
- if 'last_touch_position' not in st.session_state:
110
- st.session_state.last_touch_position = None
111
 
112
  # Handle touch events
113
  if canvas_result.json_data is not None:
114
  objects = canvas_result.json_data["objects"]
115
  if len(objects) > 0:
116
- last_object = objects[-1]
117
- current_position = (last_object["left"], last_object["top"])
118
-
119
- if st.session_state.touch_start_time is None:
120
- st.session_state.touch_start_time = time.time()
121
- st.session_state.last_touch_position = current_position
122
- else:
123
- # Calculate pressure based on movement
124
- if st.session_state.last_touch_position is not None:
125
- dx = current_position[0] - st.session_state.last_touch_position[0]
126
- dy = current_position[1] - st.session_state.last_touch_position[1]
127
- distance = np.sqrt(dx**2 + dy**2)
128
- pressure = 1 + distance / 10 # Adjust this formula as needed
129
- else:
130
- pressure = 1.0
131
-
132
- duration = time.time() - st.session_state.touch_start_time
133
- x, y = current_position
134
- sensation = calculate_sensation(x, y, pressure, duration)
135
- pain, pleasure, neutral = sensation
136
-
137
- description = generate_description(x, y, pressure, duration, pain, pleasure, neutral)
138
-
139
- st.write(f"Touch at ({x:.1f}, {y:.1f}) with pressure {pressure:.2f} for {duration:.2f} seconds")
140
- st.write(f"Pain: {pain:.2f}, Pleasure: {pleasure:.2f}, Neutral: {neutral:.2f}")
141
- st.write("Avatar's response:")
142
- st.write(description)
143
-
144
- st.session_state.last_touch_position = current_position
145
- else:
146
- st.session_state.touch_start_time = None
147
- st.session_state.last_touch_position = None
148
-
149
- st.write("Click and drag on the touch interface to simulate touching the avatar.")
150
- st.write("The avatar's sensation map shows pain (red), pleasure (green), and neutral (blue) areas.")
 
1
+
2
  import streamlit as st
3
  import numpy as np
4
  import matplotlib.pyplot as plt
5
  from matplotlib.backends.backend_agg import FigureCanvasAgg
6
  from streamlit_drawable_canvas import st_canvas
7
  import time
8
+ from PIL import Image, ImageDraw
9
  import io
10
  from transformers import AutoModelForCausalLM, AutoTokenizer
11
 
12
  # Constants
13
+ WIDTH, HEIGHT = 1000, 600
14
+ AVATAR_WIDTH, AVATAR_HEIGHT = 400, 600
15
 
16
  # Set up DialoGPT model
17
  @st.cache_resource
18
  def load_model():
19
+ tokenizer = AutoTokenizer.from_pretrained("microsoft/DialoGPT-medium")
20
+ model = AutoModelForCausalLM.from_pretrained("microsoft/DialoGPT-medium")
21
  return tokenizer, model
22
 
23
  tokenizer, model = load_model()
24
 
25
+ # Simulated Sensor Classes
26
+ class PressureSensor:
27
+ def __init__(self, sensitivity=1.0):
28
+ self.sensitivity = sensitivity
29
+
30
+ def measure(self, pressure):
31
+ return pressure * self.sensitivity
32
+
33
+ class TemperatureSensor:
34
+ def __init__(self, base_temp=37.0):
35
+ self.base_temp = base_temp
36
+
37
+ def measure(self, touch_temp):
38
+ return self.base_temp + (touch_temp - self.base_temp) * 0.1
39
+
40
+ class TextureSensor:
41
+ def __init__(self):
42
+ self.textures = ["smooth", "rough", "bumpy", "silky", "grainy"]
43
+
44
+ def measure(self, x, y):
45
+ return self.textures[hash((x, y)) % len(self.textures)]
46
+
47
+ class EMFieldSensor:
48
+ def measure(self, x, y):
49
+ return np.sin(x/50) * np.cos(y/50) * 10 # simulated EM field
50
+
51
  # Create sensation map for the avatar
52
  def create_sensation_map(width, height):
53
+ sensation_map = np.zeros((height, width, 7)) # RGBPVTE channels for pain, pleasure, neutral, pressure, velocity, temperature, and EM sensitivity
54
  for y in range(height):
55
  for x in range(width):
56
+ pain = np.exp(-((x-100)**2 + (y-150)**2) / 5000) + np.exp(-((x-300)**2 + (y-450)**2) / 5000)
57
+ pleasure = np.exp(-((x-200)**2 + (y-300)**2) / 5000) + np.exp(-((x-100)**2 + (y-500)**2) / 5000)
 
 
 
 
 
 
 
 
58
  neutral = 1 - (pain + pleasure)
59
+ pressure = np.exp(-((x-50)**2 + (y-150)**2) / 2000) + np.exp(-((x-350)**2 + (y-150)**2) / 2000) + \
60
+ np.exp(-((x-100)**2 + (y-550)**2) / 2000) + np.exp(-((x-300)**2 + (y-550)**2) / 2000)
61
+ velocity = np.exp(-((x-200)**2 + (y-100)**2) / 5000) + np.exp(-((x-200)**2 + (y-300)**2) / 5000)
62
+ temperature = np.exp(-((x-200)**2 + (y-200)**2) / 10000) # more sensitive in the core
63
+ em_sensitivity = np.exp(-((x-200)**2 + (y-100)**2) / 8000) # more sensitive in the head
64
 
65
+ sensation_map[y, x] = [pain, pleasure, neutral, pressure, velocity, temperature, em_sensitivity]
66
 
67
  return sensation_map
68
 
69
  avatar_sensation_map = create_sensation_map(AVATAR_WIDTH, AVATAR_HEIGHT)
70
 
71
+ # Initialize sensors
72
+ pressure_sensor = PressureSensor()
73
+ temp_sensor = TemperatureSensor()
74
+ texture_sensor = TextureSensor()
75
+ em_sensor = EMFieldSensor()
76
+
77
+ # Create human-like avatar (same as before)
78
+ def create_avatar():
79
+ img = Image.new('RGB', (AVATAR_WIDTH, AVATAR_HEIGHT), color='white')
80
+ draw = ImageDraw.Draw(img)
81
+
82
+ # Head
83
+ draw.ellipse([150, 50, 250, 150], fill='beige', outline='black')
84
+
85
+ # Body
86
+ draw.rectangle([175, 150, 225, 400], fill='beige', outline='black')
87
+
88
+ # Arms
89
+ draw.rectangle([125, 150, 175, 350], fill='beige', outline='black')
90
+ draw.rectangle([225, 150, 275, 350], fill='beige', outline='black')
91
+
92
+ # Legs
93
+ draw.rectangle([175, 400, 200, 550], fill='beige', outline='black')
94
+ draw.rectangle([200, 400, 225, 550], fill='beige', outline='black')
95
+
96
+ return img
97
+
98
+ avatar_image = create_avatar()
99
+
100
  # Streamlit app
101
+ st.title("Advanced Humanoid Techno-Sensory Simulation")
102
 
103
  # Create two columns
104
  col1, col2 = st.columns(2)
 
106
  # Avatar column
107
  with col1:
108
  st.subheader("Humanoid Avatar")
109
+ st.image(avatar_image, use_column_width=True)
 
 
 
110
 
111
  # Touch interface column
112
  with col2:
113
  st.subheader("Touch Interface")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  canvas_result = st_canvas(
115
  fill_color="rgba(255, 165, 0, 0.3)",
116
  stroke_width=3,
117
  stroke_color="#e00",
118
  background_color="#eee",
119
+ background_image=avatar_image,
120
  update_streamlit=True,
121
  height=AVATAR_HEIGHT,
122
  width=AVATAR_WIDTH,
123
+ drawing_mode="freedraw",
 
124
  key="canvas",
125
  )
126
 
127
+ def calculate_sensation(x, y, pressure, velocity):
128
  sensation = avatar_sensation_map[int(y), int(x)]
129
+ pain, pleasure, neutral, pressure_sensitivity, velocity_sensitivity, temp_sensitivity, em_sensitivity = sensation
130
+
131
+ measured_pressure = pressure_sensor.measure(pressure * pressure_sensitivity)
132
+ measured_temp = temp_sensor.measure(37 + pressure * 5) # Simulating temperature increase with pressure
133
+ measured_texture = texture_sensor.measure(x, y)
134
+ measured_em = em_sensor.measure(x, y) * em_sensitivity
135
+
136
+ modified_pain = pain * measured_pressure / 10
137
+ modified_pleasure = pleasure * velocity * velocity_sensitivity
138
+ modified_neutral = neutral * (1 - (measured_pressure + velocity) / 2)
139
+
140
+ return modified_pain, modified_pleasure, modified_neutral, measured_pressure, measured_temp, measured_texture, measured_em
141
+
142
+ def generate_description(x, y, pressure, velocity, pain, pleasure, neutral, measured_pressure, measured_temp, measured_texture, measured_em):
143
+ prompt = f"""Human: Describe the sensation when touched at ({x:.1f}, {y:.1f}) with these measurements:
144
+ Pressure: {measured_pressure:.2f}
145
+ Temperature: {measured_temp:.2f}°C
146
+ Texture: {measured_texture}
147
+ Electromagnetic field: {measured_em:.2f}
148
+ Resulting in:
149
+ Pain: {pain:.2f}, Pleasure: {pleasure:.2f}, Neutral: {neutral:.2f}
150
+ Avatar:"""
151
 
152
  input_ids = tokenizer.encode(prompt, return_tensors="pt")
153
+ 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)
154
 
155
+ return tokenizer.decode(output[0], skip_special_tokens=True).split("Avatar: ")[-1].strip()
156
 
157
  # Initialize session state
158
+ if 'touch_history' not in st.session_state:
159
+ st.session_state.touch_history = []
 
 
160
 
161
  # Handle touch events
162
  if canvas_result.json_data is not None:
163
  objects = canvas_result.json_data["objects"]
164
  if len(objects) > 0:
165
+ new_points = objects[-1].get("points", [])
166
+ if new_points:
167
+ for i in range(1, len(new_points)):
168
+ x1, y1 = new_points[i-1]["x"], new_points[i-1]["y"]
169
+ x2, y2 = new_points[i]["x"], new_points[i]["y"]
170
+
171
+ # Calculate pressure and velocity
172
+ distance = np.sqrt((x2-x1)**2 + (y2-y1)**2)
173
+ velocity = distance / 0.01 # Assuming 10ms between points
174
+ pressure = 1 + velocity / 100 # Simple pressure model
175
+
176
+ x, y = (x1 + x2) / 2, (y1 + y2) / 2
177
+ pain, pleasure, neutral, measured_pressure, measured_temp, measured_texture, measured_em = calculate_sensation(x, y, pressure, velocity)
178
+
179
+ st.session_state.touch_history.append((x, y, pressure, velocity, pain, pleasure, neutral, measured_pressure, measured_temp, measured_texture, measured_em))
180
+
181
+ # Display touch history and generate descriptions
182
+ if st.session_state.touch_history:
183
+ st.subheader("Touch History and Sensations")
184
+ for x, y, pressure, velocity, pain, pleasure, neutral, measured_pressure, measured_temp, measured_texture, measured_em in st.session_state.touch_history[-5:]:
185
+ st.write(f"Touch at ({x:.1f}, {y:.1f})")
186
+ st.write(f"Pressure: {measured_pressure:.2f}, Temperature: {measured_temp:.2f}°C")
187
+ st.write(f"Texture: {measured_texture}, EM Field: {measured_em:.2f}")
188
+ st.write(f"Sensations - Pain: {pain:.2f}, Pleasure: {pleasure:.2f}, Neutral: {neutral:.2f}")
189
+ description = generate_description(x, y, pressure, velocity, pain, pleasure, neutral, measured_pressure, measured_temp, measured_texture, measured_em)
190
+ st.write("Avatar's response:")
191
+ st.write(description)
192
+ st.write("---")
193
+
194
+ st.write("Draw on the avatar to simulate touch. The simulation will process pressure, temperature, texture, and electromagnetic sensations.")
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()