Cara Menggunakan Gerakan Wajah Untuk Berinteraksi Dengan Tipografi

Diterbitkan: 2022-03-10
Ringkasan cepat Dalam artikel ini, kami akan membahas cara menggabungkan Pembelajaran Mesin, font variabel, dan kisi CSS untuk membuat tata letak yang merespons kedekatan, kemiringan, dan jumlah wajah pengguna.

Desainer web selalu mencari cara baru untuk meningkatkan penyajian konten halaman. Terkadang, ini dapat mengarah pada solusi yang cerdik atau untuk berinteraksi dengan teknologi yang sering kali dijauhkan dari bidang desain. Dalam artikel ini kami akan membawa tipografi yang berhubungan dengan Kecerdasan Buatan, menggunakan pembelajaran mesin untuk mendeteksi hal-hal seperti kedekatan wajah pengguna untuk meningkatkan keterbacaan teks.

Kami akan bereksperimen tentang cara menggunakan pengenalan wajah dengan Tensorflow untuk mengekstrak beberapa informasi dari kamera, seperti jarak antara layar dan wajah pengguna atau jumlah orang yang membaca halaman. Kemudian, kami akan meneruskan data tersebut ke CSS untuk menyesuaikan tipografi dan menyesuaikan tata letak halaman.

Apa itu Tensorflow?

Tensorflow adalah platform sumber terbuka dari Google untuk Pembelajaran Mesin. Machine Learning adalah bidang Ilmu Komputer yang mempelajari algoritme yang belajar mengenali hubungan kompleks dan pola berulang dari gambar, trek audio, deret waktu, teks alami, dan data secara umum. Algoritma ini menghasilkan model matematika (juga disebut model terlatih), yang merupakan semacam skema yang dapat digunakan untuk membuat keputusan berdasarkan data input. Jika Anda ingin mendekati topik, Charlie Gerard menulis tentang ML untuk pengembang frontend di sini di Smashing Mag.

Tensorflow menyediakan banyak alat untuk pengembang AI, ilmuwan data, matematikawan, tetapi jangan panik jika analisis data bukan pekerjaan harian Anda! Kabar baiknya adalah Anda tidak perlu menjadi ahli untuk menggunakannya, selama Anda menggunakan model yang dibuat sebelumnya, seperti yang akan kita lakukan.

Model Tensorflow tersedia untuk digunakan di Web dengan JavaScript SDK-nya.

Mempersiapkan

Untuk mulai menggunakan algoritme pengenalan wajah, kita perlu mengikuti beberapa langkah:

  • memuat Tensorflow SDK.
  • memuat perpustakaan Facemesh yang berisi model matematika.
  • mengakses kamera pengguna dan mengalirkannya ke elemen video HTML. Facemesh akan menganalisis bingkai dari tag video untuk mendeteksi keberadaan wajah.

Dalam proyek ini kita akan menggunakan Tensorflow melalui CDN, tetapi juga tersedia di NPM jika Anda lebih suka cara bundler:

 <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-core"></script> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-converter"></script> <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs-backend-webgl"></script>

Tensorflow tidak melakukan trik itu sendiri, jadi kita perlu menambahkan Facemesh, library yang dibangun di atas framework ML dan menyediakan model yang sudah terlatih untuk pengenalan wajah:

 <script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/facemesh"></script>

Langkah selanjutnya adalah menyiapkan perpustakaan Facemesh untuk memuat model yang dilatih dan untuk menentukan fungsi yang akan mengevaluasi data wajah dari aliran video:

 // create and place the video const video = document.createElement('video'); document.body.appendChild(video); // setup facemesh const model = await facemesh.load({ backend: 'wasm', maxFaces: 1, }); async function detectFaces() { const faces = await model.estimateFaces(video); console.log(faces); // recursively detect faces requestAnimationFrame(detectFaces); }

Sekarang kami siap untuk meminta izin kepada pengguna untuk mengakses aliran kameranya menggunakan tag video:

 // enable autoplay video.setAttribute('autoplay', ''); video.setAttribute('muted', ''); video.setAttribute('playsinline', ''); // start face detection when ready video.addEventListener('canplaythrough', detectFaces); // stream the camera video.srcObject = await navigator.mediaDevices.getUserMedia({ audio: false, video: { facingMode: 'user', }, }); // let's go! video.play();

Metode navigator.mediaDevices.getUserMedia akan meminta izin dan akan mulai mengalirkan kamera ke elemen video. Setelah diterima, kamera akan mulai melakukan streaming ke tag video, sementara konsol browser akan mencatat informasi wajah yang terdeteksi oleh Facemesh.

Harap dicatat bahwa izin kamera memerlukan koneksi https atau localhost yang aman: Anda tidak bisa begitu saja membuka file index.html. Jika Anda tidak yakin bagaimana mengatur server lokal, checkout http-server untuk Node atau ikuti panduan ini untuk Python atau yang ini untuk PHP.

Lebih banyak setelah melompat! Lanjutkan membaca di bawah ini

Kasus 1. Menyesuaikan Tipografi Menggunakan Kamera Smartphone

Kami menavigasi web di mana-mana dengan ponsel cerdas kami. Ada suatu waktu, belum lama ini, di mana kami biasa naik kereta atau bus yang ramai dan kami meletakkan smartphone sangat dekat dengan mata kami karena tidak ada tempat. Di banyak momen dan tempat dalam sehari, kita sering mengubah posisi dan kemiringan smartphone, bahkan jika kita menonton situs yang sama. Jarak antara mata dan smartphone mempengaruhi kemampuan membaca kita. Mengevaluasi jarak itu, kami dapat menyesuaikan mikrotipografi untuk mengoptimalkan mesin terbang untuk pembacaan yang lebih dekat atau lebih jauh.

Deteksi wajah berarti, tentu saja, deteksi posisi mata juga. Kita dapat menggunakan data yang disediakan oleh Facemesh untuk menghitung ukuran wajah kita dalam kaitannya dengan keseluruhan gambar yang diambil oleh kamera. Kita dapat berasumsi bahwa semakin besar wajah kita, semakin dekat kita dengan layar. Kita dapat mengatur skala dari 0 (satu lengan berjauhan — wajah kira-kira menempati setengah bagian kamera) hingga 1 (ditempelkan ke layar) dan mendeteksi nilai saat ini dengan pembagian segmen:

 async function detectFaces() { const faces = await model.estimateFaces(video); if (faces.length === 0) { // is somebody out there? return requestAnimationFrame(detectFaces); } const [face] = faces; // extract face surface corners let { bottomRight, topLeft} = face.boundingBox; // calculate face surface size let width = bottomRight[0] - topLeft[0]; let height = bottomRight[1] - topLeft[1]; let videoWidth = video.videoWidth; let videoHeight = video.videoHeight; let adjustWidth = videoWidth / 2; let adjustHeight = videoHeight / 2; // detect the ratio between face and full camera picture let widthRatio = Math.max(Math.min((width - adjustWidth) / (videoWidth - adjustWidth), 1), 0); let heightRatio = Math.max(Math.min((height - adjustHeight) / (videoHeight - adjustHeight), 1), 0); let ratio = Math.max(widthRatio, heightRatio); // recursively detect faces requestAnimationFrame(detectFaces); }
Representasi wajah pengguna berdasarkan segmen ditempatkan di dalam bingkai smartphone untuk menunjukkan seberapa luas area layar yang ditempati oleh wajah.
Dua contoh ciri yang dideteksi oleh Facemesh, seperti posisi dan kemiringan mata, hidung, dan mulut. Kita bisa menggunakan area antar titik untuk menghitung jarak ke kamera smartphone. (Pratinjau besar)

Sekarang kita telah menghitung ratio , saatnya untuk membuat keajaiban terjadi, meneruskan nilai ke stylesheet:

 document.documentElement.style.setProperty('--user-distance', ratio);

Dengan nilai ini dan sedikit perhitungan, kita dapat dengan mudah menerapkan sedikit perubahan pada berat font, ukuran, dan mungkin gaya juga, tetapi kita dapat melakukan sesuatu yang lebih baik lagi. Menggunakan font variabel, font yang memiliki parameter bentuk dan ruang mesin terbang, kita dapat menyesuaikan persepsi setiap mesin terbang dengan memperbarui variasi ukuran optiknya.

Karena setiap font variabel menggunakan skalanya sendiri untuk nilai ukuran optik, kita perlu menghubungkan nilai rasio kita dengan skala itu. Selain itu, kami mungkin ingin berpindah hanya di antara subset ukuran optik yang tersedia, untuk memberikan sedikit peningkatan saja.

 .main-text { --min-opsz: 10; --max-opsz: 15; --opsz: calc(var(--min-opsz) + (var(--user-distance) * (var(--max-opsz) - var(--min-opsz)))); ... font-family: 'Amstelvar', serif; font-variation-settings: 'opsz' var(--opsz); }

Anda bisa melihatnya secara langsung di sini. Harap dicatat bahwa contoh ini hanyalah demonstrasi cara kerja teknologi. Perubahan tipografi harus hampir tidak terlihat oleh mata pengguna agar benar-benar memberikan pengalaman pembaca yang lebih baik. Di sini kami memanfaatkan bentuk mesin terbang, tetapi menggunakan warna untuk menambah atau mengurangi kontras hanyalah solusi bagus lainnya untuk dicoba. Eksperimen lain adalah mendeteksi sudut wajah untuk menghitung perspektif pembacaan, memodifikasi ascender, descender dan ketinggian huruf:

Lihat Pena [Facemesh dan ascenders/descenders](https://codepen.io/smashingmag/pen/oNxrYop) oleh Edoardo Cavazza.

Lihat Pena Facemesh dan ascenders/descenders oleh Edoardo Cavazza.

Kasus #2: Menyesuaikan Tata Letak Saat Jumlah Orang yang Melihat Berubah

Dalam kasus kedua ini, kita akan mengubah tata letak berdasarkan jumlah orang yang menonton layar. Kita bisa membayangkan sebuah esai yang ditampilkan di Papan Tulis Interaktif dalam konteks ruang kelas sekolah menengah. Skenario ini secara diam-diam berbeda dari yang terdeteksi oleh kueri media proyeksi yang tidak digunakan lagi karena kami ingin menyesuaikan tata letak halaman jika jumlah siswa yang menonton lebih kecil atau lebih besar dari 10. Ketika hanya beberapa siswa di dalam kelas, mereka dapat dengan aman mendekati papan, tetapi jika seluruh ruang kelas hadir, mungkin ruang tidak cukup dan kita perlu mengubah tata letak untuk menunjukkan lebih sedikit (dan lebih besar) hal-hal.

Kami hanya perlu beberapa perubahan pada skrip sebelumnya untuk mendeteksi dengan benar jumlah wajah yang menonton di papan tulis. Pertama, kita perlu menginstruksikan Facemesh untuk mendeteksi banyak wajah:

 const model = await facemesh.load({ backend: 'wasm', maxFaces: 30, });

Dan kemudian, kita harus meneruskan nomor itu ke stylesheet:

 async function detectFaces() { const faces = await model.estimateFaces(video); document.documentElement.style.setProperty('--watching', faces.length); // recursively detect faces requestAnimationFrame(detectFace); }

Sekali lagi, kita bisa menggunakan nilai itu untuk sekadar menambah ukuran font, tetapi tujuan kita adalah menyediakan tata letak yang sama sekali berbeda. Tata letak kisi CSS dapat membantu kami dalam misi ini. Dokumen proyeksi ini berbentuk panjang dengan sisi yang berisi gambar terkait:

 <section> <article> <h1>...</h1> <h2>...</h2> <p>...</p> </article> <aside> <img src="..." alt="..." /> </aside> </section>

Dan ini adalah tata letak defaultnya:

 section { display: grid; grid-template-columns: repeat(12, 1fr); grid-column-gap: 1em; width: 120ch; max-width: 100%; padding: 1em; } section article { grid-column: 1 / -5; } section aside { grid-column: 7 / -1; }
Kiri: Saat lebih dari 10 orang menonton, kami memprioritaskan teks utama menggunakan semua kolom yang tersedia dan memindahkan gambar setelah teks. Kanan: Tata letak halaman menggunakan 12 kolom dengan panduan pemeriksa kisi Firefox aktif. Semua 12 kolom digunakan untuk teks utama, 4 untuk gambar setelahnya.
Kiri : Tata letak default halaman menggunakan 8 dari 12 kolom untuk teks bentuk panjang dan 4 sisanya untuk gambar. Kanan : Saat menonton lebih dari 10 orang, kami memprioritaskan teks utama menggunakan semua kolom yang tersedia dan memindahkan gambar setelah teks. (Pratinjau besar)

Ketika banyak orang menonton, kita perlu mengistimewakan konteks membaca bentuk panjang, memberikan lebih banyak ruang ke kolom utama, meningkatkan ukuran fontnya, dan menghapus elemen yang mengganggu. Untuk melakukan itu, kita menambah jumlah kolom terbentang, memindahkan ke samping di bawah teks utama.

 :root { --watching: 10; } section { /** The maximum number of people watching for the default layout */ --switch: 10; /** The default number of columns for the text */ --text: 8; /** The default number of columns for the aside */ --aside: 4; grid-template-columns: repeat(calc(var(--text) + var(--aside)), 1fr); } section article { /** * Kinda magic calculation. * When the number of people watching is lower than --switch, it returns -2 * When the number of people watching is greater than --switch, it returns -1 * We are going to use this number for negative span calculation */ --layout: calc(min(2, (max(var(--switch), var(--watching)) - var(--switch) + 1)) - 3); /** * Calculate the position of the end column. * When --layout is -1, the calculation just returns -1 * When --layout is -2, the calculation is lower than -1 */ --layout-span: calc((var(--aside) * var(--layout)) + var(--aside) - 1); /** * Calculate the maximum index of the last column (the one "before" the aside) */ --max-span: calc(-1 * var(--aside) - 1); /** * get the max between --layout-span and the latest column index. * -1 means full width * --max-span means default layout */ --span: max(var(--max-span), var(--span)); grid-column-start: 1; grid-column-end: var(--span); }
  • Anda dapat melihatnya secara langsung di sini →

Sebaliknya, ketika sekelompok kecil siswa sedang mengalami teks di dekat papan, kami dapat memberikan lebih banyak detail, seperti file media dan pemicu tindakan interaktif.

Melampaui Pengenalan Wajah

Kasus yang kami hadapi () hanyalah dua contoh bagaimana kami dapat menggunakan teknologi pengenalan wajah untuk tata letak atau cakupan tipografi. Tensorflow menyediakan model dan pustaka lain yang dapat mengubah aliran kamera menjadi variabel untuk halaman kita. Selain itu, kita tidak boleh lupa bahwa di ponsel cerdas kita ada banyak sensor lain yang dapat kita manfaatkan menggunakan API Sensor: GPS, akselerometer, cahaya sekitar, dll.

Karena suasana hati memengaruhi cara kita membaca, mempelajari, dan mencari informasi, dengan pembelajaran mesin, kita juga dapat menganalisis ekspresi pengguna untuk beralih dari tata letak minimal ke detail sesuai keinginan pengguna.

Selama bertahun-tahun kami telah terbiasa menggunakan kueri Media CSS untuk desain web yang responsif. Namun, ukuran area pandang hanyalah salah satu variabel dari pengalaman pengguna. Baru-baru ini, jenis kueri media baru yang dirancang untuk menghormati preferensi pengguna mendarat di browser, seperti prefers-color-scheme dan prefers-reduced-motion . Ini memberi desainer dan pengembang cara untuk melangkah maju dalam praktik desain web, memungkinkan halaman web beradaptasi dengan seluruh lingkungan, bukan hanya perangkat pengguna. Di era data besar, kami memiliki peluang untuk melampaui desain responsif dan adaptif. Halaman web kami akhirnya dapat "meninggalkan layar" dan menjadi bagian dari pengalaman global pengguna. Desain interaksi akan melibatkan semua kemungkinan ini, jadi terus bereksperimen dengan kemungkinan kombinasi antara teknologi dan desain web akan sangat penting di tahun-tahun berikutnya.