7. ünite / 12
Konturlar ve şekil öznitelikleri: say, ölç, sınıflandır
findContours, alan ve çevre, momentler ve ağırlık merkezi, sınırlayıcı kutu, approxPolyDP, dairesellik ve dışbükeylik.
Bu ünitenin sonunda
- İkili maskeden konturları bulmak ve nesneleri saymak
- Alan, çevre, ağırlık merkezi ve sınırlayıcı kutuyu hesaplamak
- Douglas-Peucker ile konturu çokgene indirip köşe sayısından şekil tahmin etmek
- Dairesellik ve dışbükeylik (solidity) ile ölçeğe bağımsız öznitelikler kurmak
Ders notları
Kontur, bir nesnenin sınırını izleyen nokta dizisidir. cv2.findContours ikili görüntüde beyaz bölgelerin sınırlarını bulur; RETR_EXTERNAL yalnız dış sınırları, RETR_TREE iç içe delikleri de hiyerarşiyle verir.
Ölçüler
- Alan (
contourArea): ayakkabı bağı formülü, ½·|Σ(xiyi+1 − xi+1yi)|. - Çevre (
arcLength): ardışık noktalar arası uzaklıkların toplamı. - Momentler: m00 alan, ağırlık merkezi (m10/m00, m01/m00).
- Sınırlayıcı kutu (
boundingRect) ve en küçük döndürülmüş kutu (minAreaRect).
Şekil tanıma
approxPolyDP (Douglas-Peucker) konturu, her noktası en fazla ε uzakta kalacak biçimde daha az köşeli bir çokgene indirir; ε genelde çevrenin %1–3'üdür. Üç köşe üçgen, dört köşe dörtgen (en/boy oranı ≈ 1 ise kare), çok köşe ve yüksek dairesellik daire demektir.
Bu oranlar ölçekten bağımsızdır: nesne kameraya yaklaşsa da değişmez. Bu yüzden basit sınıflandırıcılar için iyi özniteliklerdir.
Oyun alanı
Konturlar ve şekil öznitelikleri
Eşiklenmiş görüntüde her nesnenin dış sınırı bulunur. Alan, çevre, dairesellik (4πA/P²), sınırlayıcı kutu ve çokgen yaklaşımındaki köşe sayısı sağdaki tabloda; köşe sayısına göre şekil adı tahmin edilir.
| # | Alan | Çevre | Dairesellik | Köşe | Kutu | Şekil |
|---|---|---|---|---|---|---|
| 1 | 5039 | 260.5 | 0.93 | 8 | 79×79 | daire |
| 2 | 4353 | 257.7 | 0.82 | 4 | 66×66 | kare |
| 3 | 4317 | 269.7 | 0.75 | 4 | 90×48 | dikdörtgen |
| 4 | 4205 | 249.1 | 0.85 | 6 | 80×70 | altıgen |
| 5 | 3751 | 239.1 | 0.82 | 5 | 74×71 | beşgen |
| 6 | 1903 | 199.7 | 0.60 | 3 | 64×56 | üçgen |
Kendin dene
Renkli şekillerde tablodaki köşe sayılarına ve daireselliğe bak: hangi şekil en yuvarlak? ε oranını %1'den %8'e çıkar: altıgen ve daire hangi değerde yanlış sınıflanmaya başlıyor? Sonra gürültülü pullara geç: önce kontur sayısını, sonra en küçük alan sınırını 50 yapınca kalan sayıyı yaz. Kendi fotoğrafını (beyaz kâğıtta birkaç nesne) yükle ve aynı sayımı dene.
Kod
import cv2
import numpy as np
img = cv2.imread('girdi.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, bw = cv2.threshold(cv2.GaussianBlur(gray, (5, 5), 0), 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
if (bw > 0).mean() > 0.5:
bw = 255 - bw # nesneler beyaz, arka plan siyah olmalı
contours, hierarchy = cv2.findContours(bw, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
out = img.copy()
for cnt in contours:
A = cv2.contourArea(cnt)
if A < 200: # küçük gürültüyü atla
continue
P = cv2.arcLength(cnt, True)
circ = 4 * np.pi * A / (P * P) # daire 1, kare yaklaşık 0,785
approx = cv2.approxPolyDP(cnt, 0.02 * P, True)
M = cv2.moments(cnt)
cx, cy = int(M['m10'] / M['m00']), int(M['m01'] / M['m00'])
v = len(approx)
name = {3: 'tri', 4: 'quad'}.get(v, 'circle' if circ > 0.8 else f'{v}-gon')
x, y, w, h = cv2.boundingRect(cnt)
print(f'{name:7s} A={A:7.0f} P={P:6.1f} circ={circ:.2f} merkez=({cx},{cy}) box={w}x{h}')
cv2.drawContours(out, [approx], -1, (0, 0, 255), 2)
cv2.putText(out, name, (cx - 20, cy), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1)
cv2.imwrite('cikti.png', out)Sık yapılan hatalar
- findContours'a gri ya da renkli görüntü vermek: ikili (0/255) tek kanallı görüntü ister. Önce eşikle.
- Siyah nesne beyaz zeminde: OpenCV beyaz bölgeleri nesne sayar, zemini tek dev kontur olarak bulursun. Maskeyi ters çevir.
- Küçük gürültü konturlarını süzmemek: sayım şişer. En küçük alan sınırı koy ya da önce açma uygula.
- approxPolyDP'de sabit ε (piksel) kullanmak: büyük nesnede çok köşe, küçükte az köşe çıkar. ε'yi çevreye oranla.
Yazılım mühendisliği bağlantısı
Kontur öznitelikleri basit bir kural tabanlı sınıflandırıcıya girer. Kuralları kodun içine dağıtma; bir tabloda topla.
- Kuralları (köşe sayısı, dairesellik aralığı) veri olarak tut, her kural için bir test yaz.
- Yanlış sınıflanan örnekleri bir klasörde biriktir; kural değiştikçe bu "regresyon seti" ile sına.
Kendini sına
Yarıçapı 10 px olan bir dairenin dairesellik değeri (4πA/P²) yaklaşık kaçtır?
Kenar uzunluğu 20 px olan bir karenin dairesellik değeri yaklaşık kaçtır?
approxPolyDP'de ε neden çevrenin bir oranı olarak seçilir?
Ağırlık merkezi momentlerden nasıl bulunur?
Bu üniteden sonra bitirme projesinde
- Köşe bulma: kose_bul ve kose_sirala; altın sette G1 ölçümü ve başarısız örneklerin listesi.
