Javascript ile kameranızı kullanarak nesne tanıma uygulaması — TensorFlow.js & MobileNet

Merhabalar, bu haftaki makalemde .NET dünyasından sıyrılarak sizlerle birlikte günümüzün popüler teknolojilerinden TensorFlow ile kameramızı kullanarak nesneleri anlık tanımlayabilen bir web uygulaması geliştireceğiz.

TensorFlow nedir?

Google tarafından geliştirilen derin öğrenme üzerinde kullanılan açık kaynak kodlu bir makine öğrenmesi kütüphanesidir. Özellikle Python programlama dili ile çok verimli geliştirmeler yapabilmeniz mümkün olsa da Google popülaritesini artırması ve çok daha fazla alanda kullanılabilirlik katması için TensorFlow’a Javascript dili desteği de getirmiştir. Bununla ilgili çeşitli datasetlerini TensorFlow Hub adresinde bulabilirsiniz.

Peki MobileNet nedir?

MobileNet ise kısaca bahsetmek gerekirse bir resim sınıflandırma kütüphanesidir. Özellikle mobil uygulamalar geliştirirken sıkça kullanılan bu kütüphanenin yine Javascript için de kullanılabilirlik desteği bulunmaktadır.


Projemiz Hakkında

Bu yazımdaki projemizin konusu; internet sitemizin tarayıcı üzerinden kamera iznini kullanarak kamerada görünen nesnelerin ne olabileceğini tahmin edip oranlarıyla birlikte ekrana yazdıran bir uygulama olacak.

İlgili kütüphanelerin anlaşılması için temel özelliklerini kullanarak bu uygulamayı geliştireceğiz. Nesne tanımlamaların olasılıkları İngilizce olarak çıktı verecektir. Projemizin yalnızca iki dosyası olacaktır; birincisi index.html ikincisi ise init.js dosyalarıdır.

Projemizde kameradan bir kanvasa her saniyede bir görüntü aktarılacak ve bu görüntü işlenerek arka planda MobileNet sayesinde ne olduğu tahmin edilip sitemizin ilgili alanlarında yazılacak.

Kodlardan anlaşılacağı üzere <video> tag’i içerisinde kamera görüntümüz belirecektir. <canvas> tag’inde ise kameramızdan bir saniyede bir çektiğimiz görselleri arka planda burada tutacağız. <pre> tag’i içerisinde ise canvas da tutulan görselin anlık olarak tahminini yayınlayacağız.

Şimdi Javascript dosyamızı oluşturalım. Öncelikle ana fonksiyonumuz olan setup() fonksiyonunu oluşturup içerisinde de bazı sabitlerimizi tanımlayalım:

function setup() {
let video = document.getElementById("video");
let canvas = document.getElementById("canvas");
let pre = document.getElementById("tahminler");
let model = null;
}

Kamera izinlerimizi isteyip izin verilmesi halinde <video> tag’i içerisinde kamera görüntülerimizi gösterelim:

async function startCamera() {
let stream = await navigator.mediaDevices.getUserMedia({ video: true }); //kamera izni isteyelim
video.srcObject = stream; //<video> tag'i içerisine kaynağımızı kamera olarak tanımladık
await video.play(); //asenkron olarak kameramızın görüntüsünü bu tag içerisinde görüntüleyelim
setInterval(() => takeSnapshot(), 1000); //her 1 saniyede bir görüntü çekip canvas'a göndereceğiz
}

Fonksiyon içerisinden de anlaşılacağı üzere takeSnapshot() isimli fonksiyon yardımıyla kameramızdan saniyede bir kare çekilip canvas içerisine aktarılacak:

function takeSnapshot() {
let context = canvas.getContext("2d"),
width = video.videoWidth,
height = video.videoHeight; //canvas'ı videomuzdan çekilen genişlik ve yüksekliğe uygun olarak oluşturuyoruz.
if (width && height) {
canvas.width = width;
canvas.height = height;
context.drawImage(video, 0, 0, width, height); //canvas içerisine kameradan çekilen görüntüyü işliyoruz.
classifyImage(); //MobileNet yardımıyla resim sınıflandırması yapılacak
}
}

Şimdi de sıra geldi MobileNet kütüphanesi kullanarak canvas içerisindeki resimlerin sınıflandırmasına:

async function classifyImage() {
predictions = await model.classify(canvas); //sınıflandırmalar için kullanılan method
displayPredictions(predictions); //elde edilen tahminleri gösterecek fonksiyon
}

Sınıflandırma fonksiyonumuzda görselden elde ettiğimiz tahminlerin dizisini göstermek üzere displayPredictions() fonksiyonuna aktarıyoruz. Ardından bu fonksiyon içerisinde de ilgili tahminlerde gezinerek olası en yüksek üç tahmini sitemizde göstereceğiz:

function displayPredictions(predictions) {
let val = ""; //boş tahmin tanımalaöa
for (prediction of predictions) {
let perc = (prediction.probability * 100).toFixed(2); // tanımlanan nesne olasılığını hesaplama
val += `${perc}% | ${prediction.className}\n`; //olasılığı hesaplanan nesneyi ve olasılık değerini ekleme
}
pre.innerHTML = val; //elde edilen değerleri tahminler içerisine yazdırma
}

Tüm bunların ardından MobileNet kütüphanemizi model değişkenine atayan ve kameramızı çalıştıran fonksiyonu tetikleyen ana fonksiyonumuz olan main() fonksiyonunu tanımlayalım:

async function main() {
model = await mobilenet.load();
await startCamera();
}

Javascript dosyamızı bitirmiş bulunmaktayız. Yaptıklarımızı şöyle baştan itibaren tekrar etmek gerekirse:

  • Öncelikle HTML Taglerimizi Javascript dosyamız içerisinde sabitlere tanımladık.
  • Kamera izni aldık ve kameradan gelen görüntüleri video tag’i içerisinde gösterdik.
  • MobileNet kütüphanesinde işlenmek üzere kameramızdan her bir saniyede görüntü çekerek bu görüntüyü canvas tag’imizde sakladık.
  • Canvas tag’imiz içerisindeki görüntünün ne olduğunu tahmin etmesi için MobileNet içerisindeki classify metodunu kullandık.
  • Tahminlerin ne olduğunu ve oranlarını <pre> tag’i içerisinde gösterdik.

Son olarak init.js dosyamız aşağıdaki gibi olacaktır:

Uygulamamızı çalıştırdığımızda öncelikle bizden kamera izni isteyecektir:

İzin verdikten hemen sonra kameramızın görüntüleri ekrana yansıyacak ve 1 saniye sonrasında tahminler altında listelenecektir:

BuNedir uygulamamızın son hali

Projemize https://emrekizildas.github.io/bunedir/ adresinden erişebilirsiniz. Takip ettiğiniz ve buraya kadar okuyup zaman ayırdığınız için çok teşekkür ederim. Bir sonraki yazımda görüşmek üzere!