{"id":19525445,"url":"https://github.com/trflorian/ball-tracking-live-plot","last_synced_at":"2025-04-16T04:25:25.321Z","repository":{"id":261698628,"uuid":"885077308","full_name":"trflorian/ball-tracking-live-plot","owner":"trflorian","description":"Tracking a ball using OpenCV and plotting the trajectory using Matplotlib","archived":false,"fork":false,"pushed_at":"2025-03-06T23:00:18.000Z","size":10621,"stargazers_count":20,"open_issues_count":0,"forks_count":3,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-29T04:51:15.402Z","etag":null,"topics":["computer-vision","matplotlib","opencv","python"],"latest_commit_sha":null,"homepage":"https://medium.com/@flip.flo.dev/animated-plotting-in-python-with-opencv-and-matplotlib-d640462c41f4","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/trflorian.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-07T23:06:24.000Z","updated_at":"2025-03-26T00:23:02.000Z","dependencies_parsed_at":"2024-11-08T00:19:01.593Z","dependency_job_id":"4a586f0c-948b-4495-b344-f53f076b806d","html_url":"https://github.com/trflorian/ball-tracking-live-plot","commit_stats":null,"previous_names":["trflorian/ball-tracking-live-plot"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trflorian%2Fball-tracking-live-plot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trflorian%2Fball-tracking-live-plot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trflorian%2Fball-tracking-live-plot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/trflorian%2Fball-tracking-live-plot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/trflorian","download_url":"https://codeload.github.com/trflorian/ball-tracking-live-plot/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249194725,"owners_count":21228044,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["computer-vision","matplotlib","opencv","python"],"created_at":"2024-11-11T01:04:30.592Z","updated_at":"2025-04-16T04:25:25.312Z","avatar_url":"https://github.com/trflorian.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ball Tracking with Live Trajectory Visualization\n\n![Python](https://img.shields.io/badge/python-3.13-blue.svg)\n![GitHub License](https://img.shields.io/github/license/trflorian/ball-tracking-live-plot?style=flat)\n[![ci](https://github.com/trflorian/ball-tracking-live-plot/actions/workflows/ci.yaml/badge.svg)](https://github.com/trflorian/ball-tracking-live-plot/actions/workflows/ci.yaml)\n\n\nIn this project I showcase how you can create an animated plot with OpenCV and Matplotlib. To demonstrate the real-time animated plotting, I am tracking a ball that is thrown vertically into the air. The ball's vertical position, velocity and acceleration are plotted in the figure. Polynomial functions are used to fit a model to the motion of the ball and predict its trajectory.\n\n![Screencastfrom01 01 2025220355-ezgif com-video-to-gif-converter](https://github.com/user-attachments/assets/71c5818b-cac9-44b4-99dd-9a10355433ea)\n\n## 🌟 Quickstart\n\nThis project uses [uv](https://docs.astral.sh/uv/getting-started/installation/) for setup. Simply run the `tracking.py` or `trajectory.py` script with uv to get started!\n\n### Streaming Track Demo\n```Shell\nuv run tracking\n```\n### Trajectory Tracking\n```Shell\nuv run trajectory\n```\n\n## 📈 Matplotlib + OpenCV\n\nTo get a plot/figure from matplotlib into OpenCV, I render the canvas into a buffer in memory, store the buffer in a numpy array and transform it to the correct BGR format to display in OpenCV.\n\n```Python\nfig.canvas.draw()\n\nbuf = fig.canvas.buffer_rgba()\nplot = np.asarray(buf)\nplot = cv2.cvtColor(plot, cv2.COLOR_RGB2BGR)\n```\n\n## 🎨 Blitting\nThe naive draw call in matplotlib as shown above is quite expensive, the full figure needs to be re-drawn every frame. To improve the performance, I make use of a technique called [blitting](https://matplotlib.org/stable/users/explain/animations/blitting.html). \nThis allows me to only re-draw regions that have changed and therefore drastically redducing the rendering time.\n\n```Python\nfig, axs = plt.subplots(nrows=1, ncols=3, figsize=(10, 2), dpi=100)\n\n...\n\n# initialize empty plots\npl_pos = axs[0].plot([], [], c=\"b\")[0]\npl_vel = axs[1].plot([], [], c=\"b\")[0]\npl_acc = axs[2].plot([], [], c=\"b\")[0]\n\n# draw initial backgrounds\nfig.canvas.draw()\nbg_axs = [fig.canvas.copy_from_bbox(ax.bbox) for ax in axs]\n\nwhile True:\n  ...\n\n  # Update plots\n  pl_pos.set_data(range(len(pos)), pos)\n  pl_vel.set_data(range(len(vel)), vel)\n  pl_acc.set_data(range(len(acc)), acc)\n  \n  # Blit Pos\n  fig.canvas.restore_region(bg_axs[0])\n  axs[0].draw_artist(pl_pos)\n  fig.canvas.blit(axs[0].bbox)\n  \n  # Blit Vel\n  fig.canvas.restore_region(bg_axs[1])\n  axs[1].draw_artist(pl_vel)\n  fig.canvas.blit(axs[1].bbox)\n  \n  # Blit Acc\n  fig.canvas.restore_region(bg_axs[2])\n  axs[2].draw_artist(pl_acc)\n  fig.canvas.blit(axs[2].bbox)\n\n  # show plot, cv2.waitKey etc.\n  ...\n```\n\n## 🎭 Visualization of the Masks\n![Screencastfrom11-07-2024103538PM-ezgif com-cut](https://github.com/user-attachments/assets/9209500a-94f4-4670-be64-c332dc839801)\n\n\n## 🔮 Trajectory Prediction\nBased on a simple physics model with constant acceleration equal to the gravitational acceleration, the ball's position, velocity and acceleration plots are polynomial functions of degree 2, 1 and 0.\nTo calculate the polynomial factors, the polyfit numpy function is used. Then the polynomials are evaluated for each step in the timeframe and plotted on top of the tracked state of the ball.\n\n```Python\npoly_pos = np.polyfit(t_pos, pos, deg=2)\npoly_vel = np.polyfit(t_vel, vel, deg=1)\npoly_acc = np.polyfit(t_acc, acc, deg=0)\n\nt_pred = np.arange(num_frames + 5)\n\npolyval_pos = np.polyval(poly_pos, t_pred)\npolyval_vel = np.polyval(poly_vel, t_pred)\npolyval_acc = np.polyval(poly_acc, t_pred)\n```\n\n![image](https://github.com/user-attachments/assets/fb7c6d32-0a01-4d67-8e8e-454002128f15)\n\n## 🎥 Streaming Trajectory\n\nCheck `src/stream.py` on how to use `deque` from `collections` to create a fixed-length buffer of trajectory points.\n\n![2025-01-26_17-18-11-ezgif com-optimize](https://github.com/user-attachments/assets/d5a91971-5df9-4777-9c66-854934e180de)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrflorian%2Fball-tracking-live-plot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftrflorian%2Fball-tracking-live-plot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftrflorian%2Fball-tracking-live-plot/lists"}