Bir dizüstü bilgisayarla somatosensoriyel oyunlar oynayabilirsiniz! TensorFlow.js somatosensory dövüş öğreticisini gerçekleştirir

Xiaocha Derleyin ve organize edin

Qubit Üretildi | Genel Hesap QbitAI

Çocukken, oyunda kolu ovduğunuzda, gerçekte "Savaşçıların Kralı" nın hareketlerini taklit eder miydiniz? Oyun karakterlerini kontrol etmek için bedeni kullanan somatosensoriyel oyunlar uzun zamandır ortaya çıkmıştır, ancak bir somatosensoriyel tutamaç (Wii) veya somatosensoriyel kamera (Microsoft Kinect) gerektirir. Ve şimdi, dizüstü bilgisayar tüm bunları sizin için yapabilir!

Son zamanlarda adında bir kişi vardı Minko Gechev Dizüstü bilgisayarda oynamayı fark eden yazılım mühendisleri "Ölümüne kavga" (Mortal Kombat), sadece bir ön kameraya ihtiyacınız var.

5 yıl kadar erken bir zamanda, somatosensoriyel dövüş oyunları oynamanın proje sonuçlarını göstermişti:

O zamanlar uygulama planı çok basitti ve popüler AI teknolojisi kullanılmıyordu. Ancak bu algoritma mükemmel olmaktan uzaktır çünkü referans olarak tek renkli bir arka plana ihtiyaç duyar ve kullanım koşulları serttir.

Son beş yılda, hem web tarayıcısı API'si hem de WebGL önemli ilerleme kaydetti. Bu yüzden mühendis, oyun programını geliştirmek için TensorFlow.js kullanmaya karar verdi ve kişisel blogunda eksiksiz bir eğitim yayınladı.

Qubit makaleyi derledi, ana içerik modeli "Mortal Kombat" ı tanıması için eğitmektir. Bu oyunda ağırlıklı olarak boks ve tekme vardır ve model çıktısı aracılığıyla ilgili eylemleri yapmak için oyun karakterlerini kontrol eder.

Aşağıdaki blogunun ana içeriği:

Giriş

Bir eylem sınıflandırma algoritması oluşturmak için TensorFlow.js ve MobileNet kullanımıyla ilgili bazı deneyimlerimi paylaşacağım. Tam metin aşağıdaki bölümlere ayrılacaktır:

  • Görüntü sınıflandırması için veri toplayın
  • Veri iyileştirme için imgaug kullanın
  • MobileNet aktarım öğrenimini kullanın
  • İkili sınıflandırma ve N-ary sınıflandırma
  • Tarayıcıda görüntü sınıflandırmasını eğitmek için TensorFlow.js modelini kullanın

Eylem sınıflandırması için LSTM kullanımı hakkında kısa tartışma

Kullanıcının yumruk attığını, tekmelediğini veya herhangi bir şey yapmadığını ayırt etmek için dizüstü bilgisayar kamerasından gelen görüntüleri kullanan denetimli bir derin öğrenme modeli geliştireceğiz. Nihai gösteri etkisi aşağıdaki gibidir:

Bu makalenin içeriğini anlamak, temel yazılım mühendisliği ve JavaScript bilgisi gerektirir. Bazı temel derin öğrenme bilgilerine sahip olmanız yararlıdır, ancak bu bir gereklilik değildir.

Veri toplama

Derin öğrenme modellerinin doğruluğu büyük ölçüde eğitim verilerinin kalitesine bağlıdır. Bu nedenle, birincil hedefimiz zengin bir eğitim veri kümesi oluşturmaktır.

Modelimizin karakterlerin boks ve tekmelemesini tanıması gerekir, bu nedenle görseller aşağıdaki üç kategoriden toplanmalıdır:

  • boks
  • Atmak
  • diğer

Bu deney için, resim toplamama yardımcı olacak iki gönüllü buldum. Her biri 2-4 boks hareketi ve 2-4 tekme hareketi içeren toplam 5 video kaydettik. Toplanan video dosyası bir video dosyası olduğundan, onu kare kare bir resim çerçevesine dönüştürmek için de ffmpeg kullanmamız gerekir:

ffmpeg -i video.mov $ dosyaadı% 03d.jpg

Sonunda, her dizinde aşağıdaki gibi yaklaşık 200 resim topladık:

Not: Boks ve tekme atmaya ek olarak, resim kataloğunun büyük bir kısmı "diğer" kısmıdır ve temelde yürüme, dönme ve video kayıtlarını değiştirmeye ilişkin bazı resimlerdir. Bu bölümde çok fazla içerik varsa, eğitilen modelin önyargılı olma riski vardır.İlk iki kategoriye ayrılması gereken resimler "diğer" olarak sınıflandırılır, bu nedenle resmin bu kısmının miktarını azalttık.

Aynı ortamın ve aynı kişilerin bu 600 fotoğrafını kullanırsak, yüksek doğruluk elde edemeyeceğiz. Tanıma doğruluğunu daha da iyileştirmek için, örneği genişletmek için veri artırmayı kullanacağız.

Veri geliştirme

Veri artırma, mevcut verileri yeni örneklerle bütünleştiren bir tekniktir ve bu, veri setlerinin örnek boyutunu ve çeşitliliğini artırmamıza yardımcı olabilir. Orijinal görüntüyü işleyip yeni bir görüntüye dönüştürebiliriz, ancak süreç çok yoğun olmamalıdır, böylece makine yeni görüntüyü doğru bir şekilde sınıflandırabilir.

Görüntüleri işlemenin yaygın yolları arasında döndürme, renkleri tersine çevirme, bulanıklaştırma vb. Bulunur. İnternette hazır yazılım var.Python'da yazılmış bir imgaug aracı kullanacağım (proje adresi için eke bakınız) Veri geliştirme kodum aşağıdaki gibidir:

np.random.seed (44) yani tohum (44) def main (): aralıktaki i için (1, 191): draw_single_sequential_images (str (i), "diğerleri", "diğerleri-aug") aralıktaki i için (1, 191): draw_single_sequential_images (str (i), "hits", "hits-aug") aralıktaki i için (1, 191): draw_single_sequential_images (str (i), "tekmeler", "başlama-aug") def draw_single_sequential_images (dosya adı, yol, aug_path): image = misc.imresize (ndimage.imread (yol + "/" + dosya adı + ".jpg"), (56, 100)) bazen = lambda aug: iaa. Bazen (0.5, aug) seq = iaa.Sequential ( ), iaa.Sharpen (alfa = (0, 1.0), hafiflik = (0.75, 1.5)), # görüntüleri keskinleştir iaa.Emboss (alfa = (0, 1.0), kuvvet = (0, 2.0)), # kabartma resimleri iaa.AdditiveGaussianNoise (loc = 0, scale = (0.0, 0.01 * 255), per_channel = 0.5), # görüntülere gauss gürültüsü ekleyin iaa.Add ((- 10, 10), per_channel = 0.5), # görüntülerin parlaklığını değiştir (orijinal değerin -10 ila 10'u kadar) iaa.AddToHueAndSaturation ((- 20, 20)), # tonu ve doygunluğu değiştir # ya tüm görüntünün parlaklığını değiştirin (bazen # kanal başına) veya alt alanların parlaklığını değiştirin iaa.OneOf (), iaa.ContrastNormalization ((0.5, 2.0), per_channel = 0.5), # kontrastı iyileştirin veya kötüleştirin >, random_order = Doğru ) >, random_order = Doğru ) im = np.zeros ((16, 56, 100, 3), dtype = np.uint8) aralıktaki c için (0, 16): im = resim aralıktaki im için (len (ızgara)): misc.imsave (aug_path + "/" + dosya adı + "_" + str (im) + ".jpg", ızgara)

Her resim nihayet 16 resme genişletildi.Eğitim ve değerlendirme sırasındaki hesaplama miktarını daha sonra dikkate alarak resmin boyutunu küçülttük ve her resmin çözünürlüğü 100 * 56'ya sıkıştırıldı.

Modelleme

Şimdi bir resim sınıflandırma modeli oluşturmaya başlıyoruz. CNN (Convolutional Neural Network) resimleri işlemek için kullanılır.CNN, görüntü tanıma, nesne algılama ve sınıflandırma için uygundur.

Transfer öğrenimi

Transfer öğrenimi, eğitilmiş ağları kullanmamızı sağlar. Herhangi bir katmandan çıktı alabilir ve onu yeni bir sinir ağının girdisi olarak kullanabiliriz. Bu şekilde, yeni oluşturulan sinir ağını eğitmek, daha yüksek bir biliş seviyesine ulaşabilir ve kaynak modelin daha önce hiç görmediği resimleri doğru şekilde sınıflandırabilir.

Bu makalede, VGG-16 kadar güçlü, ancak tarayıcıda daha küçük boyut ve daha kısa yükleme süresine sahip MobileNet sinir ağını kullanacağız (kurulum paketi adresi için eke bakın).

Modeli tarayıcıda çalıştırın

Bu bölümde, ikili bir sınıflandırma modeli eğiteceğiz.

Öncelikle, eğitilmiş modeli tarayıcımızın oyun betiği MK.js'de çalıştırıyoruz. kod aşağıdaki gibi gösterilir:

const video = document.getElementById ('cam'); const Katman = 'global_average_pooling2d_1'; const mobilenetInfer = m = > (p): tf.Tensor < tf.Rank > = > m.infer (p, Katman); const canvas = document.getElementById ('canvas'); const scale = document.getElementById ('kırpma'); const ImageSize = { Genişlik: 100, Yükseklik: 56 }; navigator.mediaDevices .getUserMedia ({ video: doğru, ses: yanlış }) .then (akım = > { video.srcObject = akış; });

Yukarıdaki kodda bazı değişkenler ve işlevler hakkında yorumlar:

  • video: sayfadaki HTML5 video öğesi
  • Katman: Çıktıyı aldığımız ve bunu modelimizin girdisi olarak kullandığımız MobileNet katmanının adı
  • mobilenetInfer: MobileNet'ten örnekler alın ve başka bir işlev döndürür. Döndürülen işlev girdiyi kabul eder ve ilgili çıktıyı belirli bir MobileNet katmanından döndürür.
  • canvas: Alınan kareyi HTML5 tuvaline yönlendirin
  • ölçek: sıkıştırılmış çerçevenin tuvali

İkinci adımda, video elementinin kaynağı olarak kameradan video akışını elde ediyoruz. Elde edilen görüntü üzerinde gri tonlamalı filtreleme yapın ve içeriğini değiştirin:

const grayscale = (canvas: HTMLCanvasElement) = > { const imageData = canvas.getContext ('2d'). getImageData (0, 0, canvas.width, canvas.height); const data = imageData.data; for (let i = 0; i < data.length; i + = 4) { const avg = (veri + veri + veri ) / 3; veri = ort; veri = ort; veri = ort; } canvas.getContext ('2d'). putImageData (imageData, 0, 0); };

Üçüncü adım, eğitilmiş modeli oyun betiği MK.js ile bağlamaktır.

mobilenet: (p: herhangi) = > tf.Tensor < tf.Rank > ; tf.loadModel ('http: // localhost: 5000 / model.json'). sonra (model = > { mobileNet .yük() .then ((mn: herhangi) = > mobilenet = mobilenetInfer (mn)) .then (startInterval (mobilenet, model)); });

Yukarıdaki kodda, MobileNet'in çıktısını mobilenetInfer yöntemine iletiyoruz, böylece çıktıyı ağın gizli katmanından almak için bir kısayol elde ediyoruz. Ek olarak, startInterval'dan da alıntı yaptım.

const startInterval = (mobilenet, model) = > () = > { setInterval (() = > { canvas.getContext ('2d'). drawImage (video, 0, 0); gri tonlama (ölçek .getContext ('2d') .drawImage ( tuval, 0, 0, canvas.width, canvas.width / (ImageSize.Width / ImageSize.Height), 0, 0, ImageSize.Width, ImageSize.Height )); const = Array.from (( model.predict (mobilenet (tf.fromPixels (ölçek))) as tf.Tensor1D) Float32Array olarak .dataSync (); const saptama = (herhangi bir pencere) .Detect; eğer (delme > = 0.4) saptama.onPunch (); }, 100); };

startInterval anahtardır, her 100 ms'de anonim bir işleve başvurur. Bu anonim işlevde, videonun geçerli karesini tuvale koyuyoruz, ardından 100 * 56 boyutunda bir resim halinde sıkıştırıyoruz ve ardından gri tonlama filtresi için kullanıyoruz.

Bir sonraki adımda, sıkıştırılmış çerçeveyi MobileNet'e iletiyoruz ve ardından çıktıyı eğitilmiş modele iletiyoruz ve dataSync yöntemiyle tek boyutlu bir tensör delme işlemi döndürüyoruz.

Son olarak, delme olasılığının 0,4'ten yüksek olup olmadığını belirlemek için delmeyi kullanırız. Öyleyse, onPunch yöntemi çağrılır. Şimdi bir eylemi kontrol edebiliriz:

N-ary sınıflandırması ile boks ve tekmeyi tanımlayın

Bu bölümde, daha akıllı bir model tanıtacağız: üç tür hareketi ayırt etmek için sinir ağlarını kullanma: boks, tekme ve ayakta durma.

const yumruklar = gerektirir ('fs') .readdirSync (Zımbalar) .filter (f = > f.endsWith ('. jpg')) .map (f = > `$ {Zımbalar} / $ {f}`); const kicks = gerektirir ('fs') .readdirSync (Başlamalar) .filter (f = > f.endsWith ('. jpg')) .map (f = > `$ {Kicks} / $ {f}`); const diğerleri = gerektirir ('fs') .readdirSync (Diğerleri) .filter (f = > f.endsWith ('. jpg')) .map (f = > `$ {Diğerleri} / $ {f}`); const ys = tf.tensor2d ( yeni Dizi (punches.length) .fill () .concat (yeni Dizi (kicks.length) .fill ()) .concat (yeni Dizi (diğerleri.length) .fill ()), ); const xs: tf.Tensor2D = tf.stack ( yumruklar .map ((yol: dize) = > mobileNet (readInput (yol))) .concat (kicks.map ((yol: string) = > mobileNet (readInput (yol)))) .concat (diğerleri.map ((yol: dize) = > mobileNet (readInput (yol)))) ) tf.Tensor2D olarak;

Sıkıştırılmış ve gri tonlamalı görüntülerde MobileNet'i arıyoruz ve ardından çıktıyı eğitilmiş modele iletiyoruz. Model tek boyutlu bir tensör döndürür ve onu bir diziye dönüştürmek için dataSync kullanırız. Ardından, Array.from kullanarak, yazılan diziyi bir JavaScript dizisine dönüştürüyoruz, dizi, çerçevedeki üç pozu çıkarmamız için olasılıkları içerir.

Ne tekme ne de boks olasılığı 0,4'ün üzerinde değilse, hareketsiz duruma döneceğiz. Aksi takdirde, 0.32'den daha yüksek bir boks olasılığı gösterirse, MK.js'ye bir boks talimatı vereceğiz. Vuruş olasılığı 0.32'yi aşarsa, bir vuruş yaparız.

Tam gösteri etkisi aşağıdadır:

Eylem tanıma

Daha büyük bir çeşitlilik veri kümesi toplarsak, oluşturduğumuz model her çerçeveyi daha doğru işleyebilir. Ama bu yeterli mi? Tabii ki hayır, lütfen aşağıdaki iki resme bakın:

İkisi de tekme hareketleri ama aslında videoda büyük bir fark var, iki farklı hareket.

Eylemleri tanımak için, ayrıca RNN (tekrarlayan sinir ağı) kullanmamız gerekir. RNN'nin avantajı, zaman serisi problemleriyle başa çıkmaktır.

  • Doğal dil işleme, kelimelerin anlamı bağlam içinde olmalıdır
  • Geçmiş kayıtlara dayanarak, kullanıcıların ziyaret edeceği sayfaları tahmin edin
  • Eylemleri bir dizi çerçevede tanımlayın

Eylemleri tanımak için, birkaç resim karesini CNN'ye girmemiz ve ardından çıktı sonucunu RNN'ye girmemiz gerekir.

sonuç olarak

Bu yazıda, bir görüntü sınıflandırma modeli geliştirdik. Bu amaçla, video karelerini manuel olarak çıkarıyoruz ve veri kümelerini topluyoruz, bunları üç farklı kategoriye ayırıyoruz ve ardından veri geliştirme için imgaug kullanıyoruz.

Bundan sonra, transfer öğrenmenin ne olduğunu ve MobileNet'i nasıl kullandığımızı açıklamak için MobileNet kullanıyoruz. Eğitimden sonra modelimiz% 90'ın üzerinde bir doğruluk oranına ulaştı!

Tarayıcıda geliştirdiğimiz modeli kullanmak için MobileNet ile birlikte yüklüyoruz ve kullanıcının kamerasından her 100ms'de bir kare çıkarıyoruz, kullanıcının eylemlerini tanıyor ve modelin çıktısını "Mortal Kombat 3 "'ü kontrol etmek için kullanıyoruz. karakteri.

Son olarak, modelimizi RNN aracılığıyla nasıl daha da geliştirebileceğimizi kısaca tartıştık.

Umarım bu küçük projeyi benim kadar beğenirsiniz.

ek:

Orijinal adres:

https://blog.mgechev.com/2018/10/20/transfer-learning-tensorflow-js-data-augmentation-mobile-net/

Orijinal eylem tanıma proje adresi:

https://github.com/mgechev/movement.js

"Mortal Kombat" proje adresinin JS versiyonu:

https://github.com/mgechev/mk.js

imgaug:

https://github.com/aleju/imgaug

MobileNet sinir ağı:

https://www.npmjs.com/package/@tensorflow-models/mobilenet

- Bitiş -

Oyun dünyasındaki en kötü adam! Çocukluğunuzdan beri ölümcül bir hastalıktan muzdarip, sadece sevdiğiniz biriyle tanıştığınızda yedek lastik olabilir misiniz?
önceki
Zafer Kralı yine HATA mı? Oyuncu bu sefer kızgın değil: Tianmei kan alma tazminatı!
Sonraki
Zhang Jike / Wang Manyu iki puan kaybetti, karışık çiftlerde ilk 4'ü kaçırdı
Resmi yumruk nihayet dövüldü! League of Legends Unlimited Brawl Mode, ulusal sunucu 29 Ocak'ta başlayacak!
20 yılda Microsoft Research Asia'da 20 kişi
anlaştık mı! Cannavaro'nun AFC Şampiyonlar Ligi bu eski rakiple karşı karşıya gelecek
IGN puanı 8,7'ye kadar yükseldi! Bu küresel şaheserin bu hareketi Çinli oyuncuları mutlu etti!
Huawei Mate 20 Pro'nun gerçek ölçümü: Kirin 980 çipi takıldıktan sonra yapay zeka ne kadar güçlü?
Ding Ning ve Zhu Yuling "Çin Derbisi" ni kazandı, "Guangdong Çocuğu" Fan Zhendong Lin Gaoyuan zorluklarla karşı karşıya
Dota2: Liquid takımı da elendi! FNC arka arkaya iki oyun kazandı ve başarıyla ilerledi!
Musk her şeye yanıt verdi: 2018 son derece sancılı geçti, Ford bir sonraki durgunluğa pek dayanamadı
China Open single envanteri: Xu Xinyu "Korean Wave", Gu Yuting "5 Kill" Hirano Miu
LOL: Kumar kralının oğlunun takımı yine kaybetti! BLG tarafından arka arkaya iki oyun kazandınız! Oyuncu: Takım Savaşı Baharatlı Gözler
2018'de beş büyük ligin ilk hedefi doğdu, düzgün bir takım çalışması
To Top