Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # tk_Pose_Guide_Canvas.py
- import tkinter as tk
- import math
- root = tk.Tk()
- root.title("Pose Guide Canvas")
- canvas = tk.Canvas(root, width=400, height=500, bg="white")
- canvas.pack()
- orig_joints = {
- "head": [200, 60, 0],
- "neck": [200, 100, 0],
- "r_shoulder": [165, 105, 0], "l_shoulder": [235, 105, 0],
- "r_elbow": [140, 170, 0], "l_elbow": [260, 170, 0],
- "r_wrist": [125, 235, 0], "l_wrist": [275, 235, 0],
- "pelvis": [200, 250, 0],
- "r_hip": [175, 255, 0], "l_hip": [225, 255, 0],
- "r_knee": [165, 350, 0], "l_knee": [235, 350, 0],
- "r_ankle": [155, 450, 0], "l_ankle": [245, 450, 0]
- }
- joints = {k: list(v) for k, v in orig_joints.items()}
- bones = [
- ("neck", "r_shoulder"), ("neck", "l_shoulder"),
- ("r_shoulder", "r_elbow"), ("l_shoulder", "l_elbow"),
- ("r_elbow", "r_wrist"), ("l_elbow", "l_wrist"),
- ("neck", "pelvis"), ("pelvis", "r_hip"), ("pelvis", "l_hip"),
- ("r_hip", "r_knee"), ("l_hip", "l_knee"),
- ("r_knee", "r_ankle"), ("l_knee", "l_ankle"),
- ("head", "neck")
- ]
- lengths = {
- (u, v): math.hypot(
- joints[u][0] - joints[v][0],
- joints[u][1] - joints[v][1]
- )
- for u, v in bones
- }
- lengths.update({(v, u): l for (u, v), l in lengths.items()})
- sel = [None]
- def draw():
- canvas.delete("all")
- for b1, b2 in bones:
- canvas.create_line(
- joints[b1][0], joints[b1][1],
- joints[b2][0], joints[b2][1],
- fill="#2c3e50",
- width=4
- )
- canvas.create_oval(
- joints["head"][0] - 20,
- joints["head"][1] - 20,
- joints["head"][0] + 20,
- joints["head"][1] + 20,
- fill="#3498db",
- outline="#2c3e50",
- width=2
- )
- for k, p in joints.items():
- if k != "head":
- canvas.create_oval(
- p[0] - 6, p[1] - 6,
- p[0] + 6, p[1] + 6,
- fill="#e74c3c",
- outline="#c0392b"
- )
- def click(e):
- sel[0] = None
- for k, p in joints.items():
- r = 20 if k == "head" else 8
- if math.hypot(e.x - p[0], e.y - p[1]) < r:
- sel[0] = k
- break
- def drag(e):
- curr = sel[0]
- if not curr:
- return
- joints[curr] = [
- max(10, min(390, e.x)),
- max(10, min(490, e.y))
- ]
- for _ in range(5):
- for u, v in list(lengths.keys()):
- dx = joints[v][0] - joints[u][0]
- dy = joints[v][1] - joints[u][1]
- dist = math.hypot(dx, dy) or 1
- diff = (lengths[(u, v)] - dist) / dist * 0.5
- if v == curr:
- joints[u][0] -= dx * diff * 2
- joints[u][1] -= dy * diff * 2
- elif u == curr:
- joints[v][0] += dx * diff * 2
- joints[v][1] += dy * diff * 2
- else:
- joints[u][0] -= dx * diff
- joints[u][1] -= dy * diff
- joints[v][0] += dx * diff
- joints[v][1] += dy * diff
- draw()
- def rotate(e):
- deg = 10 if e.keysym in ("Right", "Down") else -10
- rad = math.radians(deg)
- cx, cy, cz = joints["pelvis"]
- cos_a = math.cos(rad)
- sin_a = math.sin(rad)
- for k, p in joints.items():
- if k == "pelvis":
- continue
- x = p[0] - cx
- y = p[1] - cy
- z = p[2] - cz
- if e.keysym in ("Left", "Right"):
- nx = x * cos_a + z * sin_a
- nz = -x * sin_a + z * cos_a
- ny = y
- else:
- nx = x
- ny = y * cos_a - z * sin_a
- nz = y * sin_a + z * cos_a
- joints[k] = [
- max(10, min(390, cx + nx)),
- max(10, min(490, cy + ny)),
- nz + cz
- ]
- draw()
- def reset_rig():
- for k, v in orig_joints.items():
- joints[k] = list(v)
- draw()
- def copy_coords():
- txt = "\n".join(f"{k}: {v}" for k, v in joints.items())
- root.clipboard_clear()
- root.clipboard_append(txt)
- root.update()
- def copy_img():
- try:
- from PIL import ImageGrab
- import io
- import win32clipboard
- root.update()
- x = root.winfo_rootx() + canvas.winfo_x()
- y = root.winfo_rooty() + canvas.winfo_y()
- w = canvas.winfo_width()
- h = canvas.winfo_height()
- img = ImageGrab.grab(
- bbox=(x, y, x + w, y + h)
- )
- output = io.BytesIO()
- img.convert("RGBA").save(output, format="BMP")
- data = output.getvalue()[14:]
- output.close()
- win32clipboard.OpenClipboard()
- win32clipboard.EmptyClipboard()
- win32clipboard.SetClipboardData(
- win32clipboard.CF_DIB,
- data
- )
- win32clipboard.CloseClipboard()
- except:
- canvas.postscript(
- file="pose.ps",
- colormode="color"
- )
- btn_frame = tk.Frame(root)
- btn_frame.pack(fill="x", padx=5, pady=5)
- tk.Button(
- btn_frame,
- text="Reset Rig",
- command=reset_rig
- ).pack(side="left", expand=True, fill="x")
- tk.Button(
- btn_frame,
- text="Copy Coords",
- command=copy_coords
- ).pack(side="left", expand=True, fill="x")
- tk.Button(
- btn_frame,
- text="Copy Image",
- command=copy_img
- ).pack(side="left", expand=True, fill="x")
- canvas.bind("<Button-1>", click)
- canvas.bind("<B1-Motion>", drag)
- root.bind("<Left>", rotate)
- root.bind("<Right>", rotate)
- root.bind("<Up>", rotate)
- root.bind("<Down>", rotate)
- draw()
- root.mainloop()
Add Comment
Please, Sign In to add comment