Patch Based Image Processing

Mavi Polatoğlu
KoçDigital
Published in
7 min readDec 30, 2021

Merhabalar,

Bu yazıda, “patch-based processing” diye tabir edilen ve “yama olarak işleme” gibi komik bir anlamı olan metottan bahsedeceğiz. KoçDigital olarak danışmanlığını yaptığımız bir projenin görüntü işleme tarafında kullandık. Teknik ayrıntısı gayet bol olan bu projenin içinden bu konuyu ayıklayıp en sade hâliyle sunma çabasındayız aslında.

Tek cümlede özetleyecek olursak: Patch-based processing, bir görüntüyü parçalar hâlinde işlemden geçirmek demektir.

Neden?

Neden bir görüntüyü bölmeliyim ki, diye düşünenleriniz için bu bölümü yazdık.

Bildiğiniz gibi uygulamaya bağlı olarak görüntüler 2 boyutlu ya da 3 boyutlu olabiliyor. Görüntüleri de dijital domainde belli bir genişliği (w), boyu(h) ve derinliği(d) olan matrisler olarak ifade ediyoruz. Genişliği ve boyu sırasıyla 6000x4000 pixel olan bir görüntü düşünelim (Şekil 1(a)). Kolaylık açısından bu görüntüler üzerinden bir model eğitmiş gibi yazmaya devam edeceğiz ama aslında öyle değil. Görüntüler projenin detaylarıyla beraber saklı kalması gerektiği için bu oyuncak görselleri oluşturduk.

Şimdi, diyelim ki Şekil 1(a)daki gibi bir manzara görüntüsü üzerinde Şekil 1(b) ve Şekil 1(c)de gösterilen taşıtları bölütlemeye (segmentation) çalıştığımızı varsayalım. Başka bir deyişle, derin öğrenme modeline bir manzara görüntüsü verince hangi piksellerinin bir taşıt cismine denk geldiğini söylemesini istiyoruz. Taşıtın nerede olduğunu 0’dan farklı piksel değerleri görünce, taşıtın cinsini de bu piksel kümesinin hangi renk olduğuna bakınca anlayabilmek istiyoruz. Şekil 1(e) ve Şekil 1(f)de eğitim için kullanılan maske görüntülerine yer verdik. Gördüğünüz gibi taşıtların olduğu bölgeler boyalı ve bu renkler taşıtın cinsini ifade edicek şekilde kodlu (gemiler gri, motorlar beyaz). Tabii biz eğitirken bu renk kodlarını one-hot encode dönüşümü yapıyoruz (yani aslında taşıtın cinsini mimarinin hangi output kesitinde olduğuna bakarak anlıyoruz) ama bu yazıyı daha anlaşılır kılmak için böyle gösterdik.

Modele gelecek olursak; mimarisinin girişinde bir görüntü, çıkışında da segmentasyon maskeleri olan bir Convolutional Neural Networkden (CNN) (Evrişimsel Sinir Ağı, ESA) bahsediyoruz. CNNlerin ne olduğunu, nasıl çalıştıklarını, nasıl eğitildiklerini, eğitildikten sonra nasıl kullanılabildiklerini bildiğinizi varsayıyoruz. Hedefimiz patch based processing anlatmak olduğu için modelin hangi mimariye sahip olduğu önemli değil.

CNNlerin girişte alabilecekleri input sizeı (girdi boyutu) bellidir ve literatüre bakarsanız nadiren 512x512, 640x640 gibi sayılara çıktığını görürsünüz. Normalde “Zaten CNNlere girdi olarak vermek istediğimiz görüntüleri hep resize fonksiyonu ile kabul edilen boyuta getiriyoruz” deyip geçmemiz gereken bir konu neden bizim durumumuzda bir blog post hak ediyor? Sırasıyla üç şey düşünüyor olmanız lazım: (i) manzara görüntüsünün boyutları literatürde görülen input sizelara kıyasla çok büyük; (ii) taşıtlar, görüntü üzerine minicik yerler kaplıyorlar; (iii) ilk iki maddenin sentezi olarak da resize fonksiyonunun maalesef kullanılamayacak olması çünkü resize işlemi taşıtlar gibi küçük detayları yok ediyor. Bu yüzden Şekil 2deki gibi, görüntülerin belli yerlerinden patchler (görüntücükler) alıyoruz ve asıl onları modelden geçiriyoruz.

Bu arada, patch-based processing kesinlikle bizim icat ettiğimiz bir şey değil. Sık sık medikal ve biyomedikal görüntü işleme projelerinde karşılaşılan bir metot. Neden? Çünkü alınan görüntülerin boyutları çok büyük (mesela bir hastalığın ancak yüksek çözünürlüklü görüntüler üzerinde yakalanabilen detaylara bakarak teşhis edilebildiği durumlar olabiliyor) ve bir şekilde bu görüntüyü bir CNNden geçirmemiz lazım. Nitekim bizim danışmanlığını yaptığımız projede de durum öyleydi — Üretim hattından geçen ürünlerin yüksek çözünürlüklü fotoğraflarını işlememiz gerekiyordu çünkü ürünlerin üzerinde küçük çiziklerin tespitini yapmamız isteniyordu.

“Peki sıfırdan bir CNN oluşturamaz mıyız? Girdi boyutunu 6000x4000 verebiliriz?” diye düşünenleriniz için de şöyle bir not düşmek istedim: CNNlerin girdi katmanının boyutunu artırırsanız zincirleme olarak diğer katmanların da boyutunu artırmak zorunda kalacağınız için model çok büyük boyutlara ulaşıyor. Çok büyük bir CNNi hem hafızaya sığdırmakta güçlük çekmeye başlayacaksınız hem de yavaş eğitileceği için art arda bir yığın hiperparametre denemeye zamanınız kalmayacak. Zaten CNNlerin gücü, büyük olmasından değil derin olmasından kaynaklanıyor. Tabii güçlü, yüksek hafızalı ve pahalı bir GPUyu bu iş için tahsis edebiliyorsanız durum farklı.

Nasıl?

Training (eğitim) sırasında:

Şekil 2de görüldüğü gibi görüntü üzerinden patchler alıyoruz. Patchlerin boyutlarını örnek olması için 250x250 seçtik, başka boyutlar da olabilir. Modelin inputunda görüntü patchleri, outputunda (çıktıda) da segmentasyon maske patchleri var (sırasıyla Şekil 2(b) ve Şekil 2(c)). Eğitim sırasında modele “doğru” olarak göstereceğimiz segmentasyon maske patchlerinin aynı koordinatlardan alınan görüntücükler olduğuna dikkat çekmek isteriz. Bu şekilde her batchde belli bir sayıda patch olacak şekilde modeli converge (model veriden öznitelikler çıkarıp onlar üzerinden işlem yapacak hâle gelene kadar) olana kadar eğitiyoruz.

Modelin training sırasında taşıtlı ve taşıtsız yerlerden dengeli bir şekilde örnek görmesi gerekiyor. Alınan patch sayısından direkt olarak bahsetmiyoruz aslında. Sınıfların (taşıt1, taşıt2, …, taşıtN ve taşıtsız) piksel sayısı olarak dengeli olmaları gerekiyor mümkün olduğunca. Çünkü sınıfların, optimizasyon sırasında hesaplanan loss değerine etkilerinin mümkün olduğunca eşit olması gerekiyor. Bunu sağlamak için yapılabilcekler (i) “sampling” (örnekleme) dediğimiz patch seçiminde tamamen gelişigüzel olmayan bir mantık kurmak; (ii) training sırasında patchleri klasörlerden alan generatorlere belirli kurallar getirmek; (iii) loss fonksiyonu içerisinde sınıflara ağırlıklar tanımlamak. Biz projemizde (i) ve (iii) stratejilerini uyguladık. Sampling mantığı, insan diliyle şunu yaptırtıyor: “Git, taşıtlı bölgelerden patchler al. Patchlerin merkez noktaları işaretlenen bölge üzerinde olsun. Patchlerin merkez noktaları arasındaki mesafe de belli bir sınırdan büyük olmalı.”. Sınıflara ağırlıklar tanımlarken de hiper-parametrelerde yaptığımız gibi deneme yanılma yoluyla iyi sonuçlar verdiğini gördüğümüz ağırlıklar bulmaya çalıştık. (ii) hakkında denemeleri artırmadıkça ve sistematik bir şekilde sonuçları düzenlemedikçe yazmak iyi bir fikir değil. Belki başka bir blog post konusu olabilir.

Inference sırasında (model canlıya alındığında):

Modeli eğittik ve sıra modeli kullanmaya geldi. Inference sırasında elimizde etiketlerin olmadığını ve dolayısı ile “sampling” yaparken aynı mantığı uygulayacak veriye sahip olmadığımızı hatırlatmakta yarar vardır. Görüntünün tamamını taramak dışında bir çaremiz yoktur. Bunun için de “sliding-window” dediğimiz bildiğiniz yan yana alt alta grid şeklinde patchler almamız gerekiyor. Üstelik çıktının yine 6000x4000 pixel boyutlarında bir maske olması beklendiği için “reconstruction” (yeniden birleştirme) denilen işlemin uygulanması gerekiyor. Reconstruction, insan diliyle patchlerin merkez koordinatlarını kaydederek modelden geçtikten sonra gidip yine aynı yerine oturtmak şeklinde söylenebilir. Yani patchleri doğru sıralarıyla birleştirme işlemi.

Şekil 3(a) eğitim kümesinde olmamakla beraber yine taşıtların görüntüye göre küçük olduğu bir manzara resmidir. Sliding-window tipi sampling yapıldığı için inputta bu sefer görüntünün heryerinden patchler var. Şekil 3(b)de sıralı bir şekilde bu grid üzerinden alınan patchlere örnekler vermeye çalıştık. Şekil 3(c), Şekil 3(b)deki patchlerin modelden geçmiş hâlidir. İyi eğitilmiş bir model olduğunu varsayarsak geminin olduğu patchlerde gri bölgeler olmasını bekliyoruz. Groundtruth segmentasyonlar (etiketli veriler) ile tıpa tıp aynı ya da yüksek keskinlikte olmasa da geminin olduğu bölgeler segmentlenmiştir. Son patch, denizin üzerinde bolca köpüğün olduğu yerlerden alınan bir bölgeye denk gelmiş. Şekil 3(c)nin en alttaki segmentasyonunda beyaz noktalar ile modelin noise (gürültü) yapabileceğini hatırlatmaya çalıştık. Yani oralarda tabiiki motorsiklet yok ama model köpük görmediyse ve motorsiklet sınıfını çok iyi öğrenmediyse bu tür karışıklıklar yaşanabilir. Noiselar reconstructiondan sonra da önce de filtrelenebilir. Son adıma gelecek olursak, Şekil 3(d)nin Şekil 3(a)ya denk gelen segmentasyonu olmasını bekliyoruz ki görüldüğü üzere gemilerin olduğu yerler griye boyanmıştır.

Evaluation sırasında (değerlendirme):

Evet, kaçış yok. Görüntü işleme kullanılan ileri analitik projelerinde de Key Performance Indicator (KPI)lar business tarafından sıkça sorulur. Ve maalesef CNNlerin performansını takip ederken kullandığımız metrikler direkt olarak kullanılamaz. Çünkü bu metrikler (i) patch bazında işlem yapan bir modelin performansına yöneliktir; ve (ii) zaten “business dilinde” değildir. Biz de patch bazındaki metrikleri daha çok model eğitirken, hiper-parametreleri ayarlarken kullandık. Görüntüyü reconstruct ettikten sonra hesaplanabilen metrikleri de çalışmamızı başkalarıyla paylaşırken ve modelleme tarafında yaptıklarımızın business çıktısı üzerindeki etkisini incelemek için kullandık.

Patch bazındaki metrikler şunlardır: training/validation/test accuracy, training/validation/test loss ya da Dice Similarity Coefficient (DSC). Anlayacağınız üzere hiçbiri teknik olmayan bir toplantıda bahsi geçilebilecek terimler değil. Öte yandan görüntü bazındaki metriklerde durum öyle değildir. Kesinlik (precision), Duyarlılık (recall), Yanlış pozitif sayısı (false positive count) direkt olarak bu isimleriyle anılmasalar da bilinmek istenen şeyler oluyor. Bu metriklerin teknik detaylardan uzak kişilerce nasıl sorulduğunu gösterebilmek için de şöyle örnekler verilebilir: “Taşıtlardan kaç tanesini buluyor?” sorusuna duyarlılık, “Bulduklarından kaçı gerçekten bir taşıt ve kaçı doğru sınıflandırılabilmiş?” sorusuna kesinlik metrikleriyle cevap verebiliyoruz.

Patch bazındaki metriklerin neden yetersiz kalabildiğini Şekil4 ile açıklamaya çalışacağız. Diyelim ki, iki ardışık patchte bulunan bir taşıt var (Şekil 4(b)) ve model sadece birinde sıfırdan farklı pikseller verdi. Mesela, Şekil 4(c)de bir gemi olabileceğine dair gri bölgeler var ama Şekil 4(d) tamamen karanlık. Şekil 4(c) ve Şekil 4(e) ile Şekil 4(d) ve Şekil 4(f) çiftlerini kullanarak DSC değerlerinin aşağı yukarı, sırasıyla 0.80 ve 0.00 olduğunu görebilirsiniz.

Asıl business çıktısı modelin başarılı olduğu yönünde, çünkü sonuçta geminin bir bölümünü işaretleyip o bölgede bir gemi olduğu sonucuna varılmıştır. Ama patch bazındaki metriklere kalsaydık sağ taraftaki patchin DSCsinin 0.00 olmasından kaynaklı haksız bir ceza oluşturmuş olurduk. Yani eğitim sırasında kullanılan metrikler her zaman projenin ya da tüm workflowun performansını ölçemeyebiliyor.

Son

Patch based processing genel olarak derin öğrenme projelerine ekstra hiperparametreler katıyor. Patch boyutu, sınıflar arasındaki patch dengesi, uygulanabilecek augmentation (veri artırma) çeşitleri hep denenmesi gereken parametreler arasına eklenmesi gerekiyor. Bu da tabii eğitim süresinin uzaması anlamına geliyor. Ayrıca sadece patchler gören model, uzaktan anlaşılabilecek bilgilerden de yoksun kalmış oluyor. Diyelim ki uçak diye bir taşıt sınıfı olsaydı ve uçaklar görüntünün sadece üst kısımlarında bulunabilseydi, modelimizin patchlerden böyle bir öznitelik çıkarma ihtimali yoktur. Halbuki uçak sınıfını tanımlamada belki de yardımcı olabilecek bir bilgi. Bu durumda patchlerle beraber bir koordinat bilgisini de input olarak almak hiç de fena bir fikir olmuyor. Buna benzer bir stratejiyi biz de projemizde uyguladık ve performans artışı gördük. Sonuç olarak bu dezavantajlara rağmen patch based processing yine de olmazsa olmaz bir metot konumunda.

Bu yazıda patch based processing mantığının eğitim, inference ve evaluation safhalarını nasıl etkilediğini tasvir etmeye çalıştık. Umarım aklınızda bir şeyler canlanmıştır. Sağlıcakla kalın!

--

--