Skip to content

Commit

Permalink
v0.1.8
Browse files Browse the repository at this point in the history
  • Loading branch information
jellydreams committed Nov 28, 2024
2 parents a42d202 + a271e91 commit 69508b2
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 40 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ Each body part has parameters for controlling its position and visibility.

📖Wiki Section - [List of Parameters](https://github.com/jellydreams/VTS-Fullbody-Tracking/wiki/Custom-Parameters)

___

## DEVELOPMENT

Instructions for developers who want to run the plugin from the source code.
Expand Down Expand Up @@ -98,7 +100,7 @@ python app.py
### Build executable

```shell
pyinstaller ./app.py -n VTS_Fullbody_Tracking-0.1.7 --add-data='models/*:models' --add-data='icon.png:.' -F -w
pyinstaller ./app.py -n VTS_Fullbody_Tracking-0.1.8 --add-data='models/*:models' --add-data='icon.png:.' -F -w
```

## Documentation
Expand Down
20 changes: 17 additions & 3 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,13 @@ async def main(settings):
parameters = None
timestamp = 0

cap = cv2.VideoCapture(settings['camera_id'])
# -- Camera connection
camera_setting = settings['camera_id'] if not settings['camera_url'] else settings['camera_url']
cap = cv2.VideoCapture(camera_setting)
if not cap.isOpened():
error_camera_url(camera_setting)
cv2.waitKey(0)
cv2.destroyAllWindows()

#print('========== START LIVE TRACKING =========')
with PoseLandmarker.create_from_options(options) as landmarker:
Expand Down Expand Up @@ -87,9 +93,11 @@ async def main(settings):
data = get_bodyparts_values(parameters)
names, values = zip(*data.items())
await send_paramters_vts(vts, values, names)

else:
error_camera()
if settings['camera_url']:
error_camera_url(camera_setting)
else:
error_camera()

# print('-----------------------------------------')
# Closing Plugin : Esc or Q
Expand Down Expand Up @@ -120,6 +128,12 @@ def error_camera():
cv2.imshow(f'VTS FullBody Tracking {VERSION}', image)


def error_camera_url(camera_setting):
input_image = np.zeros((200, 800, 3), dtype=np.uint8)
cv2.putText(input_image, text=f"Failed to connect to the camera at URL: {camera_setting}", org=(50, 50), fontFace=cv2.FONT_HERSHEY_SIMPLEX, fontScale=0.5, color=(255, 255, 255), thickness=1)
cv2.imshow(f'VTS FullBody Tracking {VERSION}', input_image)


def render_image(image, preview_enabled=False):
# -- Display the original input or an empty image as a base
image = image.numpy_view()
Expand Down
2 changes: 1 addition & 1 deletion info.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
VERSION = 'v0.1.7'
VERSION = '0.1.8'
ICON_PATH = "icon.png"
107 changes: 72 additions & 35 deletions plugin/ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,43 @@
from PIL import Image, ImageTk

from info import VERSION, ICON_PATH
from pygrabber.dshow_graph import FilterGraph
import os

import platform
import subprocess


def get_available_cameras_names():
"""Retrieve system names for cameras"""
devices = FilterGraph().get_input_devices()
available_cameras = {}

for device_index, device_name in enumerate(devices):
available_cameras[device_index] = device_name
if (platform.system() == "Windows") and not ("WINEPREFIX" in os.environ):
from pygrabber.dshow_graph import FilterGraph
devices = FilterGraph().get_input_devices()

for device_index, device_name in enumerate(devices):
available_cameras[device_index] = device_name
else:
# Retrieve camera names using system_profiler on macOS
try:
# Execute the command to get video devices
result = subprocess.run(
["system_profiler", "SPCameraDataType"],
stdout=subprocess.PIPE,
text=True
)
output = result.stdout

# Search for camera names in the output
lines = output.split("\n")
camera_index = 0
for line in lines:
if "Model ID:" in line or "Camera Model ID:" in line: # Check for the model name
camera_name = line.split(":")[1].strip()
available_cameras[camera_index] = camera_name
camera_index += 1

except Exception as e:
print(f"Error while retrieving cameras: {e}")

return available_cameras

Expand Down Expand Up @@ -50,22 +76,26 @@ def window_tracking_configuration():

def get_configuration():
""" Retrieves configuration values from UI form """
camera_name = camera_selection.get()
camera_index = camera_options.index(camera_name)

port = api_port_entry.get()
api_port = api_port_entry.get()
camera_url = camera_url_entry.get()

settings = {
'camera_id': available_cameras[camera_index]['id'],
'camera_url': camera_url,
'preview_enabled': show_camera_view_var.get(),
'port': port if port else 8001
'port': api_port if api_port else 8001
}

if available_cameras:
camera_name = camera_selection.get()
camera_index = camera_options.index(camera_name)
settings['camera_id'] = available_cameras[camera_index]['id']

return settings

root = tk.Tk()
root.title(f"VTS Fullbody Tracking {VERSION} - Settings")
root.geometry("340x340")
root.geometry("340x380")
root.configure(bg='#333333')

icon_path = os.path.abspath(os.path.join(os.path.dirname(__file__), ICON_PATH))
Expand Down Expand Up @@ -104,34 +134,41 @@ def get_configuration():
camera_selection = ttk.Combobox(root, values=camera_options, state='readonly', font=('Arial', 10))
camera_selection.current(0)
camera_selection.pack(pady=(10, 5), padx=20, fill=tk.X)

# Option for showing original input when displaying tracking pose
show_camera_view_var = tk.BooleanVar()
show_camera_view_checkbox = tk.Checkbutton(root, text="Show Camera View", variable=show_camera_view_var, bg='#333333', fg='white', activeforeground='white', activebackground="#333333", selectcolor='black', font=('Arial', 10))
show_camera_view_checkbox.pack(anchor='w', padx=20, pady=(0, 10))

# -- Vtube Studio Settings
vtube_studio_frame = create_section_header(root, "Vtube Studio Settings")
vtube_studio_frame.pack(fill=tk.X, pady=(0, 5))

# Custom Port Entry
api_port_frame = tk.Frame(root, bg='#333333')
api_port_frame.pack(pady=(10, 20), padx=20, fill=tk.X)
api_port_label = tk.Label(api_port_frame, text="API Port:", bg='#333333', fg='white', font=('Arial', 10))
api_port_label.pack(side=tk.LEFT, padx=5)
vcmd = root.register(validate_port_input)
api_port_entry = tk.Entry(api_port_frame, validate="key", validatecommand=(vcmd, '%P'), font=('Arial', 10), width=10)
api_port_entry.insert(0, "8001")
api_port_entry.pack(side=tk.LEFT, fill=tk.X)

# -- Start Tracking Button
start_tracking_button = tk.Button(root, text="Start Tracking", command=root.quit, font=('Arial', 14, 'bold'), bg='#07121d', fg='white', activebackground='#3c9fbb', activeforeground='white', bd=0)
start_tracking_button.pack(pady=(5, 20), padx=20, fill=tk.X)

else:
camera_label = tk.Label(root, text="No camera found\n Connect a camera before running the plugin")
camera_label.pack()

# Camera external connection
camera_url_frame = tk.Frame(root, bg='#333333')
camera_url_frame.pack(pady=(10, 20), padx=20, fill=tk.X)
camera_url_label = tk.Label(camera_url_frame, text="Camera url", bg='#333333', fg='white', font=('Arial', 10))
camera_url_label.pack(side=tk.LEFT, padx=5)
camera_url_entry = tk.Entry(camera_url_frame, validate="key", font=('Arial', 10), width=30)
camera_url_entry.pack(side=tk.LEFT, fill=tk.X)

# Option for showing original input when displaying tracking pose
show_camera_view_var = tk.BooleanVar()
show_camera_view_checkbox = tk.Checkbutton(root, text="Show Camera View", variable=show_camera_view_var, bg='#333333', fg='white', activeforeground='white', activebackground="#333333", selectcolor='black', font=('Arial', 10))
show_camera_view_checkbox.pack(anchor='w', padx=20, pady=(0, 10))

# -- Vtube Studio Settings
vtube_studio_frame = create_section_header(root, "Vtube Studio Settings")
vtube_studio_frame.pack(fill=tk.X, pady=(0, 5))

# Custom Port Entry
api_port_frame = tk.Frame(root, bg='#333333')
api_port_frame.pack(pady=(10, 20), padx=20, fill=tk.X)
api_port_label = tk.Label(api_port_frame, text="API Port:", bg='#333333', fg='white', font=('Arial', 10))
api_port_label.pack(side=tk.LEFT, padx=5)
vcmd = root.register(validate_port_input)
api_port_entry = tk.Entry(api_port_frame, validate="key", validatecommand=(vcmd, '%P'), font=('Arial', 10), width=10)
api_port_entry.insert(0, "8001")
api_port_entry.pack(side=tk.LEFT, fill=tk.X)

# -- Start Tracking Button
start_tracking_button = tk.Button(root, text="Start Tracking", command=root.quit, font=('Arial', 14, 'bold'), bg='#07121d', fg='white', activebackground='#3c9fbb', activeforeground='white', bd=0)
start_tracking_button.pack(pady=(5, 20), padx=20, fill=tk.X)

root.mainloop()

tracking_configuration = get_configuration()
Expand Down
40 changes: 40 additions & 0 deletions plugin/vtube_studio.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from .mediapipe import get_parameters_names

from debug import start_timer, stop_timer


async def connection_vts(vts):
# Initialize VTube Studio connection
await vts.connect()

# Authenticate with VTube Studio API
# print('authentification VtubeStudio..')
await vts.request_authenticate_token() # get token
await vts.request_authenticate() # use token

# TODO: Error Message if Vtube Studio not open
# TODO: Error Message if Port cant connect


async def create_parameters_vts(vts):
start_time = start_timer()

# print('Create parameters in VTube Studio')

# Prepare parameter names for each body part
parameter_names = get_parameters_names()

# Maximum of 100 parameters allowed to be created in VTube Studio per plugin
for parameter_name in parameter_names:
# Add custom parameters in VTube Studio
send_request_new_parameter = vts.vts_request.requestCustomParameter(parameter_name, min=-10, max=10)
await vts.request(send_request_new_parameter)

stop_timer(start_time, 'create parameters in vts')


async def send_paramters_vts(vts, values, names):
""" parameters in VTube Studio """

send_request_parameter = vts.vts_request.requestSetMultiParameterValue(names, values, weight=1, face_found=True, mode='set')
await vts.request(send_request_parameter)

0 comments on commit 69508b2

Please sign in to comment.