Bu yazı bir önceki karınca kolonisi simülasyonu yazısına benzer bir yazı olacak. Önce o yazıyı okursanız JavaFX hakkında bazı bilgileri bulabilirsiniz. Gerçek zamanlı görüntü işleme projem 2010 yılında üniversite bitirme projesi olarak başlamış olan bir hobi projemdir. JavaFX ve OpenCV kullanmaktadır. Bu uygulama bir desktop uygulamasıdır ve bir videodan veya web kamerasından aldığı görüntüyü gerçek zamanlı olarak düzenleyip gösterebilmektedir. İçinde 10 'dan fazla filtre işlemi bulunmakta ve bunları üst üste ekleyebilmektedir.
Bu uygulamayı tanıtan bir video mevcut. Bu yüzden bu yazıda uygulamanın detaylarına girmeyeceğim. Fakat biraz görüntü işleme konusunda bilgi verip bu uygulamanın geçmişini ve nasıl JavaFX ve Maven projesi haline getirdiğimi anlatacağım. Bu şekilde siz de kendi bilgisayarınızda çalıştırabileceksiniz. Ayrıca karınca algoritması yazısındaki gibi kendi uygulamamı gömeceğim ve olası iyileştirmelerden de bahsedeceğim. Öncelikle videoyu buradan izleyebilirsiniz.
Yakın zamanda yapay zeka çok popüler olduğu için görüntü işleme kavramı da sanırım pek fazla açıklamaya ihtiyaç duymuyor. Çünkü muhtemelen çoğunuz görüntü işleme terimini insanları takip etmek veya nesneleri tanımak veya saymak veya araç kazalarını engellemek gibi konularla duymuşsunuzdur. Fakat bütün bunların fazla işlem gücü gerektirmeden yapılabilmesi için öncelikle görüntü işleme algoritmalarının performansı yıllar içerisinde muazzam bir şekilde iyileştirildi.
Bilgisayar ortamında resim dediğimiz kavram aslında sadece bir matristen ibaret. Satırları, sütunları ve bir de derinliği var. Bu birimlerin her birine pixel ismi verelim. Her pixel 'in 3 renk bilgisi mevcuttur. Bu da matrisin derinliğini ifade eder. Renklerin yanına bazen de alpha dediğimiz saydamlık eklenebiilyor ama çoğunlukla alpha ile uğraştıran işlemler yapmıyoruz. Renkler ise farklı yapılarda ifade edilebiliyor. Mesela toplayan veya çıkaran veya dijital renkler farklı ifade edilebiliyor. Birisi RGB (reg, green, blue) oluyor, diğeri CMY (cyan, magenta, yellow) ve diğeri de HSI (hue, saturation, intensity). Böylece her pixel 3 bileşenden oluyor. Matrisimiz ise (M x N x 3) şeklinde geliyor.
Bu matrisi tanımladıktan sonra bütün görüntü işleme alt yapısı bunun üzerinde inşa edilebiliyor. Ama matris dediğimiz şey lineer cebirdir. Evet, olayın özü matematik. Yani görüntüler veya yapay zeka gibi gösterişli kavramlar sadece görünen yüzü. Ben bazı görüntü işleme filtreleri için yapılan matematiksel işlemleri bilmeme rağmen bunları bir resim üzerine efektif bir şekilde uygulayabilmek bambaşka bir olay. Bu yüzden OpenCV veya OpenCL veya adını bile duymadığım muhtemelen python ve c++ kütüphaneleri mevcut.
Kendi uygulamamın kısaca tarihini de anlatayım. Üniversitede (2006 - 2011) C# öğrenmiş fakat bitirme projemi Java Swing ve görüntü işleme ile yapmaya karar verme cesaretini göstermiştim. Dersin hocası bana JMF (Java Media Framework) kullanabileceğimi söylemişti ve bir örnek göstermişti. Temel seviyede java biliyordum fakat JMF ve görüntü işleme tekniklerini java ile yapabilmem yaklaşık 5 ay sürdü. Çünkü gerçek zamanlı olarak videodan veya kameradan alabilmesi gerekiyordu. Bu proje bana java öğretmiş oldu. Bir video üzerine 1 çizgi attırabildiğimde 2 ay olmuştu :)
Sonunda projeyi bitirdim mezun oldum ve aradan yıllar geçti. 2016 yılında JMF 'nin artık bakımının yapılmadığını ve 64 bit sistemlerde çalışamadığını fark ettim. Bu yüzden tekrar yazmaya karar verdim. Araştırdığımda OpenCV isimli kütüphaneyi buldum ve java ile yazılabildiğini gördüm. Bu arada JavaFX de öğrenmiş ve çok sevmiştim ve projeyi JavaFX ve OpenCV projesine çevirdim. O zamanlar Netbeans kullanmıştım ve ilgili videosunu youtube 'a, kodlarını da github 'a koymuştum. Tekrar yıllar geçti :) Projeyi OpenCV 3 'ten 4 'e geçirmeye ve maven projesi haline getirerek blogda yazmaya karar verdim. Bu kadar tarih yeter sanırım. Projenin teknik detaylarını anlatayım.
Bu proje maven olmadan JDK 8 ve Netbeans ile geliştirilmişti ve bilgisayarınızda OpenCV kurmanız ve ayarlamanız gerekiyordu. Sonrasında JavaFX opensource haline geldi ve JDK 'dan çıkarıldı. Bu yüzden eğer bir JavaFX maven projesi oluşturmak istiyorsanız JDK 11 kurmanızı tavsiye ediyorum. JDK kurduktan sonra kaynak kodlarını github 'dan alabilirsiniz. Bu projeyi çalıştırmak için JavaFX veya OpenCV ayarı yapmanıza gerek kalmıyor. Çünkü pom dosyası içinde dependency ve plugin şeklinde bulunuyor.
<dependencies>
<!-- https://mvnrepository.com/artifact/org.openjfx/javafx-controls -->
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>15.0.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.openpnp/opencv -->
<dependency>
<groupId>org.openpnp</groupId>
<artifactId>opencv</artifactId>
<version>4.3.0-3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.5</version>
</plugin>
</plugins>
</build>
Fakat proje ile ilgili birkaç sorunlu nokta da var. Projeyi çalıştıran ana sınıf Launcher.java isimli sınıf. Buradaki main metodu JavaFX 'in ana sınıfı olan Application sınıfından extend edilen uygulamayı çalıştırıyor çünkü JavaFX aslında javanın bir parçası değil. Bu yüzden Launcher 'daki main metoddan çalıştırılıyor. Ayrıca proje JDK 9+ projesi olmasına rağmen module-info.java dosyasını yani java modüllerini kullanamıyorsunuz çünkü OpenCV modülleştirilemiyor nedense. Ayrıca JDK 12 veya sonrasını da kullanamıyorsunuz çünkü OpenCV initialization yani OpenCV.loadShared() metodu hata veriyor. OpenCV + maven = sorunlar sorunlar.
Bu projenin çalıştırılabilir bir Jar dosyası da maalesef mevcut değil. Çünkü bir sebepten JRE main metodunu görmüyor. Ayrıca paketin içinde OpenCV 'yi de dahil edince zaten paket boyutu 80 megabyte 'lara kara çıkıyor. İsterseniz pom dosyasında maven plugin 'leri ekleyerek paketleme ile uğraşabilirsiniz. Bir diğer garip sorun da uygulamayı IDE üzerindne çalıştırmaya çalıştığınızda oluşuyor. 2 adet main metodu buluyor çünkü css 'lerle ilgili bir JavaFX sınıfında da main metodu mevcut. Diğerini yoksayabilirsiniz yani. Bütün bu problemleri aşabilirseniz projeyi çalıştırdığınızda eğer "gri seviyesi" + "kenar yakalama" + "negatif renkler" efektlerini sırasıyla üst üste eklerseniz aşağıdaki gibi bir görüntü elde edebilirsiniz.
Uygulamayı gömme zamanı geldi :) Bu kodları ben yaklaşık 10 yıl önce geliştirdim ve 5 yıl önce güncelledim. Uygulamada değişken ve metod isimlendirmelerinde yine tutarsızlıklar var karınca algoritmasında olduğu gibi. VBox ve HBox kullanmama rağmen translateX ve translateY özellikleri ile component 'lerin yerlerini ayarlamışım. Ekranlar FXML kullanmak yerine kod ile generate ediliyor ve operasyon sayısını seçmenize izin veriyor. Bu da kodları epeyce şişiriyor. Diğer taraftan da uygulama ekran çözünürlüğünüze göre kaç operasyonun ekrana sığacağını bilebiliyor.
Bunun gibi bir görüntü işleme uygulamasının muhtemelen en büyük sorunu video codec 'leridir. Çünkü OpenCV kütüphanesi performans açısından yeterince optimize olduğu için matris işlemlerini zaten hızlı bir biçimde yapabiliyor. Ayrıca elinize gelen video veya kamera görüntüsü de muhtemelen 1080P altı ve 30 FPS 'den düşük olacaktır. Bu yüzden 10 tane farklı filtreyi üst üste eklemiyorsanız muhtemelen performans sorunu yaşamazsınız. Uygulama içerisinde kendi yazdığım bir tane multithread yapısında efekt var ve native OpenCV metodlarına göre felaket biçimde yavaş :)
Fakat konu video render etmeye ve üzerinde görüntü işleme yapmaya gelince codec 'lerle ilgilenmeniz gerekiyor. Bu görüntü işleme kütüphanelerinin bir media player uygulaması gibi fonksiyonel olma amaçları olduğunu da sanmıyorum zaten. OpenCV size resimlerden video oluşturabiliyor ama oynatmaya gelince işler karışıyor. Eğer bütün işiniz web kameraları ile ise pek sorun yaşamazsınız diye tahmin ediyorum.
Kodlarımda hiç comment yok :) Buna ben bile gıcık oluyorum baktığımda çünkü ana sınıfta 1000 satırdan fazla kod var. Arayüzü esnek yapabilmek ve 20 'ye kadar operasyonu sığdırabilmek için arayüz ile ilgili kodlar da biraz karışmış durumda demiştim. Ayrıca efektleri uygulamak için bir tasarım deseni de uygulamam mantıklı olabilirdi. Çünkü uygulama aslında command ve chain of responsibility desenlerinin karışımı olabilir gibi görünüyor. Uygulamada video açtığınızda kontrol edemiyorsunuz ve oynayıp gidiyor. Bir noktayı kaçırdığınızda baştan başlatmak zorunda kalıyorsunuz.
Mobil oyun reklamı gibi başlık oldu bu. Bu yazıda yazdığım görüntü işleme uygulamamı anlattım. Bu uygulamanın OpenCV 3 Android versiyonu ile çalışan mobil uygulaması da play store 'da mevcut. Fakat masaüstü uygulaması kadar bakımı yapılmış değil maalesef. Görüntü işleme günümüzde çokça yüz tanıma, nesne bulma veya tanıma veya bilgi gizleme işlemlerinde kullanılıyor. Yakın zamanda da arttırılmış gerçeklik konusunda da görüntü işleme çok kullanışlı olacaktır. Normalde gözünüzle ayırt edemeyeceğiniz çok küçük düzensizlikleri veya farkları bilgisayarda bulmanız gayet kolaydır. Benim uygulamam öğrenenler için deneyler yapabilecekleri bir araç olmuş oldu. Aynı zamanda JavaFX, OpenCV ve Maven üçlüsü için güncel bir örnek de sunmuş oldum. Bir sonraki yazıda görüşmek üzere :)
Bir yorum yazabilirsiniz