Gerçek Zamanlı Video İşleme İçin En Performanslı Mimari: Python, PHP, HTML ve MySQL İş Birliği
Günümüzde güvenlik, üretim, tarım ve trafik gibi birçok alanda gerçek zamanlı görüntü işleme sistemlerine ihtiyaç duyuluyor. Bu sistemlerde performans, doğruluk ve kullanılabilirlik kritik öneme sahip. Bu yazımda, Python ile yazılmış görüntü işleme motoru ve PHP+HTML ile geliştirilen kullanıcı arayüzünü bir araya getiren yüksek performanslı bir mimariyi, diğer alternatiflerle karşılaştırarak sizlerle paylaşıyorum.

Günümüzde güvenlik, üretim, tarım ve trafik gibi birçok alanda gerçek zamanlı görüntü işleme sistemlerine ihtiyaç duyuluyor. Bu sistemlerde performans, doğruluk ve kullanılabilirlik kritik öneme sahip. Bu yazımda, Python ile yazılmış görüntü işleme motoru ve PHP+HTML ile geliştirilen kullanıcı arayüzünü bir araya getiren yüksek performanslı bir mimariyi, diğer alternatiflerle karşılaştırarak sizlerle paylaşıyorum.
1. Python Görüntü İşlemede Neden Tercih Ediliyor?
Python, zengin kütüphane desteği sayesinde görüntü işleme alanında lider konumda. Bu projede:
-
OpenCV ile RTSP kamera bağlantısı ve kare analizi,
-
YOLOv8 ile nesne tespiti,
-
Pygame ile sesli alarm yönetimi sağlandı.
Ancak Python içinde GUI (örneğin PyQt, Tkinter) çalıştırıldığında, özellikle gerçek zamanlı video işlenirken ciddi performans düşüşleri gözlenebiliyor.
2. Alternatif Mimari Seçenekler
Mimari Seçenek | Artılar | Eksiler |
---|---|---|
Tamamen Python (GUI + İşleme) | - Tek dil ile geliştirme kolaylığı - Entegre yapı |
- Yüksek işlem yükü - GUI performansı video işlemeyi yavaşlatır |
Python + PyQt veya Tkinter | - Masaüstü GUI kontrolü - PyQt ile güçlü arayüz |
- Video gecikmesi ve takılmalar - Donanıma bağımlı yapı |
Python + Flask GUI (Web Tabanlı) | - Web üzerinden kontrol - Modüler yapı |
- Geliştirmesi daha karmaşık - Video stream kodlama gerekebilir |
Python (İşleme) + PHP/HTML GUI | - Tam yük ayrımı - Web arayüz esnekliği - Donanımsız erişim |
- Farklı dillerin entegrasyonu gerekir - Stream yönetimi ayrı yapılmalı |
3. Neden PHP + HTML?
Python sadece görüntü işleme ile ilgilenirken, PHP + HTML tabanlı bir web arayüzü:
-
Kullanıcıdan ayarları alır (kamera seçimi, alarm süresi, hedef nesne vs.)
-
MySQL üzerinden Python ile iletişim kurar
-
Cihazdan bağımsız olarak uzaktan erişilebilir
Bu sayede Python’un video işlemesini yavaşlatmadan profesyonel bir kullanıcı deneyimi sunulmuş olur.
4. Veritabanı Katmanı: MySQL
Tüm sistem ayarları ve çıktılar MySQL veritabanı ile merkezi şekilde yönetilir:
-
PHP arayüzü üzerinden ayarlar MySQL’e yazılır.
-
Python bu ayarları okuyarak uygulamaya alır.
-
Olası hata, log veya tespit çıktıları tekrar MySQL’e yazılarak kullanıcıya web arayüzde gösterilir.
5. Gerçek Zamanlı Video Web’e Nasıl Aktarılır?
Python tarafı Flask veya benzeri mikro sunucu ile MJPEG akışı (Motion JPEG) sağlar:
# Flask üzerinden MJPEG akışı
@app.route('/video_feed')
def video_feed():
return Response(gen_frames(), mimetype='multipart/x-mixed-replace; boundary=frame')
HTML tarafında görüntüleme ise çok basittir:
<img src="http://localhost:5000/video_feed" />
Bu yapı düşük gecikmeli ve tarayıcı dostu bir video yayını sunar.
6. Önerilen Mimari Akış
Aşağıdaki yapıyı öneriyoruz:
-
Python (backend): YOLOv8 + OpenCV + veritabanı etkileşimi
-
Flask: Video stream servisi (MJPEG)
-
PHP + HTML (frontend): Kullanıcı arayüzü, ayar yönetimi, log paneli
-
MySQL: Tüm verilerin merkezi olarak saklandığı veritabanı
Sonuç
Bu mimari, sistem kaynaklarını dengeli kullanarak hem yüksek performanslı video işleme hem de esnek bir kullanıcı arayüzü sunar. Modüler yapısı sayesinde zamanla yeni özellikler (PTZ kontrolü, çoklu kamera desteği, bulut entegrasyonu vb.) kolayca eklenebilir.
Gerçek zamanlı video işleme projelerinde performans, kullanılabilirlik ve sürdürülebilirlik dengesini kurmak istiyorsanız, bu mimariyi gönül rahatlığıyla tercih edebilirsiniz.
Örnek Uygulama:
Konuyla alakalı biraz kapsamlı, örnek bir uygulama hazırlayalım. Mimari Python 3.9.13 versiyon için hazırlanmıştır.
app.py ve index.html dosyası oluşturmakla başlayalım. app.py dosyamız projemizin kök klasöründe yer alsın.
indext.html dosyamız ise projemizin templates klasörü içinde yer alsın.
Static klasörü içinde ise medyamız olan alarm_9.mp3 dosyamız yer alsın.
app.py dosyamızın içeriği:
import cv2
from flask import Flask, render_template, Response
from ultralytics import YOLO
import threading
import pygame
import time
app = Flask(__name__)
# =================== AYARLAR ===================
CONFIDENCE_THRESHOLD = 0.3
TARGET_CLASS_ID = 0 # 0 = person
ALARM_SOUND_PATH = "static/alarm_8.mp3"
RTSP_URL = 0 # Web kamerası
class ObjectTracker:
def __init__(self, rtsp_url):
self.model = YOLO('yolov8l.pt') # YOLOv8 modeli
self.rtsp_url = rtsp_url
self.cap = self._connect_video_source()
self.latest_frame = None
self.frame_lock = threading.Lock()
self.running = True
self.capture_thread = threading.Thread(target=self._capture_frames)
self.capture_thread.start()
pygame.mixer.init()
self.alarm_playing = False
self.last_detection_time = 0 # Hedef nesnenin son görüldüğü zaman
def _connect_video_source(self):
cap = cv2.VideoCapture(self.rtsp_url)
cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
if not cap.isOpened():
print(f"RTSP bağlantısı kurulamadı: {self.rtsp_url}")
return None
return cap
def _capture_frames(self):
while self.running and self.cap and self.cap.isOpened():
ret, frame = self.cap.read()
if ret:
with self.frame_lock:
self.latest_frame = frame
else:
print("Kare alınamadı, tekrar bağlanılıyor...")
self.cap.release()
time.sleep(2)
self.cap = self._connect_video_source()
def get_detections(self, frame):
detections = []
results = self.model(frame, verbose=False, conf=CONFIDENCE_THRESHOLD)
for result in results:
for box in result.boxes:
class_id = int(box.cls)
x1, y1, x2, y2 = map(int, box.xyxy[0].cpu().numpy())
confidence = float(box.conf)
label = self.model.names[class_id]
detections.append({
'bbox': (x1, y1, x2, y2),
'center': ((x1 + x2) // 2, (y1 + y2) // 2),
'confidence': confidence,
'class_id': class_id,
'label': label
})
return detections
def play_alarm(self):
if not self.alarm_playing:
pygame.mixer.music.load(ALARM_SOUND_PATH)
pygame.mixer.music.play(loops=-1)
self.alarm_playing = True
def stop_alarm(self):
if self.alarm_playing:
pygame.mixer.music.stop()
self.alarm_playing = False
def get_frame(self):
with self.frame_lock:
if self.latest_frame is None:
return None
frame = self.latest_frame.copy()
frame_resized = cv2.resize(frame, (960, 540))
detections = self.get_detections(frame_resized)
target_detected = False
for detection in detections:
x1, y1, x2, y2 = detection['bbox']
label = detection['label']
confidence = detection['confidence']
class_id = detection['class_id']
if class_id == TARGET_CLASS_ID:
color = (0, 0, 255) # Kırmızı
target_detected = True
else:
color = (0, 255, 255) # Sarı
cv2.rectangle(frame_resized, (x1, y1), (x2, y2), color, 2)
text = f"{label} %{confidence * 100:.1f}"
cv2.putText(frame_resized, text, (x1, y1 - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2)
current_time = time.time()
if target_detected:
self.last_detection_time = current_time
self.play_alarm()
else:
if current_time - self.last_detection_time > 3:
self.stop_alarm()
ret, jpeg = cv2.imencode('.jpg', frame_resized)
return jpeg.tobytes()
# =================== FLASK ROUTES ===================
@app.route('/')
def index():
return render_template('index.html')
def generate_frames():
tracker = ObjectTracker(RTSP_URL)
while True:
frame = tracker.get_frame()
if frame is None:
continue
yield (b'--frame\r\n'
b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')
@app.route('/video_feed')
def video_feed():
return Response(generate_frames(),
mimetype='multipart/x-mixed-replace; boundary=frame')
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000, debug=True)
index.html dosyamızın içeriği:
<!DOCTYPE html>
<html lang="tr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Video Akış Sistemi</title>
<style>
/* Genel sayfa stilleri */
body {
font-family: 'Arial', sans-serif;
margin: 0;
padding: 0;
background-color: #f4f4f9;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
}
/* Ana container */
.container {
text-align: center;
background-color: #ffffff;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
padding: 30px;
max-width: 980px;
width: 100%;
}
/* Başlık stilleri */
h1 {
font-size: 36px;
color: #333;
margin-bottom: 20px;
text-transform: uppercase;
letter-spacing: 2px;
}
/* Video akışı stilleri */
.video-container {
position: relative;
overflow: hidden;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1);
background-color: #000;
}
.video-container img {
width: 100%;
border-radius: 10px;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
}
/* Footer stilleri */
footer {
margin-top: 20px;
font-size: 14px;
color: #555;
}
footer a {
color: #007bff;
text-decoration: none;
}
footer a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<div class="container">
<h1>Canlı Video Akışı</h1>
<div class="video-container">
<img src="{{ url_for('video_feed') }}" alt="Video Akışı">
</div>
<footer>
<p>© 2025 Video Akış Sistemi | <a href="#">Gizlilik Politikası</a></p>
</footer>
</div>
</body>
</html>
app.py dosyamızı çalıştırdığımızda programımız çalışacaktır.
Tarayıcıa localhost:5000 değeri ile video akışını görebiliriz.
Bu Yazıya Tepkin Nedir?






