Spaces:
Running
on
A10G
Running
on
A10G
from fastapi import FastAPI, File, UploadFile | |
import aiofiles | |
import uvicorn, os, io | |
import cv2, json, math | |
import numpy as np | |
from PIL import Image | |
from typing import List | |
from fastapi.middleware.cors import CORSMiddleware | |
origins = [ | |
"*" | |
] | |
app = FastAPI() | |
app.add_middleware( | |
CORSMiddleware, | |
allow_origins=origins, | |
allow_credentials=True, | |
allow_methods=["*"], | |
allow_headers=["*"], | |
) | |
vertices_list = ['leftUpperArm', | |
'rightUpperArm', | |
'leftLowerArm', | |
'rightLowerArm', | |
'leftHand', | |
'rightHand', | |
'leftUpperLeg', | |
'rightUpperLeg', | |
'leftLowerLeg', | |
'rightLowerLeg', | |
'leftFoot', | |
'rightFoot', | |
'head', | |
'upperChest'] | |
def process_depth_file(file_data): | |
image = Image.open(io.BytesIO(file_data)) | |
if image.mode != 'RGBA': | |
raise ValueError("Image is not in RGBA format") | |
data = np.array(image) | |
R = data[:, :, 0] | |
G = data[:, :, 1] | |
B = data[:, :, 2] | |
A = data[:, :, 3] | |
depth = (R + G / 256.0 + B / (256.0 * 256.0)) | |
depth[A == 0] = 5.0 | |
return depth | |
vertices_list = ['leftUpperArm', | |
'rightUpperArm', | |
'leftLowerArm', | |
'rightLowerArm', | |
'leftHand', | |
'rightHand', | |
'leftUpperLeg', | |
'rightUpperLeg', | |
'leftLowerLeg', | |
'rightLowerLeg', | |
'leftFoot', | |
'rightFoot', | |
'head', | |
'hips', | |
'spine'] | |
def backproject_to_3d(base_dir): | |
for fn in os.listdir(base_dir): | |
if fn.endswith(".json"): | |
pose_file = open(os.path.join(base_dir, fn), "r") | |
pose_dict = json.load(pose_file) | |
vertices = [] | |
joints_name = [] | |
for node_name in vertices_list: | |
joints_name.append(node_name) | |
v = pose_dict['node_array'][node_name] | |
vertices.append([v["world_position"]['x'], v["world_position"]['y'], v["world_position"]['z'], 1.0]) | |
vertices = np.array(vertices) | |
chest_v = vertices[12] * 2 / 3 + vertices[14] / 3 | |
vertices = np.concatenate([vertices[:13], [chest_v]], axis=0) | |
vertices = vertices[[12, 13, 0, 2, 4, 1, 3, 5, 6, 8, 10, 7, 9, 11]] | |
focal_length = 256 / np.tan(40 / 2 / 180 * np.pi) | |
ext = np.array(pose_dict["extrinsicMatrix"]["elements"]).reshape(4,4) | |
ext = np.linalg.inv(ext) | |
vertices = vertices @ ext | |
camera_v = vertices[...,:3] / vertices[...,3:] | |
camera_v = camera_v[...,:2] / camera_v[...,2:] * focal_length | |
camera_v += 256 | |
camera_v /= 512 | |
camera_v[:,0] = 1 - camera_v[:,0] | |
canvas = np.zeros((768, 768, 3), dtype=np.uint8) | |
#canvas = cv2.imread(os.path.join(base_dir, fn.replace(".json", "_rgb.png"))) | |
draw_bodypose(canvas, camera_v) | |
cv2.imwrite(os.path.join(base_dir, fn.replace(".json", "_pose.png")), cv2.cvtColor(canvas, cv2.COLOR_BGR2RGB)) | |
def draw_bodypose(canvas: np.ndarray, keypoints) -> np.ndarray: | |
H, W, C = canvas.shape | |
stickwidth = 4 | |
limbSeq = [ | |
[2, 3], [2, 6], [3, 4], [4, 5], | |
[6, 7], [7, 8], [2, 9], [9, 10], | |
[10, 11], [2, 12], [12, 13], [13, 14], | |
[2, 1], | |
] | |
colors = [[255, 0, 0], [255, 85, 0], [255, 170, 0], [255, 255, 0], [170, 255, 0], [85, 255, 0], [0, 255, 0], \ | |
[0, 255, 85], [0, 255, 170], [0, 255, 255], [0, 170, 255], [0, 85, 255], [0, 0, 255], [85, 0, 255], \ | |
[170, 0, 255], [255, 0, 255], [255, 0, 170], [255, 0, 85]] | |
for (k1_index, k2_index), color in zip(limbSeq, colors): | |
if k1_index-1 >= len(keypoints) or k2_index -1>= len(keypoints): | |
continue | |
keypoint1 = keypoints[k1_index - 1] | |
keypoint2 = keypoints[k2_index - 1] | |
if keypoint1 is None or keypoint2 is None: | |
continue | |
Y = np.array([keypoint1[0], keypoint2[0]]) * float(W) | |
X = np.array([keypoint1[1], keypoint2[1]]) * float(H) | |
mX = np.mean(X) | |
mY = np.mean(Y) | |
length = ((X[0] - X[1]) ** 2 + (Y[0] - Y[1]) ** 2) ** 0.5 | |
angle = math.degrees(math.atan2(X[0] - X[1], Y[0] - Y[1])) | |
polygon = cv2.ellipse2Poly((int(mY), int(mX)), (int(length / 2), stickwidth), int(angle), 0, 360, 1) | |
cv2.fillConvexPoly(canvas, polygon, [int(float(c) * 0.6) for c in color]) | |
for keypoint, color in zip(keypoints, colors): | |
if keypoint is None: | |
continue | |
x, y = keypoint | |
x = int(x * W) | |
y = int(y * H) | |
cv2.circle(canvas, (int(x), int(y)), 4, color, thickness=-1) | |
return canvas | |
count = 0 | |
async def create_upload_files(files: List[UploadFile] = File(...)): | |
global count | |
count += 1 | |
print(count) | |
for file in files: | |
object_name = file.filename.split("_")[0] | |
folder = f"E:/new_render/{object_name}" | |
if not os.path.exists(folder): | |
os.makedirs(folder) | |
file_data = await file.read() | |
if(file.filename.split('_')[-1].split('.')[0] == "depth"): | |
depth = process_depth_file(file_data) | |
cv2.imwrite(f"{folder}/{file.filename}", depth) | |
new_path = f"{folder}/{file.filename}" | |
numpy_path = new_path.replace(".png", ".npz") | |
np.savez_compressed(numpy_path, depth) | |
else: | |
with open(f"{folder}/{file.filename}", "wb") as buffer: | |
buffer.write(file_data) | |
backproject_to_3d(folder) | |
if __name__ == "__main__": | |
uvicorn.run(app, host="127.0.0.1", port=17070) |