<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[How I Got My Drone to Spot Golf Balls]]></title><description><![CDATA[How I Got My Drone to Spot Golf Balls]]></description><link>https://golfballdetectordrone.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Sat, 17 Oct 2026 14:19:30 GMT</lastBuildDate><atom:link href="https://golfballdetectordrone.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[How I Got My Drone to Spot Golf Balls]]></title><description><![CDATA[I’m not a golfer…at all.
But a few weekends ago, I found myself standing on the tee, watching golf balls vanish into the horizon like tiny white UFOs.
That’s when the developer in me had a thought:

“Could I use my DJI Mini 4K drone, a live video str...]]></description><link>https://golfballdetectordrone.hashnode.dev/how-i-got-my-drone-to-spot-golf-balls</link><guid isPermaLink="true">https://golfballdetectordrone.hashnode.dev/how-i-got-my-drone-to-spot-golf-balls</guid><category><![CDATA[Machine Learning]]></category><category><![CDATA[drone]]></category><category><![CDATA[Python]]></category><category><![CDATA[Computer Vision]]></category><category><![CDATA[drones]]></category><category><![CDATA[object detection ]]></category><category><![CDATA[golf]]></category><dc:creator><![CDATA[Anthony Dutra]]></dc:creator><pubDate>Sat, 09 Aug 2025 13:23:01 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1754742315685/990c274c-33e9-47ab-82c3-17e11cdebd6d.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I’m not a golfer…at all.</p>
<p>But a few weekends ago, I found myself standing on the tee, watching golf balls vanish into the horizon like tiny white UFOs.</p>
<p>That’s when the developer in me had a thought:</p>
<blockquote>
<p><em>“Could I use my DJI Mini 4K drone, a live video stream, and machine learning to track these things in real time?”</em></p>
</blockquote>
<p>Fast forward a few days, and I had built a working prototype:</p>
<ul>
<li><p>Streaming live video from my drone to my laptop via <strong>RTMP</strong></p>
</li>
<li><p>Running a <strong>Roboflow object detection</strong> workflow to spot golf balls</p>
</li>
<li><p>Logging detections with timestamps, confidence scores, and (mock) GPS coordinates</p>
</li>
<li><p>Visualizing everything in an interactive <strong>Streamlit dashboard</strong> — complete with a map of “detections”</p>
</li>
</ul>
<p>This post walks you through exactly how I built it, the lessons I learned, and where I’m taking it next.</p>
<h2 id="heading-the-big-idea">The Big Idea</h2>
<p>This started as a weekend “what if” experiment and turned into a working prototype that:</p>
<ol>
<li><p>Streams my drone’s video feed in real time</p>
</li>
<li><p>Runs each frame through a golf ball detection model</p>
</li>
<li><p>Logs and maps detections with GPS (mocked for now)</p>
</li>
</ol>
<p>Here’s the high-level flow:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754744789498/59e19095-9eb1-4f35-8ebb-26a72c88f671.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-1-real-time-drone-video-feed-via-rtmp">1. Real-time Drone Video Feed (via RTMP)</h2>
<p>The DJI Fly app doesn’t have an SDK for my drone model, but it <em>does</em> let you live-stream video using RTMP.<br />I set up an Nginx RTMP server on my laptop so the drone’s video feed could flow directly into my Python script.</p>
<p><strong>Key config snippet from</strong> <code>nginx.conf</code>:</p>
<pre><code class="lang-python">nginxCopyEditrtmp {
    server {
        listen <span class="hljs-number">1935</span>;
        chunk_size <span class="hljs-number">4096</span>;
        application live {
            live on;
            record off;
        }
    }
}
</code></pre>
<p>Then in Python:</p>
<pre><code class="lang-python">pythonCopyEditrtmp_url = <span class="hljs-string">"rtmp://&lt;your-ip&gt;:1935/live/stream"</span>
cap = cv2.VideoCapture(rtmp_url)
</code></pre>
<p><img src="https://media.licdn.com/dms/image/v2/D5612AQHcbUM0V6QKoQ/article-inline_image-shrink_1500_2232/B56Zh6uINLHMAU-/0/1754405570414?e=1759968000&amp;v=beta&amp;t=Q1RlL0rhekvOBf5X7DVVvIKpgW6cJfdn_8yMLFf6u5A" alt="Article content" /></p>
<h2 id="heading-2-golf-ball-detection-with-roboflow">2. Golf Ball Detection with Roboflow</h2>
<p>I trained a small object detection model on golf balls using <a target="_blank" href="https://roboflow.com">Roboflow</a>.<br />For speed, I deployed it using Roboflow’s <strong>Small Object Detection (SAHI)</strong> workflow — which is perfect for small, high-contrast objects like golf balls.</p>
<p><strong>Minimal Python snippet:</strong></p>
<pre><code class="lang-python">pythonCopyEditfrom inference_sdk <span class="hljs-keyword">import</span> InferenceHTTPClient

client = InferenceHTTPClient(
    api_url=<span class="hljs-string">"https://serverless.roboflow.com"</span>,
    api_key=<span class="hljs-string">"YOUR_API_KEY"</span>
)

result = client.run_workflow(
    workspace_name=<span class="hljs-string">"projects-lznpz"</span>,
    workflow_id=<span class="hljs-string">"small-object-detection-sahi"</span>,
    images={<span class="hljs-string">"image"</span>: frame}
)
</code></pre>
<p>I flew my test flights in my backyard and here is what an annotated capture looks like:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754745140597/4375ac94-494b-49d8-8b24-01230c9d5ea5.jpeg" alt class="image--center mx-auto" /></p>
<h2 id="heading-3-visualizing-detections-on-a-map">3. Visualizing Detections on a Map</h2>
<p>Since I can’t yet get GPS from my DJI Mini 4K, I mocked GPS coordinates to simulate where the drone <em>might</em> be when it detects a ball.</p>
<p>I used Folium + Streamlit to create a live dashboard with:</p>
<ul>
<li><p>Latest annotated detections</p>
</li>
<li><p>Confidence chart over time</p>
</li>
<li><p>Map markers for detections (mocked locations for now)</p>
</li>
</ul>
<p><strong>Minimal Folium example:</strong></p>
<pre><code class="lang-python">pythonCopyEditimport folium
map = folium.Map(location=[<span class="hljs-number">41.5081</span>, <span class="hljs-number">-71.1279</span>], zoom_start=<span class="hljs-number">17</span>)
folium.Marker(
    [<span class="hljs-number">41.5081</span>, <span class="hljs-number">-71.1279</span>],
    popup=<span class="hljs-string">"Golf Ball Detected!"</span>,
    icon=folium.Icon(color=<span class="hljs-string">"green"</span>, icon=<span class="hljs-string">"info-sign"</span>)
).add_to(map)
map.save(<span class="hljs-string">"map.html"</span>)
</code></pre>
<p>Obviously, you’ll just be looking at a gray map with some random points right now, but in the future, gathering GPS data from a drone with the SDK will be another battle:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754745434405/6fef2918-af77-46ee-883a-3c810b2636b6.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-lessons-learned">Lessons Learned</h2>
<p>This “just-for-fun” project ended up being a surprisingly solid prototype — combining video streaming, real-time inference, and mapping into a single pipeline.</p>
<p>It also reinforced something I love about modern dev tooling: with the right off-the-shelf components, you can go from idea to working proof-of-concept in a weekend.</p>
<p>Key takeaways from this build:</p>
<ul>
<li><p><strong>RTMP streaming from the DJI Fly app is smooth.</strong><br />  Once the Nginx RTMP server was set up, my drone’s video feed streamed to my laptop with low latency and minimal hiccups.</p>
</li>
<li><p><strong>Roboflow handles tiny targets like a champ.</strong><br />  Even with compression artifacts, a small dataset was enough for Roboflow’s model to detect golf balls mid-air or on grass.</p>
</li>
<li><p><strong>Mapping detections (even with fake GPS) feels futuristic.</strong><br />  Seeing a detection marker pop up in real-time makes this feel like more than just a hobby project — it’s closer to a field tool.</p>
</li>
</ul>
<p>The real “aha” moment for me:</p>
<p>Building something like this no longer requires custom hardware or months of dev time. You can stand on the shoulders of Nginx, OpenCV, Roboflow, and Streamlit to get 80% of the way <em>fast</em>.</p>
<h2 id="heading-the-plan-moving-forward">The Plan Moving Forward</h2>
<p>While this prototype already works, there’s a clear roadmap to take it from fun weekend build to something with serious real-world utility.</p>
<ol>
<li><p><strong>Upgrade to a drone with full SDK support</strong><br /> With SDK access, I could get native GPS, camera control, and telemetry directly from the drone — no workarounds required.</p>
</li>
<li><p><strong>Integrate real GPS coordinates into detections</strong><br /> Moving from mocked GPS to real coordinates would enable accurate geotagging of each detection for retrieval or analysis.</p>
</li>
<li><p><strong>Run inference on edge hardware</strong><br /> Instead of streaming every frame to the cloud, a small edge device (Jetson Nano, Coral TPU) could run detections locally — faster, cheaper, and offline-capable.</p>
</li>
</ol>
<h2 id="heading-want-to-build-your-own">Want to Build Your Own?</h2>
<p>If you’re curious about trying this yourself — whether for golf balls, lost pets, or entirely different use cases — I’m happy to share my code snippets and setup steps.</p>
<p>Check out the <a target="_blank" href="https://www.linkedin.com/pulse/i-got-my-dji-drone-help-me-spot-lost-golf-balls-heres-anthony-dutra-ftc2c">demo video</a> from my LinkedIn post.</p>
<p>Drop me a message here or connect with me <a target="_blank" href="https://www.linkedin.com/in/anthony-dutra-08464124/">LinkedIn</a>!</p>
]]></content:encoded></item></channel></rss>