Core ML ile Akıllı iOS Uygulamaları Nasıl Yapılır?

Core ML ile Akıllı iOS Uygulamaları Nasıl Yapılır?

Gelişen teknoloji yaşamımızı gün geçtikçe kolaylaştırıyor. Kolaylaşan hayat insanlara teknolojiye farklı açıdan bakmalarını sağlıyor. Tam bu noktada Apple, WWDC17’de Core ML adında bir kütüphane tanıttı. Bu kütüphane ile artık iOS uygulamalarımız yapay zekâ ile birlikte kullanılabiliyor. Peki bu nasıl yapılıyor gelin biraz yakından bakalım.


Core ML Modeli Nedir?

Girişte de bahsettiğimiz gibi hazır eğitilmiş Core ML modellerini Swift uygulamalarımızda kullanabiliyoruz. Fakat nedir bu model önce onu anlayalım. Oluşturulan bir makine öğrenmesi algoritmasının hazırlanan bir veri seti ile eğitilmesi sonucu oluşan yapı model adını alır. Oluşan bu modellerin Swift ile kullanılabilecek .mlmodel uzantılı haline ise Core ML modeli denir. Eğer bir model eğitmeyi bilmiyorsanız Apple tarafından hazır sunulan modelleri kullanabilirsiniz. Aslında bizde örnek uygulamamızı burada bulunan “MobileNetV2” modeli ile yapacağız.


Uygulama Tasarımı

Aslında yapacağımız uygulama oldukça basit olacak. Çünkü burada asıl amaç bir modelin Swift ile nasıl kullanıldığını öğrenmek. Bu yüzden uygulama tasarımımız için bir adet UIImageView, Label ve Button kullanacağız. Kullandığımız model bir resim tanıma modeli olduğu için buton yardımıyla kullanıcı bir resim seçecek ve model bu resimde ne gördüğünü bize Label içinde söyleyecek. Ayrıca model tahmin oranını da bizlere verdiği için bunuda Label içinde göstereceğiz.


Tasarımı Kodla Bağlamak

Bu aşama aslında oldukça basit. Eklediğimiz UIImageView, Label ve Button yapılarına sıra ile tıklayıp “Control” tuşuna basılı tutarak ViewController içerisine sürüklüyoruz.


Kullanıcının Resim Seçmesini Sağlamak

Şimdi artık projemizi kodlama vakti. Core ML ile ilgili işlemlere geçmeden önce isterseniz galeriden nasıl fotoğraf seçebileceğimize bakalım. Bunun için UIImagePickerController kullanacağız. Öncelikle buton fonksiyonumuzun içerisinde bir picker oluşturalım.


    @IBAction func changeButton(_ sender: Any) {
        let picker = UIImagePickerController()
    }

Ardından oluşturduğumuz picker değişkeniyle UIImagePickerController metotlarını kullanabilmek için delegate işlemini yapmalıyız. Bunun için ViewController‘ı UIImagePickerControllerDelegate ve UINavigationControllerDelegate ile birlikte kullanabiliriz.


class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate

Şimdi metotları kullanalım. Bunun için önce delegate metoduyla metotları kullanabilir hale getiriyoruz. Ardından sourceType metoduyla fotoğrafı nerden almak istediğimizi belirtiyoruz. Bu işlemin ardından present fonksiyonuyla oluşturduğumuz picker’ı ekranda gösterebiliriz.


    @IBAction func changeButton(_ sender: Any) {      
        let picker = UIImagePickerController()
        picker.delegate = self
        picker.sourceType = .photoLibrary
        present(picker, animated: true)
    }

Şimdi fotoğraf seçtik fakat bu seçtiğimiz fotoğrafı UIImageView’a almalıyız. Bunun için didFinishPickingMediaWithInfo fonksiyonunu kullanacağız. Burada bize bir info dizisi veriliyor. Bu dizinin içinde .originalImage diyip UIImage ile cast ediyoruz. Daha sonra dismiss ile açılan ekranı kapatıyoruz.


    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        image.image = info[.originalImage] as? UIImage
        self.dismiss(animated: true)  
    }

Uygun Modeli İndirmek

Fotoğraf seçme işlemini hallettik. Sıra bu yazımızın konusu olan asıl işleme geçelim. Bunun için girişte de dediğimiz gibi “MobileNetV2” modelini kullanacağız. Yandaki fotoğraftada gördüğünüz gibi bu modelin üç ayrı versiyonu mevcut. Burada oluşan fark aslında modelin ne kadar keskin tahmin yapabilme kabiliyetinden geliyor. Biz en iyi tahmin yapanı kullanmak istediğimiz için kırmızı ile işaretlenmiş versiyonunu indirelim.


İnen dosyayı Xcode içerisine aktarmakta bir hayli kolay. Bunun için inen dosyayı Xcode içerisine, proje dosyalarımızın arasına sürüklemek yeterli.


Core ML İşlemleri

Artık kodlama vakti. Bunun için ilk önce iki kütüphaneyi ekleyelim. Bunlar CoreML ve Vision.


import UIKit
import CoreML
import Vision

Ardından yeni bir fonksiyon oluşturacağız. Fakat bu noktada şuna değinmekte fayda var. Core ML ile çalışırken kullanmamız gereken resim formatı UIImage değil CIImage olmalı. Aksi takdirde işlem gerçekleşmeyecektir.


    func imageRecognize (image : CIImage) {
        
    }

Şimdi bu fonksiyonu resim seçme işlemi bittikten sonra çağırıp CIImage’a çevirdiğimiz görseli fonksiyonumuza verelim.


    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        
        image.image = info[.originalImage] as? UIImage
        self.dismiss(animated: true)
        
        if let selectedImage = CIImage(image: image.image!) {
            self.imageRecognize(image: selectedImage)
        }
        
    }

Bu işlemi de tamaladıysak Core ML kullanımı için en önemli son iki adıma geçelim. Bunlar Request ve Handler oluşturmak. Öncelikle bir request nasıl oluşturulur buna bakalım.


Core ML İşlemleri Bölüm 1 : Request Oluşturmak

Request oluşturmak için öncelikle bir model oluşturmalıyız. Bunun için VNCoreMLModel sınfından yararlanacağız. Bu sınıf kendisine bir model belirtilmesini istiyor. Bizde indirip hazırladığımız modelin ismini veriyoruz. Yalnız dikkat etmemiz gereken bir nokta var. İsmi verdikten sonra bir sınıf gibi sonuna parantez koyuyoruz. Bu sayede nokta koyarak model metoduna erişiyoruz. Böylece model oluşuyor.


    func imageRecognize (image : CIImage) {
        if let model = try? VNCoreMLModel(for: MobileNetV2().model) {
        
        }
    }

Ardından request oluşturabiliriz. Bunun için VNCoreMLRequest sınıfından yaralanıyoruz. Bu sınıf bizden bir model istiyor. Birde completion blok veriyor. Burada bir vnrequest ve bir error değişkeni oluşturuyoruz. Burada ki vnrequest bizim işimize en çok yarayacak kısım olacak.


    func imageRecognize (image : CIImage) {
        if let model = try? VNCoreMLModel(for: MobileNetV2().model) {
           let request = VNCoreMLRequest(model: model) { vnrequest, error in
           
           }
        }
    }

Dediğimiz gibi vnrequest bizim için oldukça önemli. Çünkü modelden gelen tahminler bir dizi halinde buradan ulaştırılıyor. Bu değişkenin results metodunu [VNClassificationObservation] ile cast ediyoruz. ‘if let’ ile bir results değişkeni oluşturup bize dönen diziyi alalım.


    func imageRecognize (image : CIImage) {
        if let model = try? VNCoreMLModel(for: MobileNetV2().model) {
           let request = VNCoreMLRequest(model: model) { vnrequest, error in
              if let results = vnrequest.results as? [VNClassificationObservation] {
              
              }
           }
        }
    }

Results dizisinin boş olup olmadığını ufak bir if bloğu ile kontrol ettikten sonra artık sonucu alma vakti. Fakat burada bir durumu daha konuşmakta fayda var. Bize gelen dizi içerisinde en kuvvetli ihtimal her zaman ilk ihtimal olur. Bu yüzden results değişkeninin first metodunu topResult değişkenine atayalım. Ardından sıra geldi sonucu Label’a yazdırmaya. Bu işlem asenkron olarak yapılacağı için DispatchQueue bloğu kullanmalıyız. Bu bloğun içerisinde topResult değişkeninin identifier metodu bize dönen veriyi verdiği için bunu Label ile kullanıyoruz. Bu model bize gelen verinin 0 ile 1 arasında tahmin derecesini de veriyor. Bunuda almak istediğimiz için topResult değişkeninin confidence metodunu önce 100 ile çarpıyoruz. Daha sonra çıkan sonucu yuvarlamamız lazım. Bunun için bir rounded değişkeni oluşturalım. ConfidenceLevel değişkenini bir Int() içerisinde 100 ile tekrar çarpıp çevirme işleminden sonra 100‘e bölelim. Bu sayede tamamen okunabilir bir sayı olacak.


    func imageRecognize (image : CIImage) {
        if let model = try? VNCoreMLModel(for: MobileNetV2().model) {
            let request = VNCoreMLRequest(model: model) { vnrequest, error in
                if let results = vnrequest.results as? [VNClassificationObservation] {
                    if results.count > 0 {
                        let topResult = results.first
                        DispatchQueue.main.async {
                            let confidenceLevel = (topResult?.confidence ?? 0) * 100
                            let rounded = Int(confidenceLevel * 100) / 100
                            self.label.text = "\(rounded)% It's a \(topResult!.identifier)"           
                    }
                 }
              }
           }
        }
    }

Request işlemi burada tamamlanıyor. Fakat farkettiyseniz request değişkenini halen kullanmadık. Çünkü bu değişkeni handler oluştururken kullanacağız. O zaman hiç durmadan bu kısma geçelim.


Core ML İşlemleri Bölüm 2 : Handler Oluşturmak

Geldik artık son kısma. Request işleminin bittiği yerde handler oluşturmaya başlayabiliriz. Bu noktada VNImageRequestHandler sınıfından yararlanacağız. Bu bizden bir ciImage istiyor. Bu kısma fonksiyonumuzda aldığımız image değişkenini veriyoruz. Yapılacak işlem tabiki de asenkron olmalı. Bunun için DispatchQueue.global kullanacağız. Aslında bu işlemin DispatchQueue.main işleminden tek farkı yapılacak işleme diğerlerine göre daha fazla önem vermesi. Bu sayede daha hızlı sonuç alabiliyoruz. DispatchQueue.global yapısına userInteractive olacak dedikten sonra bloğun içine girebiliriz. Burada bir do-try-catch bloğu kullanacağız. Try içerisinde handler.perform kullanıyoruz. Bu bizden bir request dizisi istiyor. Request bölümünde oluşturduğumuz request değişkenini bu dizinin içine koyuyoruz. Bu sayede request başlatılmış oluyor.


  let handler = VNImageRequestHandler(ciImage: image)
  DispatchQueue.global(qos: .userInteractive).async {
         do{
            try handler.perform([request])
         }catch{
            print("error")
      }
   }

Final

Artık uygulamamız hazır. Sizlerde bulduğunuz değişik yapay zekâ modelleriyle uygulamanızı güzelleştirebilir, ilgi çekici hale getirebilirsiniz. Entegre etmesi de gördüğünüz gibi bir o kadar kolay olan bu işlem kullanıcı deneyimini artırabilir ve oldukça kullanışlı hale getirebilir. Eğer başka bir örnek daha görmek isterseniz buradan yararlanabilirsiniz.


import UIKit
import CoreML
import Vision

class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    
    @IBOutlet weak var image: UIImageView!
    @IBOutlet weak var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
    }
    
    @IBAction func changeButton(_ sender: Any) {
        let picker = UIImagePickerController()
        picker.delegate = self
        picker.sourceType = .photoLibrary
        present(picker, animated: true)
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        image.image = info[.originalImage] as? UIImage
        self.dismiss(animated: true)
        
        if let selectedImage = CIImage(image: image.image!) {
            self.imageRecognize(image: selectedImage)
        }
    }
    
    func imageRecognize (image : CIImage) {
        if let model = try? VNCoreMLModel(for: MobileNetV2().model) {
            let request = VNCoreMLRequest(model: model) { vnrequest, error in
                if let results = vnrequest.results as? [VNClassificationObservation] {
                    if results.count > 0 {
                        let topResult = results.first
                        DispatchQueue.main.async {
                            let confidenceLevel = (topResult?.confidence ?? 0) * 100
                            let rounded = Int(confidenceLevel * 100) / 100
                            self.label.text = "\(rounded)% It's a \(topResult!.identifier)"
                            
                        }
                    }
                }
            }
            let handler = VNImageRequestHandler(ciImage: image)
            DispatchQueue.global(qos: .userInteractive).async {
                do{
                    try handler.perform([request])
                }catch{
                    print("error")
                }
            }
        }
    }
}
İnternet sitesi https://synta-x.com
Yazı oluşturuldu 28

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Benzer yazılar

Aramak istediğinizi üstte yazmaya başlayın ve aramak için enter tuşuna basın. İptal için ESC tuşuna basın.