PoseAI / PoseCameraAPI

Tools to work with the Pose Camera app
Apache License 2.0
146 stars 38 forks source link

Python for Blender Help #22

Closed saibai closed 1 year ago

saibai commented 1 year ago

hi I'm trying to implement the ability to move the head in Blender, I wanted to know if it is correct, since it gives me errors, the quaternion values to insert in the code, can you help me, thanks

import json import socket import bpy import mathutils

PORT_NUM = 8095

''' Prints your local IP address. Configure this in the App. Make sure your router and firewall do not block the port ''' def show_my_ip(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.connect(('10.255.255.255', 1)) ip = s.getsockname()[0] except Exception: ip = '127.0.0.1' finally: s.close() print("Connect the app to IP:", ip, "Port:", PORT_NUM)

The handshake configures the app

handshake = json.dumps( { 'HANDSHAKE': { 'name': 'Blender', # will be displayed in the app 'rig': 'UE4', # Options: 'UE4', 'Mixamo' 'mode': 'Desktop', # Options: 'Room', 'Desktop', 'Portrait', 'RoomBodyOnly', 'PortraitBodyOnly' 'mirror': 'YES', # Options: 'YES', 'NO' 'syncFPS': 60, # App smooths processed frames to constant FPS. 0 for async mode (will still smooth joints between processed frames) 'cameraFPS': 60, # Tries to set camera to this speed. 30 and 60 work on most iphone cameras } } ).encode()

show_my_ip()

connections = {} server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_socket.bind(('0.0.0.0', PORT_NUM))

while True: message, address = server_socket.recvfrom(65304) message = message.decode('utf-8')

decoded_message = json.loads(message)

if 'sessionUUID' in decoded_message.keys():
    # is initial connection, send it the handshake
    print(decoded_message, address)
    connections[decoded_message['sessionUUID']] = address
    server_socket.sendto(handshake, address)
else:
    # is data frame, update bone rotation
    head_rotation = decoded_message['Body']['Rotations']['head']

    bpy.data.objects["Armature"].pose.bones["head"].rotation_quaternion = head_rotation
PoseAI commented 1 year ago

hi you didn't show us what the error was? we need more info to help.

what value are you getting for head_rotation? if it is not an array of numbers or you can't find 'head', try setting packetFormat=0 in the handshake for a verbose format, and then test the setting works by printing an incoming packet to console to make sure you can see the entire structure of rotations.

if the error is the rotation looks wrong, check the order of the quaternion. We pack them in the JSON packet as XYZW (i.e. scalar last), but I believe blender initializes by using WXYZ (i.e. scalar first), so you probably need to reorder the values.

On Tue, Jan 17, 2023 at 9:08 AM Diego Parbuono @.***> wrote:

hi I'm trying to implement the ability to move the head in Blender, I wanted to know if it is correct, since it gives me errors, the quaternion values to insert in the code, can you help me, thanks

import json import socket import bpy import mathutils

PORT_NUM = 8095

''' Prints your local IP address. Configure this in the App. Make sure your router and firewall do not block the port ''' def show_my_ip(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.connect(('10.255.255.255', 1)) ip = s.getsockname()[0] except Exception: ip = '127.0.0.1' finally: s.close() print("Connect the app to IP:", ip, "Port:", PORT_NUM) The handshake configures the app

handshake = json.dumps( { 'HANDSHAKE': { 'name': 'Blender', # will be displayed in the app 'rig': 'UE4', # Options: 'UE4', 'Mixamo' 'mode': 'Desktop', # Options: 'Room', 'Desktop', 'Portrait', 'RoomBodyOnly', 'PortraitBodyOnly' 'mirror': 'YES', # Options: 'YES', 'NO' 'syncFPS': 60, # App smooths processed frames to constant FPS. 0 for async mode (will still smooth joints between processed frames) 'cameraFPS': 60, # Tries to set camera to this speed. 30 and 60 work on most iphone cameras } } ).encode()

show_my_ip()

connections = {} server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_socket.bind(('0.0.0.0', PORT_NUM))

while True: message, address = server_socket.recvfrom(65304) message = message.decode('utf-8')

decoded_message = json.loads(message)

if 'sessionUUID' in decoded_message.keys():

is initial connection, send it the handshake

print(decoded_message, address)
connections[decoded_message['sessionUUID']] = address
server_socket.sendto(handshake, address)

else:

is data frame, update bone rotation

head_rotation = decoded_message['Body']['Rotations']['head']

bpy.data.objects["Armature"].pose.bones["head"].rotation_quaternion = head_rotation

— Reply to this email directly, view it on GitHub https://github.com/PoseAI/PoseCameraAPI/issues/22, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOGO6DDUU3DEXCK47T3KRELWSZORBANCNFSM6AAAAAAT5TEOUM . You are receiving this because you are subscribed to this thread.Message ID: @.***>

-- Pose AI - 'Understanding bodies in motion'

NOTE: These emails are for discussion purposes only. Unless and until we agree and sign a written License Agreement, our email exchanges do not constitute a binding contract, or a commitment by Pose AI Ltd or its employees to provide any software or services. We accept no liability, obligation or responsibility toward the recipient.

saibai commented 1 year ago

Congratulations for this work, I think it's the best Mocap I know, I've tried many, and I hope soon it will be implemented in Blender, it would be super useful for many animators;-)

Thanks for your reply, the error it gives me is: Python: Traceback (most recent call last): File posecamera-VRM.blend/Text", line 59, in KeyError: 'Body'

maybe in this line I do something wrong: head_rotation = decoded_message['Body']['Rotations']['head'] because I don't have a return of quaternion values.

output gives me these values 'Body': {'Rotations': {'pelvis': [0.19, 0.676, 0.014, -0.712], 'spine_01': [0.19, 0.676, 0.014, -0.712], 'spine_02': [0.105, 0.692, 0.022, -0.714], 'spine_03': [0.084, 0.688, -0.02, -0.721], 'neck_01': [0.084, 0.701, -0.158, -0.691], 'head': [0.091, 0.684, -0.029, -0.723],.........etc

PoseAI commented 1 year ago

I can't replicate KeyError: 'Body' that you show, as that works fine. You are even showing as output the 'Body' field... however, when the phone doesn't detect the person it does not send empty fields, so you should check if the subfields exists before you use it. Something like:

if 'Body' in decoded_message.keys() and 'Rotations'in decoded_message['Body'].keys(): print(decoded_message['Body']['Rotations']['head'])

On Tue, Jan 17, 2023 at 2:11 PM Diego Parbuono @.***> wrote:

Congratulations for this work, I think it's the best Mocap I know, I've tried many, and I hope soon it will be implemented in Blender, it would be super useful for many animators;-)

Thanks for your reply, the error it gives me is: Python: Traceback (most recent call last): File posecamera-VRM.blend/Text", line 59, in KeyError: 'Body'

maybe in this line I do something wrong: head_rotation = decoded_message['Body']['Rotations']['head'] because I don't have a return of quaternion values.

output gives me these values 'Body': {'Rotations': {'pelvis': [0.19, 0.676, 0.014, -0.712], 'spine_01': [0.19, 0.676, 0.014, -0.712], 'spine_02': [0.105, 0.692, 0.022, -0.714], 'spine_03': [0.084, 0.688, -0.02, -0.721], 'neck_01': [0.084, 0.701, -0.158, -0.691], 'head': [0.091, 0.684, -0.029, -0.723],.........etc

— Reply to this email directly, view it on GitHub https://github.com/PoseAI/PoseCameraAPI/issues/22#issuecomment-1385485902, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOGO6DGCA743STQQBQFMT5LWS2R7LANCNFSM6AAAAAAT5TEOUM . You are receiving this because you commented.Message ID: @.***>

-- Pose AI - 'Understanding bodies in motion'

NOTE: These emails are for discussion purposes only. Unless and until we agree and sign a written License Agreement, our email exchanges do not constitute a binding contract, or a commitment by Pose AI Ltd or its employees to provide any software or services. We accept no liability, obligation or responsibility toward the recipient.

saibai commented 1 year ago

if I remove the "while true" from this code, the data arrives ;-) but then it stops and exits the code, otherwise Blender crashes

import json import socket import bpy import mathutils

PORT_NUM = 8207

''' Prints your local IP address. Configure this in the App. Make sure your router and firewall do not block the port ''' def show_my_ip(): s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.connect(('10.255.255.255', 1)) ip = s.getsockname()[0] except Exception: ip = '127.0.0.1' finally: s.close() print("Connect the app to IP:", ip, "Port:", PORT_NUM)

The handshake configures the app

handshake = json.dumps( { 'HANDSHAKE': { 'name': 'Blender', # will be displayed in the app 'PF': 0, 'rig': 'UE4', # Options: 'UE4', 'Mixamo' 'mode': 'Desktop', # Options: 'Room', 'Desktop', 'Portrait', 'RoomBodyOnly', 'PortraitBodyOnly' 'mirror': 'YES', # Options: 'YES', 'NO' 'syncFPS': 60, # App smooths processed frames to constant FPS. 0 for async mode (will still smooth joints between processed frames) 'cameraFPS': 60, # Tries to set camera to this speed. 30 and 60 work on most iphone cameras } } ).encode()

show_my_ip()

connections = {} server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server_socket.bind(('0.0.0.0', PORT_NUM))

while True: message, address = server_socket.recvfrom(65304) message = message.decode('utf-8')

decoded_message = json.loads(message)

if 'sessionUUID' in decoded_message.keys():
    # is initial connection, send it the handshake
    print(decoded_message, address)
    connections[decoded_message['sessionUUID']] = address
    server_socket.sendto(handshake, address)

if 'Body' in decoded_message.keys() and 'Rotations' in decoded_message['Body'].keys():
    head_rotations = decoded_message['Body']['Rotations']['head']

    # Use head_rotation to set rotation of head bone in Blender
    bpy.data.objects["Armature"].pose.bones["head"].rotation_quaternion = mathutils.Quaternion(head_rotations)

when i open the code in terminal, the quaternion data output is correct