· Hakan Çelik · OpenCV / Görüntü İşleme · 5 dk okuma
GrabCut ile Etkileşimli Ön Plan Çıkarma

OpenCV Serisi 31/64
- 1. Boya Fırçası Olarak Fare
- 2. Canny Kenar Algılama
- 3. Görüntü Geçişleri
- 4. Görüntü Piramitleri
- 5. Görüntülerde Aritmetik İşlemler
- 6. Görüntülerle İlgili Temel İşlemler
- 7. Görüntünün Geometrik Dönüşümleri
- 8. Görüntüyü Yumuşatma - ( Smoothing Images )
- 9. Histogramlar
- 10. Konturler ( Contours )
- 11. Morfolojik Dönüşümler
- 12. Opencv Nedir Ve Kurulumu
- 13. Opencv Resim Işlemleri
- 14. Opencv Video Işlemleri
- 15. Opencv'de Çizim Fonksiyonları
- 16. Performans Ölçüm Ve Geliştirme Teknikleri
- 17. Renk Alanlarını Değiştirme
- 18. Renk Paleti Olarak Parça Çubuğu ( Trackbar )
- 19. Resim Eşikleme
- 20. Şablon Eşleştirme
- 21. Hough Doğru Dönüşümü
- 22. Hough Daire Dönüşümü
- 23. Fourier Dönüşümü
- 24. Histogram Eşitleme
- 25. 2B Histogramlar
- 26. Histogram Geri Projeksiyonu
- 27. Kontur Özellikleri
- 28. Kontur Nitelikleri
- 29. Konturlerle Daha Fazla İşlev
- 30. Kontur Hiyerarşisi
- 31. GrabCut ile Etkileşimli Ön Plan Çıkarma
- 32. Watershed Algoritması ile Görüntü Segmentasyonu
- 33. Özellikleri Anlamak
- 34. Harris Köşe Tespiti
- 35. Shi-Tomasi Köşe Dedektörü ve İzlenecek İyi Özellikler
- 36. SIFT'e Giriş (Ölçek Değişmez Özellik Dönüşümü)
- 37. SURF'e Giriş (Hızlandırılmış Sağlam Özellikler)
- 38. Köşe Tespiti için FAST Algoritması
- 39. BRIEF — İkili Sağlam Bağımsız Temel Özellikler
- 40. ORB (Yönlü FAST ve Döndürülmüş BRIEF)
- 41. Özellik Eşleştirme
- 42. Özellik Eşleştirme + Nesneleri Bulmak için Homografi
- 43. Meanshift ve Camshift ile Nesne Takibi
- 44. Optik Akış
- 45. Arka Plan Çıkarma
- 46. Kamera Kalibrasyonu
- 47. Poz Tahmini
- 48. Epipolar Geometri
- 49. Stereo Görüntülerden Derinlik Haritası
- 50. k-En Yakın Komşuyu Anlamak
- 51. kNN ile El Yazısı OCR
- 52. SVM'yi Anlamak
- 53. SVM ile El Yazısı OCR
- 54. K-Ortalamalar Kümeleme'yi Anlamak
- 55. OpenCV'de K-Ortalamalar Kümeleme
- 56. Görüntü Gürültü Giderme
- 57. Görüntü Onarımı (Inpainting)
- 58. Yüksek Dinamik Aralık (HDR) Görüntüleme
- 59. Haar Cascade ile Yüz Tespiti
- 60. pip ile OpenCV Kurulumu
- 61. Ubuntu'da OpenCV-Python Kurulumu
- 62. Fedora'da OpenCV-Python Kurulumu
- 63. Windows'ta OpenCV-Python Kurulumu
- 64. OpenCV-Python Bağlayıcıları Nasıl Çalışır?
GrabCut ile Etkileşimli Ön Plan Çıkarma
Hedefler
Bu bölümde:
- Görüntülerde ön planı çıkarmak için GrabCut algoritmasını göreceğiz
- Bu amaçla etkileşimli bir uygulama oluşturacağız
Teori
GrabCut algoritması, Microsoft Research Cambridge’den Carsten Rother, Vladimir Kolmogorov ve Andrew Blake tarafından “GrabCut”: iterative graph cut kullanarak etkileşimli ön plan çıkarma adlı makalede tasarlanmıştır. Minimal kullanıcı etkileşimiyle ön plan çıkarma için bir algoritma gerekiyordu ve sonuç GrabCut oldu.
Kullanıcı açısından nasıl çalışır? Başlangıçta kullanıcı, ön plan bölgesinin etrafına bir dikdörtgen çizer (ön plan bölgesi tamamen dikdörtgenin içinde olmalıdır). Ardından algoritma, en iyi sonucu elde etmek için bunu yinelemeli olarak segmentler. Tamam. Ancak bazı durumlarda segmentasyon iyi olmayabilir; örneğin bazı ön plan bölgelerini arka plan olarak, bazı arka plan bölgelerini ön plan olarak işaretlemiş olabilir. Bu durumda kullanıcının bazı ince düzenlemeler yapması gerekir. Hatalı sonuçların olduğu görüntü üzerinde çizgiler çizmeniz yeterlidir. Bu çizgiler temelde şunu söyler: “Hey, bu bölge ön plan olmalı, arka plan olarak işaretledin, bir sonraki iterasyonda düzelt” ya da tam tersi. Bir sonraki iterasyonda daha iyi sonuçlar alırsınız.
Aşağıdaki görüntüye bakın. İlk olarak oyuncu ve top mavi bir dikdörtgenin içine alınır. Ardından beyaz çizgilerle (ön planı gösteren) ve siyah çizgilerle (arka planı gösteren) bazı son düzenlemeler yapılır. Ve güzel bir sonuç elde edilir:

Peki arka planda ne oluyor?
- Kullanıcı dikdörtgeni girer. Bu dikdörtgenin dışındaki her şey kesin arka plan olarak alınır (bu yüzden dikdörtgeninizin tüm nesneleri içermesi gerektiği daha önce belirtilmiştir). Dikdörtgenin içindeki her şey bilinmeyendir. Benzer şekilde, kullanıcının ön planı veya arka planı belirten girdiler “sabit etiketleme” olarak kabul edilir; bu, süreçte değişmeyecekleri anlamına gelir.
- Bilgisayar, verdiğimiz verilere göre başlangıç etiketlemesi yapar. Ön plan ve arka plan piksellerini etiketler.
- Şimdi ön planı ve arka planı modellemek için bir Gauss Karışım Modeli (GMM) kullanılır.
- Verdiğimiz verilere bağlı olarak, GMM yeni piksel dağılımları öğrenir ve oluşturur. Yani bilinmeyen pikseller, renk istatistikleri açısından diğer sabit etiketlenmiş piksellerle ilişkilerine bağlı olarak muhtemel ön plan veya muhtemel arka plan olarak etiketlenir (sadece kümeleme gibi).
- Bu piksel dağılımından bir grafik oluşturulur. Grafikteki düğümler piksellerdir. İki ek düğüm eklenir: Kaynak düğüm ve Havuz düğümü. Her ön plan pikseli Kaynak düğümüne, her arka plan pikseli ise Havuz düğümüne bağlanır.
- Pikselleri kaynak/son düğüme bağlayan kenarların ağırlıkları, pikselin ön plan/arka plan olma olasılığıyla tanımlanır. Pikseller arasındaki ağırlıklar, kenar bilgisi veya piksel benzerliğiyle tanımlanır. Piksel renginde büyük bir fark varsa, aralarındaki kenar düşük bir ağırlık alır.
- Ardından, grafiği segmentlemek için bir minimum kesme (mincut) algoritması kullanılır. Minimum maliyet fonksiyonuyla kaynak düğümü ve havuz düğümünü ayırarak grafiği iki parçaya böler. Maliyet fonksiyonu, kesilen tüm kenarların ağırlıklarının toplamıdır. Kesimden sonra Kaynak düğümüne bağlı tüm pikseller ön plan, Havuz düğümüne bağlı olanlar ise arka plan olur.
- Sınıflandırma yakınsayana kadar süreç devam eder.
Aşağıdaki görüntüde bu süreç gösterilmektedir (Görüntü kaynağı: http://www.cs.ru.ac.za/research/g02m1682/):

Demo
Şimdi OpenCV ile GrabCut algoritmasına geçelim. OpenCV bunun için cv.grabCut() fonksiyonuna sahiptir. Argümanlarına bakalım:
- img — Giriş görüntüsü
- mask — Hangi alanların arka plan, ön plan veya muhtemel arka plan/ön plan olduğunu belirttiğimiz maske görüntüsü. Bu cv.GC_BGD, cv.GC_FGD, cv.GC_PR_BGD, cv.GC_PR_FGD bayraklarıyla veya görüntüye 0, 1, 2, 3 geçirerek yapılır.
- rect — Ön plan nesnesini içeren dikdörtgenin koordinatları: (x, y, w, h) formatında
- bdgModel, fgdModel — Algoritma tarafından dahili olarak kullanılan diziler. Sadece boyutu (1, 65) olan iki np.float64 tipi sıfır dizisi oluşturun.
- iterCount — Algoritmanın çalışması gereken iterasyon sayısı
- mode — cv.GC_INIT_WITH_RECT veya cv.GC_INIT_WITH_MASK ya da birleşimi olmalıdır; dikdörtgen mi yoksa son dokunuş çizgileri mi çizdiğimize karar verir.
Önce dikdörtgen modunu görelim. Görüntüyü yüklüyoruz, benzer bir maske görüntüsü oluşturuyoruz, fgdModel ve bgdModel oluşturuyoruz, dikdörtgen parametrelerini veriyoruz ve algoritmayı 5 iterasyon çalıştırıyoruz:
import numpy as np
import cv2 as cv
from matplotlib import pyplot as plt
img = cv.imread('messi5.jpg')
assert img is not None, "file could not be read, check with os.path.exists()"
mask = np.zeros(img.shape[:2], np.uint8)
bgdModel = np.zeros((1, 65), np.float64)
fgdModel = np.zeros((1, 65), np.float64)
rect = (50, 50, 450, 290)
cv.grabCut(img, mask, rect, bgdModel, fgdModel, 5, cv.GC_INIT_WITH_RECT)
mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
img = img * mask2[:, :, np.newaxis]
plt.imshow(img), plt.colorbar(), plt.show()Sonuçlara bakın:

Messi’nin saçları gitti. Kim Messi’yi saçsız sever? Geri getirmemiz gerekiyor. Yani orada 1-piksel (kesin ön plan) ile ince bir dokunuş yapacağız. Aynı zamanda resme giren zemin ve logo gibi istemediğimiz kısımlar da var. Onları kaldırmamız gerekiyor, bunlar için 0-piksel (kesin arka plan) dokunuşu yapıyoruz:
# newmask el ile etiketlediğim maske görüntüsüdür
newmask = cv.imread('newmask.png', cv.IMREAD_GRAYSCALE)
assert newmask is not None, "file could not be read, check with os.path.exists()"
# beyaz işaretli yerleri (kesin ön plan) mask=1 yap
# siyah işaretli yerleri (kesin arka plan) mask=0 yap
mask[newmask == 0] = 0
mask[newmask == 255] = 1
mask, bgdModel, fgdModel = cv.grabCut(img, mask, None, bgdModel, fgdModel, 5, cv.GC_INIT_WITH_MASK)
mask = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')
img = img * mask[:, :, np.newaxis]
plt.imshow(img), plt.colorbar(), plt.show()Sonuca bakın:

İşte bu kadar. Dikdörtgen modunda başlatmak yerine, doğrudan maske moduna geçebilirsiniz. Sadece maske görüntüsündeki dikdörtgen alanını 2-piksel veya 3-piksel (muhtemel arka plan/ön plan) ile işaretleyin. Ardından ikinci örnekteki gibi kesin_ön_planı 1-piksel ile işaretleyin. Sonra GrabCut fonksiyonunu doğrudan maske moduyla uygulayın.
Alıştırmalar
- OpenCV örnekleri, GrabCut kullanan etkileşimli bir araç olan grabcut.py’yi içerir. Kontrol edin. Ayrıca nasıl kullanıldığına dair bu youtube videosunu izleyin.
- Burada, fare ile dikdörtgen ve çizgiler çizerek bu uygulamayı etkileşimli bir örneğe dönüştürebilirsiniz; çizgi genişliğini ayarlamak için kaydırma çubuğu ekleyebilirsiniz.
Hakan Çelik


