here2share

# tk_Pose_Guide_Canvas.py

Aug 31st, 2026
53
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.56 KB | None | 0 0
  1. # tk_Pose_Guide_Canvas.py
  2.  
  3. import tkinter as tk
  4. import math
  5.  
  6. root = tk.Tk()
  7. root.title("Pose Guide Canvas")
  8.  
  9. canvas = tk.Canvas(root, width=400, height=500, bg="white")
  10. canvas.pack()
  11.  
  12. orig_joints = {
  13.     "head": [200, 60, 0],
  14.     "neck": [200, 100, 0],
  15.     "r_shoulder": [165, 105, 0], "l_shoulder": [235, 105, 0],
  16.     "r_elbow": [140, 170, 0], "l_elbow": [260, 170, 0],
  17.     "r_wrist": [125, 235, 0], "l_wrist": [275, 235, 0],
  18.     "pelvis": [200, 250, 0],
  19.     "r_hip": [175, 255, 0], "l_hip": [225, 255, 0],
  20.     "r_knee": [165, 350, 0], "l_knee": [235, 350, 0],
  21.     "r_ankle": [155, 450, 0], "l_ankle": [245, 450, 0]
  22. }
  23.  
  24. joints = {k: list(v) for k, v in orig_joints.items()}
  25.  
  26. bones = [
  27.     ("neck", "r_shoulder"), ("neck", "l_shoulder"),
  28.     ("r_shoulder", "r_elbow"), ("l_shoulder", "l_elbow"),
  29.     ("r_elbow", "r_wrist"), ("l_elbow", "l_wrist"),
  30.     ("neck", "pelvis"), ("pelvis", "r_hip"), ("pelvis", "l_hip"),
  31.     ("r_hip", "r_knee"), ("l_hip", "l_knee"),
  32.     ("r_knee", "r_ankle"), ("l_knee", "l_ankle"),
  33.     ("head", "neck")
  34. ]
  35.  
  36. lengths = {
  37.     (u, v): math.hypot(
  38.         joints[u][0] - joints[v][0],
  39.         joints[u][1] - joints[v][1]
  40.     )
  41.     for u, v in bones
  42. }
  43.  
  44. lengths.update({(v, u): l for (u, v), l in lengths.items()})
  45.  
  46. sel = [None]
  47.  
  48. def draw():
  49.     canvas.delete("all")
  50.  
  51.     for b1, b2 in bones:
  52.         canvas.create_line(
  53.             joints[b1][0], joints[b1][1],
  54.             joints[b2][0], joints[b2][1],
  55.             fill="#2c3e50",
  56.             width=4
  57.         )
  58.  
  59.     canvas.create_oval(
  60.         joints["head"][0] - 20,
  61.         joints["head"][1] - 20,
  62.         joints["head"][0] + 20,
  63.         joints["head"][1] + 20,
  64.         fill="#3498db",
  65.         outline="#2c3e50",
  66.         width=2
  67.     )
  68.  
  69.     for k, p in joints.items():
  70.         if k != "head":
  71.             canvas.create_oval(
  72.                 p[0] - 6, p[1] - 6,
  73.                 p[0] + 6, p[1] + 6,
  74.                 fill="#e74c3c",
  75.                 outline="#c0392b"
  76.             )
  77.  
  78. def click(e):
  79.     sel[0] = None
  80.  
  81.     for k, p in joints.items():
  82.         r = 20 if k == "head" else 8
  83.  
  84.         if math.hypot(e.x - p[0], e.y - p[1]) < r:
  85.             sel[0] = k
  86.             break
  87.  
  88. def drag(e):
  89.     curr = sel[0]
  90.  
  91.     if not curr:
  92.         return
  93.  
  94.     joints[curr] = [
  95.         max(10, min(390, e.x)),
  96.         max(10, min(490, e.y))
  97.     ]
  98.  
  99.     for _ in range(5):
  100.         for u, v in list(lengths.keys()):
  101.             dx = joints[v][0] - joints[u][0]
  102.             dy = joints[v][1] - joints[u][1]
  103.  
  104.             dist = math.hypot(dx, dy) or 1
  105.  
  106.             diff = (lengths[(u, v)] - dist) / dist * 0.5
  107.  
  108.             if v == curr:
  109.                 joints[u][0] -= dx * diff * 2
  110.                 joints[u][1] -= dy * diff * 2
  111.  
  112.             elif u == curr:
  113.                 joints[v][0] += dx * diff * 2
  114.                 joints[v][1] += dy * diff * 2
  115.  
  116.             else:
  117.                 joints[u][0] -= dx * diff
  118.                 joints[u][1] -= dy * diff
  119.                 joints[v][0] += dx * diff
  120.                 joints[v][1] += dy * diff
  121.  
  122.     draw()
  123.  
  124. def rotate(e):
  125.     deg = 10 if e.keysym in ("Right", "Down") else -10
  126.     rad = math.radians(deg)
  127.  
  128.     cx, cy, cz = joints["pelvis"]
  129.  
  130.     cos_a = math.cos(rad)
  131.     sin_a = math.sin(rad)
  132.  
  133.     for k, p in joints.items():
  134.         if k == "pelvis":
  135.             continue
  136.  
  137.         x = p[0] - cx
  138.         y = p[1] - cy
  139.         z = p[2] - cz
  140.  
  141.         if e.keysym in ("Left", "Right"):
  142.             nx = x * cos_a + z * sin_a
  143.             nz = -x * sin_a + z * cos_a
  144.             ny = y
  145.  
  146.         else:
  147.             nx = x
  148.             ny = y * cos_a - z * sin_a
  149.             nz = y * sin_a + z * cos_a
  150.  
  151.         joints[k] = [
  152.             max(10, min(390, cx + nx)),
  153.             max(10, min(490, cy + ny)),
  154.             nz + cz
  155.         ]
  156.  
  157.     draw()
  158.  
  159. def reset_rig():
  160.     for k, v in orig_joints.items():
  161.         joints[k] = list(v)
  162.  
  163.     draw()
  164.  
  165. def copy_coords():
  166.     txt = "\n".join(f"{k}: {v}" for k, v in joints.items())
  167.  
  168.     root.clipboard_clear()
  169.     root.clipboard_append(txt)
  170.     root.update()
  171.  
  172. def copy_img():
  173.     try:
  174.         from PIL import ImageGrab
  175.         import io
  176.         import win32clipboard
  177.  
  178.         root.update()
  179.  
  180.         x = root.winfo_rootx() + canvas.winfo_x()
  181.         y = root.winfo_rooty() + canvas.winfo_y()
  182.  
  183.         w = canvas.winfo_width()
  184.         h = canvas.winfo_height()
  185.  
  186.         img = ImageGrab.grab(
  187.             bbox=(x, y, x + w, y + h)
  188.         )
  189.  
  190.         output = io.BytesIO()
  191.         img.convert("RGBA").save(output, format="BMP")
  192.  
  193.         data = output.getvalue()[14:]
  194.         output.close()
  195.  
  196.         win32clipboard.OpenClipboard()
  197.         win32clipboard.EmptyClipboard()
  198.         win32clipboard.SetClipboardData(
  199.             win32clipboard.CF_DIB,
  200.             data
  201.         )
  202.         win32clipboard.CloseClipboard()
  203.  
  204.     except:
  205.         canvas.postscript(
  206.             file="pose.ps",
  207.             colormode="color"
  208.         )
  209.  
  210. btn_frame = tk.Frame(root)
  211. btn_frame.pack(fill="x", padx=5, pady=5)
  212.  
  213. tk.Button(
  214.     btn_frame,
  215.     text="Reset Rig",
  216.     command=reset_rig
  217. ).pack(side="left", expand=True, fill="x")
  218.  
  219. tk.Button(
  220.     btn_frame,
  221.     text="Copy Coords",
  222.     command=copy_coords
  223. ).pack(side="left", expand=True, fill="x")
  224.  
  225. tk.Button(
  226.     btn_frame,
  227.     text="Copy Image",
  228.     command=copy_img
  229. ).pack(side="left", expand=True, fill="x")
  230.  
  231. canvas.bind("<Button-1>", click)
  232. canvas.bind("<B1-Motion>", drag)
  233.  
  234. root.bind("<Left>", rotate)
  235. root.bind("<Right>", rotate)
  236. root.bind("<Up>", rotate)
  237. root.bind("<Down>", rotate)
  238.  
  239. draw()
  240. root.mainloop()
Add Comment
Please, Sign In to add comment