{"$schema":"https://ejfox.com/schema/page-twin@1.json","kind":"project","url":"https://ejfox.com/projects/creative-interfaces","json_url":"https://ejfox.com/projects/creative-interfaces.json","generator":"ejfox.com/json-twin@1","data":{"cacheVersion":"2026-10-05-source-hash","sourceHash":"e4e3e5a9206fda139803f6cf1d9ef5c7a4f1f76a46fb44955abf004ac635b517","html":"<p class=\"\">These are my attempts to make computers that respond to the way humans actually move and gesture.</p>\n<p class=\"\">The other day I had this idea to try and control a modular synth using computer vision. I loaded YOLOv4 into a python script and had it detect objects in an episode of Atlanta I had lying around, sending the X and Y positions of every object as control voltage to the oscillators. It makes this weird, haunting, sort of robotic sound — but I kind of really like it. Then I had a fun idea to run it through the webcam, and I couldn't figure out why it wasn't working — I kept seeing the chair as an object. Then I figured it out: the chair is the instrument. Why did I make a chair an instrument? I don't know. I ended up running dance videos from Sherrie Silver, the This Is America choreographer, through it instead — not just the X and Y positions but the distances between the objects — and it comes up with some really cool, interesting generative effects. I don't really know how I use this right now, or what it's for exactly. That's kind of how I know it's art.</p>\n<p class=\"\">That session: <a href=\"https://www.youtube.com/watch?v=k2u--wFhcS4\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://www.youtube.com/watch?v=k2u--wFhcS4\">Using Computer Vision As A MIDI Controller<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M23.498 6.186a3.02 3.02 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.02 3.02 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.02 3.02 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.02 3.02 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814M9.545 15.568V8.432L15.818 12z\" class=\"\"></path></svg></a>.</p>\n<p class=\"\">The other end of the spectrum: no camera, no screen at all. I've been using Talon to control my computer, so I tried to do the dishes and code at the same time — talking to Claude while my hands were in the sink, having it answer everything out loud. There are some sharp edges — a couple times it didn't pick up everything I said — but the fact that you can detach from looking at a screen and still engage in the mechanical task of writing code and making things with a computer is completely radical. It's unlike anything I've ever experienced in my life.</p>\n<p class=\"\">That one's on video too: <a href=\"https://www.youtube.com/watch?v=381Wq9jYOGk\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://www.youtube.com/watch?v=381Wq9jYOGk\">Coding While I Do The Dishes<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M23.498 6.186a3.02 3.02 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.02 3.02 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.02 3.02 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.02 3.02 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814M9.545 15.568V8.432L15.818 12z\" class=\"\"></path></svg></a>.</p>\n<p class=\"\">See also <a href=\"/projects/flipper-zero-tools\" class=\"text-blue-600 dark:text-blue-400\">Flipper Zero Tools</a> and <a href=\"/projects/terminal-tools\" class=\"text-blue-600 dark:text-blue-400\">Terminal Tools</a>.</p>\n<h2 class=\"\" id=\"hand-tracking--gesture\">Hand-tracking &#x26; gesture</h2>\n<h3 class=\"\" id=\"hand-midi-controller\">Hand MIDI Controller</h3>\n<figure role=\"figure\" aria-label=\"Hand MIDI Controller — MediaPipe hand landmarks mapped to MIDI CC\" class=\"\">\n<img src=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/projects/hand-midi-controller/diagram.png\" alt=\"Hand MIDI Controller — MediaPipe hand landmarks mapped to MIDI CC\" loading=\"lazy\" decoding=\"async\" srcset=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_640/projects/hand-midi-controller/diagram.png 640w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_960/projects/hand-midi-controller/diagram.png 960w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/projects/hand-midi-controller/diagram.png 1280w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1920/projects/hand-midi-controller/diagram.png 1920w\" sizes=\"(max-width: 430px) 92vw, (max-width: 768px) 85vw, 900px\" title=\"Hand MIDI Controller — MediaPipe hand landmarks mapped to MIDI CC\" width=\"1956\" height=\"1306\" style=\"--splay-rot:2.54deg;\" data-dimensions=\"1956×1306\" class=\"img-full my-8 rounded-sm img-splay w-full mx-auto py-4\" crossorigin=\"anonymous\">\n<figcaption class=\"\">Hand MIDI Controller — MediaPipe hand landmarks mapped to MIDI CC</figcaption>\n</figure>\n<p class=\"\"><a href=\"https://github.com/ejfox/hand-midi-controller\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://github.com/ejfox/hand-midi-controller\">Hand MIDI Controller<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\" class=\"\"></path></svg></a> is a real-time hand-tracking MIDI controller built on MediaPipe and OpenCV, turning hand movements into MIDI control signals for music production, VJing, and performance. It includes TouchDesigner integration.</p>\n<h3 class=\"\" id=\"handtrack-websockets\">Handtrack WebSockets</h3>\n<p class=\"\"><a href=\"https://github.com/ejfox/handtrack-websockets\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://github.com/ejfox/handtrack-websockets\">Handtrack WebSockets<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\" class=\"\"></path></svg></a> does real-time 3D hand tracking with MediaPipe, OpenCV, and FastAPI, streaming hand position and rotation over WebSockets. It includes a cyberpunk visualization layer that renders the tracked hand.</p>\n<h3 class=\"\" id=\"opencv-midi-controller\">OpenCV MIDI Controller</h3>\n<figure role=\"figure\" aria-label=\"OpenCV MIDI Controller — OpenCV object tracking driving MIDI CC\" class=\"\">\n<img src=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/projects/opencv-midi-controller/diagram.png\" alt=\"OpenCV MIDI Controller — OpenCV object tracking driving MIDI CC\" loading=\"lazy\" decoding=\"async\" srcset=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_640/projects/opencv-midi-controller/diagram.png 640w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_960/projects/opencv-midi-controller/diagram.png 960w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/projects/opencv-midi-controller/diagram.png 1280w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1920/projects/opencv-midi-controller/diagram.png 1920w\" sizes=\"(max-width: 430px) 92vw, (max-width: 768px) 85vw, 900px\" title=\"OpenCV MIDI Controller — OpenCV object tracking driving MIDI CC\" width=\"2082\" height=\"1293\" style=\"--splay-rot:1.05deg;\" data-dimensions=\"2082×1293\" class=\"img-full my-8 rounded-sm img-splay w-full mx-auto py-4\" crossorigin=\"anonymous\">\n<figcaption class=\"\">OpenCV MIDI Controller — OpenCV object tracking driving MIDI CC</figcaption>\n</figure>\n<p class=\"\"><a href=\"https://github.com/ejfox/opencv-midi-controller\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://github.com/ejfox/opencv-midi-controller\">OpenCV MIDI Controller<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M12 .297c-6.63 0-12 5.373-12 12c0 5.303 3.438 9.8 8.205 11.385c.6.113.82-.258.82-.577c0-.285-.01-1.04-.015-2.04c-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729c1.205.084 1.838 1.236 1.838 1.236c1.07 1.835 2.809 1.305 3.495.998c.108-.776.417-1.305.76-1.605c-2.665-.3-5.466-1.332-5.466-5.93c0-1.31.465-2.38 1.235-3.22c-.135-.303-.54-1.523.105-3.176c0 0 1.005-.322 3.3 1.23c.96-.267 1.98-.399 3-.405c1.02.006 2.04.138 3 .405c2.28-1.552 3.285-1.23 3.285-1.23c.645 1.653.24 2.873.12 3.176c.765.84 1.23 1.91 1.23 3.22c0 4.61-2.805 5.625-5.475 5.92c.42.36.81 1.096.81 2.22c0 1.606-.015 2.896-.015 3.286c0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12\" class=\"\"></path></svg></a> is an experiment in sending MIDI signals based on OpenCV object detection.</p>\n<h3 class=\"\" id=\"speech-echoes\">Speech Echoes</h3>\n<figure role=\"figure\" aria-label=\"Live speech rendered as decaying typographic echoes\" class=\"\">\n<img src=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/projects/opencv-talk-typography/echo-1.png\" alt=\"Live speech rendered as decaying typographic echoes\" loading=\"lazy\" decoding=\"async\" srcset=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_640/projects/opencv-talk-typography/echo-1.png 640w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_960/projects/opencv-talk-typography/echo-1.png 960w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/projects/opencv-talk-typography/echo-1.png 1280w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1920/projects/opencv-talk-typography/echo-1.png 1920w\" sizes=\"(max-width: 430px) 92vw, (max-width: 768px) 85vw, 900px\" title=\"Live speech rendered as decaying typographic echoes\" width=\"3258\" height=\"2262\" style=\"--splay-rot:-1.24deg;\" data-dimensions=\"3258×2262\" class=\"img-full my-8 rounded-sm img-splay w-full mx-auto py-4\" crossorigin=\"anonymous\">\n<figcaption class=\"\">Live speech rendered as decaying typographic echoes</figcaption>\n</figure>\n<p class=\"\">Speech Echoes is a Vue app that captures live speech and renders it as decaying typographic \"echoes,\" with a font and weight captured per utterance. It's built with p5, MediaPipe, and d3-force.</p>\n<h3 class=\"\" id=\"glasses-hud\">Glasses HUD</h3>\n<figure role=\"figure\" aria-label=\"The two lenses you compose a HUD across\" class=\"\">\n<img src=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/projects/glasses-hud/lenses.png\" alt=\"The two lenses you compose a HUD across\" loading=\"lazy\" decoding=\"async\" srcset=\"https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_640/projects/glasses-hud/lenses.png 640w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_960/projects/glasses-hud/lenses.png 960w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1280/projects/glasses-hud/lenses.png 1280w, https://res.cloudinary.com/ejf/image/upload/c_scale,f_auto,q_auto:good,w_1920/projects/glasses-hud/lenses.png 1920w\" sizes=\"(max-width: 430px) 92vw, (max-width: 768px) 85vw, 900px\" title=\"The two lenses you compose a HUD across\" width=\"1600\" height=\"600\" style=\"--splay-rot:0.92deg;\" data-dimensions=\"1600×600\" class=\"img-full my-8 rounded-sm img-splay w-full mx-auto py-4\" crossorigin=\"anonymous\">\n<figcaption class=\"\">The two lenses you compose a HUD across</figcaption>\n</figure>\n<p class=\"\"><a href=\"https://ejfox.github.io/glasses-hud/\" target=\"_blank\" rel=\"noopener noreferrer\" class=\"external-link group inline-flex items-center text-blue-600 dark:text-blue-400\" data-preview-url=\"https://ejfox.github.io/glasses-hud/\">Glasses HUD<svg class=\"inline-block w-4 h-4 ml-1 opacity-50 dark:opacity-75 group-hover:opacity-100 transition-opacity align-text-bottom\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1em\" height=\"1em\" viewBox=\"0 0 24 24\"><path fill=\"currentColor\" d=\"M14.435 12.973c.269 0 .492.133.686.396c.192.265.294.588.294.975c0 .385-.102.711-.294.973c-.193.265-.417.396-.686.396c-.278 0-.522-.131-.715-.396c-.192-.262-.294-.588-.294-.973c0-.387.102-.71.294-.975c.192-.264.436-.396.715-.396m3.44-3.559c.746.811 1.125 1.795 1.125 2.953q0 1.122-.259 2.023q-.263.896-.654 1.459a4.3 4.3 0 0 1-.974.989a5 5 0 0 1-1.065.623a5.5 5.5 0 0 1-1.111.306a9 9 0 0 1-.943.123l-.685.014l-.547.015a18 18 0 0 1-1.524 0l-.547-.015l-.685-.014a9 9 0 0 1-.943-.123a5.3 5.3 0 0 1-1.111-.306a5 5 0 0 1-1.064-.623a4.3 4.3 0 0 1-.975-.989q-.392-.563-.654-1.459q-.26-.9-.259-2.023c0-1.158.379-2.143 1.125-2.953q-.123-.062-.008-1.217a7 7 0 0 1 .495-2.132c.934.099 2.09.629 3.471 1.581c.466-.119 1.101-.183 1.917-.183q1.278.002 1.918.184q.943-.638 1.805-1.034c.584-.261 1.005-.416 1.269-.457l.396-.09q.404.974.496 2.132q.114 1.154-.009 1.216m-5.845 7.82c1.688 0 2.954-.202 3.821-.607c.855-.404 1.292-1.238 1.292-2.496q0-1.096-.822-1.828a1.85 1.85 0 0 0-.989-.486q-.563-.091-1.72 0q-1.155.091-1.582.09c-.385 0-.8-.018-1.319-.059q-.78-.06-1.223-.078a3.7 3.7 0 0 0-.958.108a1.9 1.9 0 0 0-.853.425c-.521.469-.79 1.077-.79 1.828q0 1.888 1.28 2.496c.85.405 2.113.607 3.802.607zm-2.434-4.261c.268 0 .492.133.685.396c.192.265.294.588.294.975c0 .385-.102.711-.294.973c-.192.265-.417.396-.685.396c-.279 0-.522-.131-.716-.396c-.192-.262-.294-.588-.294-.973c0-.387.102-.71.294-.975c.193-.264.436-.396.716-.396\" class=\"\"></path></svg></a> is a tool for quickly prototyping AR lens visualizations and HUDs. Drag data widgets onto the left and right lenses to compose a heads-up display from live bio, motion, location, environment, and device signals.</p>","title":"Hand-Tracking & Generative Art","metadata":{"title":"Hand-Tracking & Generative Art","date":"2024-07-01T04:00:00.000Z","category":"Art","featured":false,"modified":"2025-08-13T15:46:54.000Z","tech":["Computer Vision","MIDI","WebGL","Hand Tracking","Generative Art","Interactive Media"],"state":"deployed","ai-involvement":"ai-assisted","tags":["creativity","interfaces"],"words":540,"images":4,"imageDetails":{"total":4,"cloudinary":4,"withDimensions":0},"links":8,"codeBlocks":0,"headers":{"h2":1},"toc":[{"text":"Hand-tracking & gesture","slug":"hand-tracking--gesture","level":"h2","children":[{"text":"Hand MIDI Controller","slug":"hand-midi-controller","level":"h3","children":[]},{"text":"Handtrack WebSockets","slug":"handtrack-websockets","level":"h3","children":[]},{"text":"OpenCV MIDI Controller","slug":"opencv-midi-controller","level":"h3","children":[]},{"text":"Speech Echoes","slug":"speech-echoes","level":"h3","children":[]},{"text":"Glasses HUD","slug":"glasses-hud","level":"h3","children":[]}]}],"type":"post"}},"_links":{"self":"https://ejfox.com/projects/creative-interfaces.json","html":"https://ejfox.com/projects/creative-interfaces","index":"/projects.json"}}