Interactive GUI toolkit for robotics visualization - Python & C++, runs on desktop and web

Hi everyone,

I’d like to share Dear ImGui Bundle, an open-source framework for building interactive GUI applications in Python and C++. It wraps Dear ImGui with 23 integrated libraries (plotting, image inspection, node editors, 3D gizmos, etc.) and runs on desktop, mobile, and web.

I’m a solo developer and have been working hard on this for 4 years. I am new here, but I thought it might be useful for robotics developers.

It provides:

Real-time visualization

  • ImPlot and ImPlot3D for sensor data, trajectories, live plots at 60fps (or even 120fps)
  • ImmVision for camera feed inspection with zoom, pan, pixel values, and colormaps
  • All GPU-accelerated (OpenGL/Metal/Vulkan)

Interactive parameter tuning

  • Immediate mode means your UI code is just a few lines of Python or C++
  • Sliders, knobs, toggles, color pickers - all update in real time
  • No callbacks, no widget trees, no framework boilerplate

Cross-platform deployment

  • Same code runs on Linux, macOS, Windows
  • Python apps can run in the browser via Pyodide (useful for sharing dashboards without requiring install)
  • C++ apps compile to WebAssembly via Emscripten

Example: live camera + Laplacian filter with colormaps in 54 lines

import cv2
import numpy as np
from imgui_bundle import imgui, immvision, immapp


class AppState:
    def __init__(self):
        self.cap = cv2.VideoCapture(0)
        self.image = None
        self.filtered = None
        self.blur_sigma = 2.0
        # ImmVision params
        # For the camera image
        self.params_image = immvision.ImageParams()
        self.params_image.image_display_size = (400, 0)
        self.params_image.zoom_key = "cam"
        # For the filtered image (synced zoom via zoom_key)
        self.params_filter = immvision.ImageParams()
        self.params_filter.image_display_size = (400, 0)
        self.params_filter.zoom_key = "cam"
        self.params_filter.show_options_panel = True


def gui(s: AppState):
    # grab
    has_image, frame = s.cap.read()
    if has_image:
        s.image = cv2.resize(frame, (640, 480))
        gray = cv2.cvtColor(s.image, cv2.COLOR_BGR2GRAY)
        gray_f = gray.astype(np.float64) / 255.0
        blurred = cv2.GaussianBlur(gray_f, (0, 0), s.blur_sigma)
        s.filtered = cv2.Laplacian(blurred, cv2.CV_64F, ksize=5)

    # Refresh images only if needed
    s.params_image.refresh_image = has_image
    s.params_filter.refresh_image = has_image

    if s.image is not None:
        immvision.image("Camera", s.image, s.params_image)
        imgui.same_line()
        immvision.image("Filtered", s.filtered, s.params_filter)

    # Controls
    _, s.blur_sigma = imgui.slider_float("Blur", s.blur_sigma, 0.5, 10.0)


state = AppState()
immvision.use_bgr_color_order()
immapp.run(lambda: gui(state), window_size=(1200, 550), window_title="Camera Filter", fps_idle=0)

The filtered image is float64 - click “Options” to try different colormaps (Heat, Jet, Viridis…). Both views are zoom-linked: pan one, the other follows.

Try it:

Install: pip install imgui-bundle

Adoption:
The framework is used in several research projects, including CVPR 2024 papers (4K4D), Newton Physics, and moderngl. The Python bindings are auto-generated with litgen, so they stay in sync with upstream Dear ImGui.

Happy to answer any questions or discuss how it could fit into ROS workflows.

Best,
Pascal

2 Likes