Mikrodenetleyicilerle bir yere kadar gidiyorsunuz. Robotunuzun “önümde bir engel var” demesi yerine “önümde kırmızı bir dur işareti var” demesi gerektiğinde, Arduino sınıfı kartlar yetersiz kalıyor. İşte orada Raspberry Pi ve OpenCV devreye giriyor.
Bu rehberde Raspberry Pi üzerinde görüntü işlemeye pratik bir giriş yapıyoruz: kurulum, temel işlemler, otonom araç için şerit takibi, performans optimizasyonu ve Pi ile mikrodenetleyicinin birlikte nasıl çalıştırılacağı.
Neden Raspberry Pi
Arduino ile Raspberry Pi farklı kategorilerde. Arduino bir mikrodenetleyici, Pi ise tam bir bilgisayar: Linux çalıştırır, dosya sistemi vardır, Python kodunu doğrudan koşturur.
| Arduino / ESP32 | Raspberry Pi | |
|---|---|---|
| Yapı | Mikrodenetleyici | Tek kartlı bilgisayar |
| İşletim sistemi | Yok | Linux |
| Gerçek zamanlılık | Kesin | Kesin değil |
| Açılış süresi | Anında | 20–40 saniye |
| Analog giriş | Var | Yok (harici ADC gerekir) |
| Görüntü işleme | Yapamaz | Yapar |
| Güç tüketimi | Çok düşük | Yüksek (600 mA+) |
Bu tablodaki en önemli satır “gerçek zamanlılık”. Linux, motor kontrol döngünüzü istediği an duraklatabilir. Bu yüzden ciddi robotlarda ikisi birlikte kullanılır: Pi görür ve karar verir, mikrodenetleyici sürer.
Kurulum
Raspberry Pi OS kurulu bir sistemde OpenCV’yi paket yöneticisinden kurmak en pratik yol:
sudo apt update
sudo apt install -y python3-opencv python3-picamera2 python3-numpy
python3 -c "import cv2; print(cv2.__version__)"
pip install opencv-python ile kurmak da mümkün ama Pi üzerinde derleme gerektirebilir ve saatler sürebilir. Sistem paketi çoğu proje için yeterli.
Kameradan ilk görüntü
from picamera2 import Picamera2
import cv2
kamera = Picamera2()
kamera.configure(kamera.create_preview_configuration(
main={"format": "RGB888", "size": (320, 240)}
))
kamera.start()
while True:
kare = kamera.capture_array()
cv2.imshow("Kamera", kare)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyAllWindows()
Çözünürlüğü daha ilk satırda 320×240’a düşürdüğümüze dikkat edin. Bu, tüm rehberdeki en önemli performans kararı.
HSV: renk tabanlı algılamanın temeli
OpenCV görüntüleri varsayılan olarak BGR formatında tutar. Renk tespiti için BGR kötü bir seçimdir çünkü parlaklık ve renk bilgisi iç içe geçmiştir — bulut geçince kırmızınız artık “kırmızı” olmaz.
HSV renk uzayı bunu ayırır:
- H (Hue): Rengin kendisi, 0–179 arası. Işıktan bağımsız.
- S (Saturation): Doygunluk, 0–255. Rengin ne kadar canlı olduğu.
- V (Value): Parlaklık, 0–255.
import cv2, numpy as np
hsv = cv2.cvtColor(kare, cv2.COLOR_BGR2HSV)
# Kırmızı HSV çemberinin iki ucunda yer alır, iki aralık gerekir
alt1, ust1 = np.array([0, 120, 70]), np.array([10, 255, 255])
alt2, ust2 = np.array([170, 120, 70]), np.array([180, 255, 255])
maske = cv2.inRange(hsv, alt1, ust1) | cv2.inRange(hsv, alt2, ust2)
# Gürültü temizliği
cekirdek = np.ones((5, 5), np.uint8)
maske = cv2.morphologyEx(maske, cv2.MORPH_OPEN, cekirdek)
maske = cv2.morphologyEx(maske, cv2.MORPH_CLOSE, cekirdek)
Aşağıdaki modülde bu dört sayının ne yaptığını doğrudan görebilirsiniz. Soldaki sahnede kırmızı topu yalnız bırakacak aralığı bulmaya çalışın: önce Hue aralığını daraltın, sonra Saturation alt sınırını yükselterek soluk zemini eleyin.
Nesneyi bulmak
konturlar, _ = cv2.findContours(maske, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if konturlar:
enBuyuk = max(konturlar, key=cv2.contourArea)
if cv2.contourArea(enBuyuk) > 300: # küçük gürültüyü ele
x, y, w, h = cv2.boundingRect(enBuyuk)
merkez_x = x + w // 2
hata = merkez_x - (kare.shape[1] // 2) # PID'e girecek hata
Son satırdaki hata değişkeni tanıdık gelmiş olmalı: bu, doğrudan bir PID kontrol döngüsüne beslenebilecek konum hatasıdır. Görüntü işleme, sensör yerine geçse de kontrol matematiği aynı kalır.
Otonom araç: şerit takibi
Görüntüden şerit çıkarmanın klasik boru hattı beş adımdan oluşur.
1. Gri tonlama ve bulanıklaştırma
gri = cv2.cvtColor(kare, cv2.COLOR_BGR2GRAY)
bulanik = cv2.GaussianBlur(gri, (5, 5), 0)
2. Kenar tespiti
kenarlar = cv2.Canny(bulanik, 50, 150)
Canny’nin iki eşik değeri ayar gerektirir. Genel kural: üst eşik alt eşiğin 2–3 katı olsun. Aydınlatma değişiyorsa eşikleri görüntünün ortancasına göre otomatik hesaplayabilirsiniz.
3. İlgi alanı (ROI) maskesi
Görüntünün üst yarısında gökyüzü, ağaç, bina var — hiçbiri işinize yaramaz. Sadece yolun olduğu bölgeyi işleyin:
def ilgiAlani(img):
h, w = img.shape[:2]
maske = np.zeros_like(img)
poligon = np.array([[
(0, h), (w, h), (int(w * 0.6), int(h * 0.55)), (int(w * 0.4), int(h * 0.55))
]], np.int32)
cv2.fillPoly(maske, poligon, 255)
return cv2.bitwise_and(img, maske)
Bu adım hem doğruluğu artırır hem işlem yükünü düşürür.
4. Çizgi tespiti
cizgiler = cv2.HoughLinesP(
kenarlar, rho=1, theta=np.pi/180, threshold=40,
minLineLength=30, maxLineGap=100
)
5. Şeritleri birleştirip yön çıkarma
Hough dönüşümü size onlarca kısa çizgi döndürür. Bunları eğimlerine göre sol ve sağ şerit olarak ayırıp ortalamasını almanız gerekir:
sol, sag = [], []
for x1, y1, x2, y2 in cizgiler[:, 0]:
if x2 == x1:
continue
egim = (y2 - y1) / (x2 - x1)
if abs(egim) < 0.3: # yataya yakın çizgileri ele
continue
(sol if egim < 0 else sag).append((x1, y1, x2, y2))
# İki şeridin orta noktası, aracın gitmesi gereken yön
if sol and sag:
sol_x = np.mean([ (l[0] + l[2]) / 2 for l in sol ])
sag_x = np.mean([ (r[0] + r[2]) / 2 for r in sag ])
hedef = (sol_x + sag_x) / 2
hata = hedef - (kare.shape[1] / 2)
Yine aynı hata değişkeni. Bunu PID’e verip direksiyon açısını üretirsiniz.
Şerit tespiti kare kare bağımsız çalıştırıldığında titrer. Son 5 karenin ortalamasını almak (hareketli ortalama) görüntüyü belirgin şekilde kararlı hale getirir. Bir karede şerit bulunamazsa son geçerli değeri kullanmaya devam edin.
Performans: kare hızını yükseltmek
Raspberry Pi güçlü ama sınırsız değil. Şu dört müdahale, çoğu projede kare hızını birkaç katına çıkarır.
1. Çözünürlüğü düşürün
En büyük kazanç burada:
| Çözünürlük | Piksel sayısı | Göreli yük |
|---|---|---|
| 1920×1080 | 2.073.600 | 27× |
| 640×480 | 307.200 | 4× |
| 320×240 | 76.800 | 1× |
Şerit takibi için 320×240 fazlasıyla yeterlidir. Yüksek çözünürlük ancak küçük ve uzak nesneleri tanımanız gerekiyorsa anlamlı.
2. Kareleri atlayın
sayac = 0
while True:
kare = kamera.capture_array()
sayac += 1
if sayac % 2: # her ikinci kareyi işle
continue
isle(kare)
3. Gereksiz dönüşümleri kaldırın
Aynı karede hem HSV hem gri dönüşüm yapıyorsanız, ikisine de gerçekten ihtiyacınız olup olmadığını sorgulayın. Her cvtColor çağrısı tüm pikselleri dolaşır.
4. Görüntülemeyi kapatın
cv2.imshow() beklenenden pahalıdır. Robot sahada çalışırken pencereyi açmayın; hata ayıklarken kareyi diske kaydedin veya ağ üzerinden gönderin.
Pi ve mikrodenetleyiciyi birlikte kullanmak
Sağlam otonom araç mimarisi görevleri ayırır:
- Raspberry Pi: Kamera, görüntü işleme, karar verme, üst seviye strateji.
- Arduino / ESP32: Motor sürme, encoder okuma, PID hız kontrolü, acil durdurma.
Aralarındaki iletişim için en basit ve en güvenilir yöntem seri porttur:
# Raspberry Pi tarafı
import serial, time
mcu = serial.Serial('/dev/ttyUSB0', 115200, timeout=0.1)
time.sleep(2) # kartın açılmasını bekle
def komutGonder(hiz, direksiyon):
mcu.write(f"S{hiz},D{direksiyon}\n".encode())
// Arduino tarafı
void loop() {
if (Serial.available()) {
String satir = Serial.readStringUntil('\n');
int hiz = satir.substring(satir.indexOf('S') + 1, satir.indexOf(',')).toInt();
int dir = satir.substring(satir.indexOf('D') + 1).toInt();
motorSur(hiz, dir);
sonKomutZamani = millis();
}
// Güvenlik: Pi susarsa dur
if (millis() - sonKomutZamani > 500) {
motorDur();
}
}
Son bloktaki güvenlik zamanlayıcısı kritik. Raspberry Pi kilitlenir, Python hata verir veya USB kablosu çıkarsa, araç son komutla sonsuza kadar devam etmemeli.
Renk kalibrasyon aracı
HSV aralıklarını tahminle bulmaya çalışmak saatler yiyor. Bunun yerine kaydırıcılı küçük bir araç yazın; hedefi kameraya gösterip aralığı canlı ayarlarsınız.
import cv2, numpy as np
from picamera2 import Picamera2
def bosluk(x): pass
cv2.namedWindow("Ayar")
for ad, baslangic, maks in [("H alt",0,179), ("H ust",179,179),
("S alt",0,255), ("S ust",255,255),
("V alt",0,255), ("V ust",255,255)]:
cv2.createTrackbar(ad, "Ayar", baslangic, maks, bosluk)
kamera = Picamera2()
kamera.configure(kamera.create_preview_configuration(
main={"format": "RGB888", "size": (320, 240)}))
kamera.start()
while True:
kare = kamera.capture_array()
hsv = cv2.cvtColor(kare, cv2.COLOR_BGR2HSV)
g = lambda ad: cv2.getTrackbarPos(ad, "Ayar")
alt = np.array([g("H alt"), g("S alt"), g("V alt")])
ust = np.array([g("H ust"), g("S ust"), g("V ust")])
maske = cv2.inRange(hsv, alt, ust)
cv2.imshow("Maske", maske)
cv2.imshow("Goruntu", kare)
if cv2.waitKey(1) & 0xFF == ord('q'):
print(f"alt = {alt.tolist()}\nust = {ust.tolist()}")
break
Kaydırıcıları, maske penceresinde sadece hedef nesne beyaz kalana kadar oynatın. Çıkıştaki iki diziyi doğrudan kodunuza yapıştırın.
Kalibrasyonu robotun gerçekte çalışacağı ışıkta yapın. Atölye lambası altında bulunan aralık, gün ışığında çalışmaz. İki farklı ortam varsa iki ayrı aralık kaydedin ve koddan seçilebilir yapın.
Robot açılınca kendiliğinden başlaması
Yarışma alanında Pi’ye klavye ve monitör bağlayıp programı elle başlatmak istemezsiniz. Program, kart açılır açılmaz çalışmalı.
En sağlam yöntem systemd servisi tanımlamak:
sudo nano /etc/systemd/system/robot.service
[Unit]
Description=Robot goruntu isleme
After=multi-user.target
[Service]
Type=simple
User=pi
WorkingDirectory=/home/pi/robot
ExecStart=/usr/bin/python3 /home/pi/robot/main.py
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload
sudo systemctl enable robot.service
sudo systemctl start robot.service
# Ne olduğunu görmek için
sudo systemctl status robot.service
journalctl -u robot.service -f
Restart=always satırı önemli: Python bir hata verip çökerse servis üç saniye sonra otomatik yeniden başlar. Yarışma ortasında robotun tamamen ölmesindense yeniden başlaması iyidir.
Güvenli kapatma
Raspberry Pi bir bilgisayardır; gücü aniden kesmek dosya sistemini bozabilir. Robota bir kapatma butonu ekleyin:
import RPi.GPIO as GPIO, os, time
GPIO.setmode(GPIO.BCM)
GPIO.setup(17, GPIO.IN, pull_up_down=GPIO.PUD_UP)
while True:
if not GPIO.input(17): # butona basıldı
time.sleep(2) # yanlışlıkla basmayı ele
if not GPIO.input(17):
os.system("sudo shutdown -h now")
time.sleep(0.2)
Güç: sessiz sorun kaynağı
Raspberry Pi 4, yük altında 3 A’e yakın akım çekebilir ve besleme gerilimi 4,8 V’un altına düştüğünde sessizce yavaşlar veya yeniden başlar. Motorlarla aynı hattan beslerseniz, motor kalkışındaki gerilim çöküşü Pi’yi düşürür.
- Pi için ayrı bir 5 V / 3 A regülatör kullanın.
- Motor ve Pi hatlarının topraklarını tek noktada birleştirin.
- Pi girişine 1000 µF kondansatör ekleyin.
- Pil gerilimini izleyin — LiPo rehberindeki gerilim bölücü devresi burada da işinize yarar.
Nereden başlamalı
Doğrudan otonom araç yapmaya çalışmayın. Şu sırayla ilerleyin:
- Kameradan görüntü alın ve ekrana basın.
- Tek bir rengi (örneğin kırmızı bir top) HSV ile bulun ve merkezini yazdırın.
- Merkez konumunu seri porttan Arduino’ya gönderin, servo ile kamerayı topa çevirin.
- Robotu topa doğru sürün — ilk görsel geri beslemeli kontrol döngünüz.
- Şerit tespitine geçin.
Her adım öncekinin üstüne bina ediliyor ve her biri tek başına çalışan bir demo. Mikrodenetleyici tarafındaki temeliniz eksikse önce Arduino başlangıç rehberi, kart seçiminde kararsızsanız ESP32 mi Arduino mu yazısı iyi bir başlangıç noktası.
Frequently asked questions
Görüntü işleme için hangi Raspberry Pi modeli gerekir?
Gerçek zamanlı işleme için en az Raspberry Pi 4 (4 GB) önerilir; Pi 5 belirgin şekilde daha rahat çalışır. Pi Zero 2 W basit renk takibi yapabilir ama şerit tespiti gibi işlerde kare hızı çok düşer.
Raspberry Pi motorları doğrudan sürebilir mi?
Hayır. Pi’nin GPIO pinleri 3,3 V ve pin başına yaklaşık 16 mA verir. Motorlar için mutlaka ayrı bir sürücü kartı gerekir. Yaygın ve sağlam yaklaşım, motor kontrolünü bir Arduino/ESP32’ye bırakıp Pi ile seri port üzerinden haberleştirmektir.
OpenCV neden yavaş çalışıyor?
En yaygın sebep, tam çözünürlükte işlem yapmaktır. 1920×1080 yerine 320×240 ile çalışmak işlem yükünü yaklaşık 27 kat azaltır ve çoğu robot uygulaması için yeterli çözünürlüktür. İkinci sebep, her karede gereksiz dönüşüm yapmaktır.
Renk tespiti neden ışık değişince bozuluyor?
BGR renk uzayında parlaklık ve renk bilgisi iç içedir. HSV renk uzayına geçin: renk (Hue) kanalı parlaklıktan bağımsızdır, bu yüzden ışık değişimlerine çok daha dayanıklıdır.
Şerit takibi için görüntü işleme mi sensör mü daha iyi?
Sabit genişlikte, yüksek kontrastlı bir çizgi takip edilecekse kızılötesi sensör dizisi çok daha hızlı ve güvenilirdir. Görüntü işleme, gerçek yol şeritleri, trafik işaretleri veya nesne tanıma gerektiğinde anlamlı hale gelir.
Comments
0No comments yet. Be the first to comment!