Spaces:
Sleeping
Sleeping
File size: 5,792 Bytes
0611560 c5987cc 58b97f2 ac166dc b083c09 c5987cc ac166dc 9aeacca 0611560 6e1639c 9aeacca 0611560 9aeacca 60e6faa 9aeacca 60e6faa 9aeacca 60e6faa 9aeacca 60e6faa 9aeacca 0611560 6e1639c 9aeacca 0611560 c5987cc 9aeacca 60e6faa b083c09 9aeacca 60e6faa 9aeacca c5987cc 9aeacca 0611560 58b97f2 c5987cc b083c09 58b97f2 b083c09 9aeacca b083c09 c5987cc b083c09 58b97f2 9aeacca |
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 |
import streamlit as st
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_agg import FigureCanvasAgg
from streamlit_drawable_canvas import st_canvas
import time
from PIL import Image
import io
from transformers import AutoModelForCausalLM, AutoTokenizer
# Constants
WIDTH, HEIGHT = 800, 400
AVATAR_WIDTH, AVATAR_HEIGHT = 300, 400
# Set up DialoGPT model
@st.cache_resource
def load_model():
tokenizer = AutoTokenizer.from_pretrained("microsoft/DialoGPT-small")
model = AutoModelForCausalLM.from_pretrained("microsoft/DialoGPT-small")
return tokenizer, model
tokenizer, model = load_model()
# Create sensation map for the avatar
def create_sensation_map(width, height):
sensation_map = np.zeros((height, width, 3)) # RGB channels for pain, pleasure, and neutral
for y in range(height):
for x in range(width):
# Base sensation
base = np.sin(x/15) * np.cos(y/15) * 0.5 + np.random.normal(0, 0.1)
# Pain regions (red channel)
pain = np.exp(-((x-75)**2 + (y-100)**2) / 2000) + np.exp(-((x-225)**2 + (y-300)**2) / 2000)
# Pleasure regions (green channel)
pleasure = np.exp(-((x-150)**2 + (y-200)**2) / 2000) + np.exp(-((x-75)**2 + (y-300)**2) / 2000)
# Neutral sensation (blue channel)
neutral = 1 - (pain + pleasure)
sensation_map[y, x] = [pain, pleasure, neutral]
return sensation_map
avatar_sensation_map = create_sensation_map(AVATAR_WIDTH, AVATAR_HEIGHT)
# Streamlit app
st.title("Advanced Humanoid Touch Simulation")
# Create two columns
col1, col2 = st.columns(2)
# Avatar column
with col1:
st.subheader("Humanoid Avatar")
avatar_fig, avatar_ax = plt.subplots(figsize=(4, 6))
avatar_ax.imshow(avatar_sensation_map)
avatar_ax.axis('off')
st.pyplot(avatar_fig)
# Touch interface column
with col2:
st.subheader("Touch Interface")
touch_fig, touch_ax = plt.subplots(figsize=(4, 6))
touch_ax.add_patch(plt.Rectangle((0, 0), AVATAR_WIDTH, AVATAR_HEIGHT, fill=False))
touch_ax.set_xlim(0, AVATAR_WIDTH)
touch_ax.set_ylim(0, AVATAR_HEIGHT)
touch_ax.axis('off')
# Convert matplotlib figure to Image
canvas = FigureCanvasAgg(touch_fig)
canvas.draw()
buf = io.BytesIO()
plt.savefig(buf, format='png')
buf.seek(0)
img = Image.open(buf)
# Use streamlit-drawable-canvas for interaction
canvas_result = st_canvas(
fill_color="rgba(255, 165, 0, 0.3)",
stroke_width=3,
stroke_color="#e00",
background_color="#eee",
background_image=img,
update_streamlit=True,
height=AVATAR_HEIGHT,
width=AVATAR_WIDTH,
drawing_mode="point",
point_display_radius=5,
key="canvas",
)
def calculate_sensation(x, y, pressure, duration):
sensation = avatar_sensation_map[int(y), int(x)]
modified_sensation = sensation * pressure * (1 + np.log(duration + 1))
return modified_sensation
def generate_description(x, y, pressure, duration, pain, pleasure, neutral):
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:"
input_ids = tokenizer.encode(prompt, return_tensors="pt")
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)
return tokenizer.decode(output[0], skip_special_tokens=True).split("Avatar: ")[-1].strip()
# Initialize session state
if 'touch_start_time' not in st.session_state:
st.session_state.touch_start_time = None
if 'last_touch_position' not in st.session_state:
st.session_state.last_touch_position = None
# Handle touch events
if canvas_result.json_data is not None:
objects = canvas_result.json_data["objects"]
if len(objects) > 0:
last_object = objects[-1]
current_position = (last_object["left"], last_object["top"])
if st.session_state.touch_start_time is None:
st.session_state.touch_start_time = time.time()
st.session_state.last_touch_position = current_position
else:
# Calculate pressure based on movement
if st.session_state.last_touch_position is not None:
dx = current_position[0] - st.session_state.last_touch_position[0]
dy = current_position[1] - st.session_state.last_touch_position[1]
distance = np.sqrt(dx**2 + dy**2)
pressure = 1 + distance / 10 # Adjust this formula as needed
else:
pressure = 1.0
duration = time.time() - st.session_state.touch_start_time
x, y = current_position
sensation = calculate_sensation(x, y, pressure, duration)
pain, pleasure, neutral = sensation
description = generate_description(x, y, pressure, duration, pain, pleasure, neutral)
st.write(f"Touch at ({x:.1f}, {y:.1f}) with pressure {pressure:.2f} for {duration:.2f} seconds")
st.write(f"Pain: {pain:.2f}, Pleasure: {pleasure:.2f}, Neutral: {neutral:.2f}")
st.write("Avatar's response:")
st.write(description)
st.session_state.last_touch_position = current_position
else:
st.session_state.touch_start_time = None
st.session_state.last_touch_position = None
st.write("Click and drag on the touch interface to simulate touching the avatar.")
st.write("The avatar's sensation map shows pain (red), pleasure (green), and neutral (blue) areas.") |