MQTT ile YOLO nesne tespiti bir kamerayı sensöre dönüştürür: video aktarmak yerine kameranın gördüklerini tanımlayan küçük JSON mesajları yayınlarsınız. Bu eğitimde Python ile bir web kamerası veya RTSP akışında YOLO modeli çalıştıracak, kare başına tespitleri yayınlayacak, nesne sayımlarını tutacak ve herhangi bir MQTT client'ının tüketebileceği uyarılar üreteceksiniz.
Neden Video Yerine Tespit Gönderilmeli
Video ağırdır, içinde arama yapmak zordur ve izleyecek bir kişiye ihtiyaç duyar. Tespitler ise hafif, yapılandırılmış ve makine tarafından okunabilir. "A bölgesinde 3 kişi, 1 forklift" gibi tek bir mesaj birkaç yüz bayttır; geldiği kare ise onlarca veya yüzlerce kilobayttır.
Tespitleri MQTT ile yayınlamak, görüyü diğer her şeyden de ayırır:
- Dashboard'lar sayımlara abone olur ve doluluğu gerçek zamanlı gösterir.
- Bir otomasyon servisi uyarılara abone olur ve bir uyarı lambasını yakar.
- Bir historian raporlama için dakika başına sayımları saklar.
- Belki farklı bir makinedeki başka bir model, görüyü diğer sensörlerle birleştirir.
Bu tüketicilerin hiçbirinin sonucu hangi kameranın, modelin veya GPU'nun ürettiğini bilmesi gerekmez. Bu, MQTT'yi sensörler için popüler kılan gevşek bağlılığın aynısıdır; şimdi uç cihazlarda bilgisayarlı görüye uygulanıyor.
Mimari
camera (USB / RTSP) -> Python + YOLO -> MQTT broker -> dashboards, alerts, storage
connectmq/demo/<id>/site1/dock/cam1/detections every processed frame (throttled)
connectmq/demo/<id>/site1/dock/cam1/counts retained, current count per class
connectmq/demo/<id>/site1/dock/cam1/alerts event when a rule triggers
connectmq/demo/<id>/site1/dock/cam1/status retained, online/offline (Last Will)
Ön Koşullar
- Python 3.9 veya üstü, bir web kamerası veya RTSP kamera
- Küçük modeller için saniyede birkaç kare hızında bir CPU yeterlidir; bir GPU veya Jetson gerçek zamanlı hız sağlar
- Paketler:
pip install ultralytics opencv-python "paho-mqtt>=2.0"
İlk çalıştırma, önceden eğitilmiş yolov8n.pt ağırlıklarını (80 COCO sınıfı üzerinde eğitilmiş nano model) indirir. Diğer model boyutları ve daha yeni sürümler için Ultralytics dokümantasyonuna bakın; aşağıda kullanılan API hepsinde çalışır.
Tespit Yayıncısı
yolo_mqtt.py olarak kaydedin. Kamerayı açar, YOLO'yu çalıştırır, sonuçları JSON'a dönüştürür, tespitleri saniyede en fazla iki kez yayınlar, değiştiklerinde retained sayımları günceller ve kısıtlı bir bölgede kişi bulunduğunda bir uyarı üretir.
import json
import time
import uuid
import cv2
import paho.mqtt.client as mqtt
from ultralytics import YOLO
SOURCE = 0 # web kamerası indeksi veya "rtsp://user:pass@192.168.1.50:554/stream1"
PREFIX = "connectmq/demo/yolo-c83f/site1/dock/cam1"
CLASSES = {"person", "car", "truck", "forklift"} # forklift yalnızca özel bir modelle
MIN_CONF = 0.5
PUBLISH_EVERY = 0.5 # saniye
ZONE = (0.6, 0.0, 1.0, 1.0) # kısıtlı bölge: karenin sağdaki %40'ı (x1, y1, x2, y2)
model = YOLO("yolov8n.pt")
names = model.names
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
client_id=f"yolo-cam1-{uuid.uuid4().hex[:6]}")
client.will_set(f"{PREFIX}/status", json.dumps({"online": False}), qos=1, retain=True)
client.connect("broker.connectmq.com", 1883, keepalive=30)
client.loop_start()
client.publish(f"{PREFIX}/status", json.dumps({"online": True, "model": "yolov8n"}),
qos=1, retain=True)
cap = cv2.VideoCapture(SOURCE)
last_pub, last_counts, zone_alert = 0.0, None, False
def in_zone(cx, cy):
x1, y1, x2, y2 = ZONE
return x1 <= cx <= x2 and y1 <= cy <= y2
try:
while True:
ok, frame = cap.read()
if not ok:
time.sleep(1)
cap.open(SOURCE) # RTSP kopmalarında yeniden bağlan
continue
h, w = frame.shape[:2]
result = model(frame, conf=MIN_CONF, verbose=False)[0]
objects, counts, people_in_zone = [], {}, 0
for box in result.boxes:
label = names[int(box.cls)]
if label not in CLASSES:
continue
x1, y1, x2, y2 = box.xyxyn[0].tolist() # 0..1 arasında normalize
cx, cy = (x1 + x2) / 2, (y1 + y2) / 2
objects.append({"label": label, "conf": round(float(box.conf), 2),
"box": [round(v, 3) for v in (x1, y1, x2, y2)]})
counts[label] = counts.get(label, 0) + 1
if label == "person" and in_zone(cx, cy):
people_in_zone += 1
now = time.time()
if now - last_pub >= PUBLISH_EVERY:
last_pub = now
client.publish(f"{PREFIX}/detections", json.dumps(
{"ts": now, "frame": [w, h], "objects": objects}), qos=0)
if counts != last_counts:
last_counts = counts
client.publish(f"{PREFIX}/counts", json.dumps({"ts": now, **counts}),
qos=1, retain=True)
if people_in_zone and not zone_alert:
zone_alert = True
client.publish(f"{PREFIX}/alerts", json.dumps(
{"ts": now, "rule": "person-in-zone", "state": "raised",
"count": people_in_zone}), qos=1)
elif not people_in_zone and zone_alert:
zone_alert = False
client.publish(f"{PREFIX}/alerts", json.dumps(
{"ts": now, "rule": "person-in-zone", "state": "cleared"}), qos=1)
finally:
cap.release()
client.publish(f"{PREFIX}/status", json.dumps({"online": False}), qos=1, retain=True)
client.loop_stop()
client.disconnect()
Çıktıyı başka bir terminalden izleyin:
mosquitto_sub -h broker.connectmq.com -p 1883 -i yolo-watch-c83f -t "connectmq/demo/yolo-c83f/#" -v
Karenin sağ tarafına yürüdüğünüzde bir raised uyarısı, oradan ayrıldığınızda ise bir cleared uyarısı göreceksiniz.
Tespit Payload'unu Tasarlamak
Betikten gelen bir tespit mesajı şöyle görünür:
{
"ts": 1792140112.42,
"frame": [1280, 720],
"objects": [
{"label": "person", "conf": 0.88, "box": [0.612, 0.204, 0.731, 0.958]},
{"label": "car", "conf": 0.74, "box": [0.051, 0.402, 0.338, 0.811]}
]
}
MQTT ile YOLO nesne tespiti payload'larını faydalı tutan yönergeler:
| Tercih | Öneri | Neden |
|---|---|---|
| Kutu koordinatları | 0 ile 1 arasında normalize | Tüketicilerin çözünürlüğü bilmesi gerekmez; bölgeler kamera değişikliklerinden etkilenmez |
| Güven değeri | 2 ondalık basamağa yuvarlanmış | Anlam kaybetmeden bayt tasarrufu sağlar |
| Kareler | Asla tespit topic'inde değil | Görüntüleri ayrı bir topic'te ya da tamamen MQTT dışında tutun |
| Hız | Saniyede 1 ila 5 mesaja sınırlayın | Tüketicilerin nadiren her kareye ihtiyacı olur |
| Sayımlar | Retained, değişimde yayınlanır | Yeni dashboard'lar mevcut durumu anında görür |
| Model bilgisi | Retained status topic'inde | Sonuçları bir model sürümüne kadar izlemenizi sağlar |
Sayım ve Uyarı Kuralları
Kare başına nesne saymak kolaydır; geçen nesneleri saymak ise daha zordur, çünkü aynı kişi birçok karede görünür. Geçiş sayımı için Ultralytics'te takibi (model.track(frame, persist=True)) etkinleştirin; bu, her nesneye bir ID atar ve merkezi bir çizgiyi geçtiğinde her ID'yi bir kez sayarsınız. Geçişi bir sayım olarak değil bir olay olarak yayınlayın ve dakika başına toplamayı aşağı akıştaki bir servise bırakın.
Gecikme önemli olduğunda (bir robot hücresine giren bir kişi) uyarı kuralları kameraya yakın olmalıdır; iş mantığı olduklarında (on dakikadır rampada bekleyen beşten fazla kamyon) ise aşağı akışta olmalıdır. Sonuçlar MQTT üzerinde olduğundan, kamera kodunu değiştirmeden bir kuralı bir yerden diğerine taşıyabilirsiniz.
Tespitleri Aşağı Akışta Tüketmek
YOLO nesne tespiti sonuçlarını MQTT ile yayınlamanın değeri, tüketen tarafta ortaya çıkar. Ekiplerin ilk haftalarda geliştirdiği birkaç kalıp:
- Doluluk dashboard'u.
site1/+/+/countsgibi bir wildcard ile her kameranın retainedcountstopic'ine abone olun. Her yeni dashboard oturumu, her kameranın mevcut sayımını anında, ardından canlı güncellemeleri alır. - Dakika başına istatistikler. Küçük bir Python veya Node-RED servisi sayımları dakika başına toplar ve bir zaman serisi veritabanına yazar. Yoğun saatler veya rampa kullanımına dair raporlar videodan değil, buradan gelir.
- Kilitlemeler ve uyarılar. Bir otomasyon servisi uyarı topic'ine abone olur ve bir uyarı lambasını yakar ya da bir amire mesaj gönderir. Güvenlik açısından kritik kilitlemeleri sertifikalı donanımda tutun; kamera uyarıları bir tamamlayıcıdır, yerine geçmez.
- Diğer sensörlerle çapraz kontrol. Bir ışık bariyeri veya kapı kontağıyla birleştirilmiş bir kişi uyarısı, her ikisinin tek başına olduğundan çok daha güvenilirdir.
Bunların her biri yalnızca bir abone daha olduğundan, yeni bir tane eklemek kamerayı asla yavaşlatmaz. Broker aynı mesajı hepsine dağıtır.
Gizlilik ve Veri Minimizasyonu
İnsanları gören kameralar sorumluluk getirir. Yüzleri veya kareleri asla yayınlamadan yalnızca etiketleri, sayımları ve normalize kutuları yayınlamak, alabileceğiniz en güçlü gizlilik önlemidir ve bu mimariye doğal olarak uyar. Doğrulama için anlık görüntülere ihtiyacınız varsa, bunları kısa bir saklama süresiyle yerelde depolayın veya yalnızca yetkili servislerin okuyabileceği özel bir topic'e gönderin. Kameranın neyi ve neden tespit ettiğini belgeleyin ve iş yerlerinde veya kamusal alanlarda kurulum yapmadan önce yerel mevzuatı kontrol edin.
Sorun Giderme
- CPU'da çok düşük kare hızı. Nano modeli kullanın,
imgsz=416ile girdi boyutunu düşürün veya her iki kareden birini işleyin. - RTSP akışı donuyor. OpenCV kareleri tamponlar; ayrı bir thread'de sürekli okuyun ve yalnızca en son kareyi işleyin.
- Gidip gelen uyarılar. Uyarı vermeden önce art arda birkaç karede tespit, temizlemeden önce ise art arda birkaç boş kare arayın.
- Mesajlar reddediliyor veya düşüyor. Genel broker'da client başına saniyede 10 mesajın ve mesaj başına 64 KB'ın altında kalın; hız sınırlama bunu halleder.
- Yanlış sınıflar. Önceden eğitilmiş model yalnızca COCO sınıflarını bilir. Forkliftler, baretler veya belirli ürünler için kendi görüntülerinizle özel bir model eğitin.
Üretim Notları
Gerçek kameralarda, kimlik bilgileriyle TLS (8883 portu) üzerinden özel bir broker'a yayın yapın ve insanların göründüğü kareleri asla genel bir topic'e göndermeyin. ConnectMQ gibi yönetilen bir MQTT broker kimlik doğrulamayı, sertifikaları ve izlemeyi üstlenir; canlı topic gezgini de tespitlerin aktığını doğrulamanın hızlı bir yoludur. Genel MQTT test broker'ını yalnızca test sahneleriyle geliştirme için kullanın.
Kameranız bir NVIDIA kartında çalışıyorsa GPU hızlandırmalı çıkarım için MQTT ile NVIDIA Jetson yazısına, mikrodenetleyici üzerinde düşük maliyetli bir varyant için ise ESP32-CAM ile kişi tespiti yazısına bakın. Yapay zeka ve IoT rehberi, görünün diğer uç yapay zeka iş yükleriyle nasıl bir araya geldiğini açıklıyor.
ConnectMQ ile Başlayın
app.connectmq.com adresinde ücretsiz Serverless planında kredi kartı gerektirmeden özel bir ConnectMQ broker'ı oluşturun, client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD") ve client.tls_set() satırlarını ekleyin, 8883 portuna geçin; kameranızın tespitleri artık güvenli şekilde akıyor.
Sık Sorulan Sorular
Kamera karelerini tespitlerle birlikte MQTT üzerinden gönderebilir miyim?
Broker'ın mesaj boyutu sınırı içinde, ayrı bir topic'te JPEG anlık görüntüler gönderebilirsiniz; ancak sürekli videoyu bir akış protokolünde tutun. Tespitler küçük ve karesiz kalmalıdır.
Hangi YOLO model boyutunu kullanmalıyım?
CPU'lar ve küçük kartlar için nano modelle başlayın; yalnızca doğruluk yeterli değilse small veya medium modele geçin. Daha büyük modeller gerçek zamanlı hızlar için GPU gerektirir.
Kişileri kare başına tespit etmek yerine nasıl sayarım?
ID atamak için takipçiyi kullanın ve her ID'yi bir çizgiyi geçtiğinde veya bir bölgeye girdiğinde bir kez sayın. Her geçişi bir olay olarak yayınlayın ve aşağı akışta toplayın.
YOLO modelini broker mı çalıştırır?
Hayır. Model kameranızın bağlı olduğu bilgisayarda çalışır; broker yalnızca ortaya çıkan mesajları abone olan herkese taşır.



