// case study · computer vision// vaka çalışması · bilgisayarlı görü
Detecting wildfire smoke from drones, measured on a fire the model has never seenDrone görüntülerinden orman yangını dumanı tespiti, modelin hiç görmediği bir yangında ölçüldü
A YOLO11 detector for fire and smoke in aerial footage, built around one rule: the numbers must hold on scenes the model has never seen. Havadan çekilmiş görüntülerde ateş ve duman tespit eden bir YOLO11 modeli. Tek bir kurala göre geliştirildi: sonuçlar modelin hiç görmediği sahnelerde de geçerli olmalı.
01
The problemProblem
Drones can spot a wildfire early, but early fires are small: a thin plume on the horizon, an ember under smoke, often seen from an oblique angle. A detector is only useful here if it finds those cases without raising alarms on clouds, haze or red equipment.
Drone'lar bir orman yangınını erken fark edebilir, ama erken yangınlar küçüktür: ufukta ince bir duman, dumanın altında bir kor, çoğu zaman eğik bir açıdan görülür. Burada bir model ancak bu durumları bulut, pus ya da kırmızı ekipman yüzünden alarm vermeden yakalayabiliyorsa işe yarar.
02
The finding that shaped the project: the official split leaksProjeyi şekillendiren bulgu: resmi bölme sızdırıyor
of FASDD_UAV's official test images (3,894 of 4,181) have a near-identical copy in train/val: the same scene a few video frames apart. The whole dataset turned out to come from only ~190 independent scenes. A model scored on that split is graded on memory, not generalisation.
FASDD_UAV'nin resmi test görüntülerinin (4.181'de 3.894) eğitim/doğrulama setinde neredeyse aynı bir kopyası var: aynı sahne, birkaç video karesi arayla. Tüm veri setinin yalnızca ~190 bağımsız sahneden oluştuğu ortaya çıktı. Bu bölmeyle ölçülen bir model genellemeye değil ezbere not alıyor.
What I did insteadBunun yerine ne yaptım
- Near-duplicate graph. Perceptual hashing links obvious copies; DINOv2 embeddings link frames of the same scene that hashing misses.
- Data-driven threshold. τ = 0.936 is the 99th percentile of similarity between different fire events, i.e. "as similar as two different fires ever get". Pairs on both sides were checked by eye.
- Group split. Connected components become scenes; whole scenes go to one split, balanced by category.
- A whole fire held out. Every frame of the Heinola fire is test-only, an event the model never sees in any form.
- Neredeyse-kopya grafı. Algısal hash bariz kopyaları bağlıyor; DINOv2 gömmeleri hash'in kaçırdığı aynı sahneye ait kareleri bağlıyor.
- Veriye dayalı eşik. τ = 0.936, farklı yangın olayları arasındaki benzerliğin 99. yüzdeliği; yani "iki farklı yangının en fazla birbirine benzeyebildiği nokta". Eşiğin iki tarafındaki çiftler gözle kontrol edildi.
- Grup bazlı bölme. Bağlı bileşenler sahne oluyor; her sahne bütün olarak tek bir bölmeye gidiyor ve kategoriye göre dengeleniyor.
- Bir yangın tamamen dışarıda. Heinola yangınının tüm kareleri yalnızca testte; model bu olayı hiçbir şekilde görmüyor.
Result: FASDD test images with a train/val neighbour above τ went from 1,205 to 0. Final split: 22,124 train / 3,651 val / 4,271 test.
Sonuç: eğitim/doğrulamada τ üzerinde komşusu olan FASDD test görüntüsü sayısı 1.205'ten 0'a indi. Son bölme: 22.124 eğitim / 3.651 doğrulama / 4.271 test.
03
Experiments: one change at a time, judged on valDeneyler: her seferinde tek değişiklik, doğrulama setiyle değerlendirme
| Exp | ChangeDeğişiklik | fire mAP50 | smoke mAP50 | mAP50-95 |
|---|---|---|---|---|
| E01 | Baseline: YOLO11s, 640 pxBaz: YOLO11s, 640 px | 0.351 | 0.731 | 0.265 |
| E02 | 1280 px | 0.328 | 0.726 | 0.259 |
| E03 | Proper LR scheduleDüzgün öğrenme oranı planı | 0.318 | 0.721 | 0.282 |
| E04 | + strong augmentation+ güçlü veri artırma | 0.422 | 0.760 | 0.308 |
| E05 | + D-Fire in train only (de-duplicated)+ yalnızca eğitime D-Fire (kopyalar ayıklanmış) | 0.498 | 0.824 | 0.371 |
| E06 | E05 with YOLO11mE05, YOLO11m ile | 0.532 | 0.815 | 0.377 |
Why 1280 px did not help: a diagnosis instead of a guess1280 px neden işe yaramadı: tahmin yerine teşhis
Fire mAP50 was 0.85 on training images vs 0.35 on val: the model was memorising scenes, so the fix was diversity (augmentation, more scenes), not resolution. Separately, 89% of val fire boxes came from two densely annotated scenes where the model found fire in every frame but split the boxes differently, so box mAP understates fire performance. From then on I report frame-level and pixel-coverage metrics next to mAP.
Ateş mAP50 değeri eğitim görüntülerinde 0.85, doğrulamada 0.35 idi: model sahneleri ezberliyordu, yani çözüm çözünürlük değil çeşitlilikti (veri artırma, daha fazla sahne). Ayrıca doğrulamadaki ateş kutularının %89'u yoğun etiketlenmiş iki sahneden geliyordu; model her karede ateşi buluyor ama kutuları farklı bölüyordu, bu yüzden kutu mAP'si ateş performansını olduğundan düşük gösteriyor. O noktadan sonra mAP'nin yanında kare bazlı ve piksel kapsama metriklerini de raporladım.
Choosing E05 over the bigger E06Daha büyük E06 yerine neden E05
E06 draws better fire boxes, but at the operating point it finds fire in the same share of frames, raises more false alarms (fire 1.0 → 1.8%, smoke 1.1 → 1.9%), detects less smoke and costs 3× the compute (68 vs 21 GFLOPs). For a drone, E05 is the better trade.
E06 ateş kutularını daha iyi çiziyor, ama çalışma noktasında ateşi aynı oranda karede buluyor, daha çok yanlış alarm veriyor (ateş %1.0 → %1.8, duman %1.1 → %1.9), daha az duman tespit ediyor ve 3 kat daha fazla işlem gücü istiyor (68'e karşı 21 GFLOPs). Bir drone için E05 daha doğru tercih.
04
Final evaluation: test set opened onceSon değerlendirme: test seti tek kez açıldı
Model and thresholds were frozen before looking at test. Confidence thresholds were chosen on val as the lowest value keeping frame-level false alarms at or below 1%.
Model ve eşikler test setine bakılmadan önce donduruldu. Güven eşikleri, kare bazlı yanlış alarmı %1 veya altında tutan en düşük değer olarak doğrulama setinde seçildi.
| Class · subsetSınıf · alt küme | DetectedTespit | False alarmYanlış alarm | Baseline detectedBaz tespit | Baseline false alarmBaz yanlış alarm |
|---|---|---|---|---|
| fire · FASDD testateş · FASDD test | 90.2% | 2.8% | 77.8% | 2.6% |
| smoke · FASDD testduman · FASDD test | 95.8% | 0.4% | 84.3% | 0.1% |
| smoke · Heinola (unseen)duman · Heinola (görülmemiş) | 94.0% | 0.0% | 99.1% | 12.0% |
On the unseen fire the baseline flagged almost everything, including 12% of smoke-free frames. The final model is nearly as sensitive and practically never fires falsely.
Görülmemiş yangında baz model neredeyse her şeyi işaretledi, dumansız karelerin %12'si dahil. Son model neredeyse aynı hassasiyette ve pratikte hiç yanlış alarm vermiyor.
Where it still failsHâlâ nerede hata yapıyor
- Tiny fires: embers under smoke or a thin fire line at night, under 10 px at 640.
- Colour overlap: a flame front behind dense orange smoke.
- Red objects: firefighting equipment triggering fire boxes.
- Distant plumes: white smoke against a hazy sky is detected late.
- Çok küçük yangınlar: dumanın altındaki korlar ya da gece ince bir ateş çizgisi, 640 px'te 10 pikselin altında.
- Renk örtüşmesi: yoğun turuncu dumanın arkasındaki alev cephesi.
- Kırmızı nesneler: itfaiye ekipmanının ateş olarak algılanması.
- Uzak duman: puslu gökyüzüne karşı beyaz duman geç fark ediliyor.
05
Deployment: ONNX and a temporal alarmDağıtım: ONNX ve zamansal alarm
The final model needs only onnxruntime, OpenCV and NumPy, no PyTorch: a 37.9 MB model at ~32 ms per frame on a Colab CPU. It raises an alarm only when a class is seen in at least 3 of the last 5 frames, so single-frame false positives never trigger it.
Son model yalnızca onnxruntime, OpenCV ve NumPy gerektiriyor, PyTorch gerekmiyor: 37,9 MB'lık model Colab CPU'sunda kare başına ~32 ms'de çalışıyor. Bir sınıf son 5 karenin en az 3'ünde görüldüğünde alarm veriyor, böylece tek karelik yanlış tespitler alarmı tetiklemiyor.
python predict.py --model models/firesmoke_y11s_640.onnx \ --source drone.mp4 --out result.mp4
On the unseen Heinola fire an alarm was raised in 7 of 8 videos, typically 2 frames after smoke first appears, the minimum the 3-of-5 rule allows. A unit test confirms predict.py matches Ultralytics' own ONNX inference box for box.
Görülmemiş Heinola yangınında 8 videonun 7'sinde alarm verildi, genellikle dumanın ilk göründüğü andan 2 kare sonra; 3'te 5 kuralının izin verdiği en kısa süre. Bir birim testi, predict.py'nin Ultralytics'in kendi ONNX çıkarımıyla kutu kutu aynı sonucu verdiğini doğruluyor.
06
Limitations & next stepsSınırlamalar & sonraki adımlar
This is a prototype for operator assistance, not a safety system. Test fire comes from only 13 scenes, the held-out event has smoke labels only, and the footage is too sparsely sampled to measure time-to-alarm or false alarms per hour. Next: continuous drone video from the target region, more night and small-fire data, thermal input, and an on-board latency benchmark on NVIDIA Jetson.
Bu bir güvenlik sistemi değil, operatöre yardımcı bir prototip. Test setindeki ateş yalnızca 13 sahneden geliyor, dışarıda tutulan olayda yalnızca duman etiketi var ve görüntüler alarm süresini ya da saat başına yanlış alarmı ölçmek için fazla seyrek örneklenmiş. Sıradaki adımlar: hedef bölgeden kesintisiz drone videosu, daha fazla gece ve küçük yangın verisi, termal kamera girdisi ve NVIDIA Jetson üzerinde gecikme ölçümü.