วิธีใช้ Face Motion เพื่อโต้ตอบกับวิชาการพิมพ์
เผยแพร่แล้ว: 2022-03-10นักออกแบบเว็บไซต์มักจะมองหาวิธีใหม่ๆ ในการปรับปรุงการนำเสนอเนื้อหาของหน้าอยู่เสมอ บางครั้งสิ่งนี้สามารถนำไปสู่การแก้ปัญหาที่แยบยลหรือโต้ตอบกับเทคโนโลยีที่มักถูกเก็บให้ห่างจากสาขาการออกแบบ ในบทความนี้ เราจะนำการพิมพ์มาสัมผัสกับปัญญาประดิษฐ์ โดยใช้การเรียนรู้ของเครื่องเพื่อตรวจจับสิ่งต่างๆ เช่น ความใกล้ชิดของใบหน้าของผู้ใช้ เพื่อปรับปรุงความชัดเจนของข้อความ
เราจะทดลองวิธีใช้การจดจำใบหน้ากับ Tensorflow เพื่อดึงข้อมูลบางส่วนออกจากกล้อง เช่น ระยะห่างระหว่างหน้าจอกับใบหน้าของผู้ใช้ หรือจำนวนคนที่อ่านหน้าเว็บ จากนั้นเราจะส่งข้อมูลเหล่านั้นไปยัง CSS เพื่อปรับรูปแบบตัวอักษรและปรับเค้าโครงหน้า
Tensorflow คืออะไร?
Tensorflow เป็นแพลตฟอร์มโอเพ่นซอร์สจาก Google สำหรับการเรียนรู้ของเครื่อง การเรียนรู้ของเครื่องเป็นสาขาวิทยาการคอมพิวเตอร์ที่ศึกษาอัลกอริทึมที่เรียนรู้ที่จะรับรู้ความสัมพันธ์ที่ซับซ้อนและรูปแบบที่เกิดซ้ำจากรูปภาพ แทร็กเสียง อนุกรมเวลา ข้อความธรรมชาติ และข้อมูลโดยทั่วไป อัลกอริธึมเหล่านี้สร้างแบบจำลองทางคณิตศาสตร์ (เรียกอีกอย่างว่าแบบจำลองที่ได้รับการฝึกอบรม) ซึ่งเป็นสคีมาประเภทหนึ่งที่สามารถใช้ในการตัดสินใจตามข้อมูลที่ป้อนเข้า หากคุณต้องการเข้าถึงหัวข้อนี้ Charlie Gerard เขียนเกี่ยวกับ ML สำหรับนักพัฒนาส่วนหน้าใน Smashing Mag
Tensorflow มีเครื่องมือมากมายสำหรับนักพัฒนา AI, นักวิทยาศาสตร์ข้อมูล, นักคณิตศาสตร์ แต่อย่าตกใจถ้าการวิเคราะห์ข้อมูลไม่ใช่สิ่งที่ขาดไม่ได้ในแต่ละวันของคุณ! ข่าวดีก็คือคุณไม่จำเป็นต้องเป็นผู้เชี่ยวชาญในการใช้งาน ตราบใดที่คุณใช้โมเดลที่สร้างไว้ล่วงหน้า เช่นเดียวกับที่เราจะใช้งาน
โมเดล Tensorflow พร้อมใช้งานบนเว็บด้วย JavaScript SDK
ติดตั้ง
เพื่อเริ่มใช้อัลกอริธึมการจดจำใบหน้า เราต้องทำตามขั้นตอนต่อไปนี้:
- โหลด Tensorflow SDK
- โหลดไลบรารี Facemesh ที่มีแบบจำลองทางคณิตศาสตร์
- เข้าถึงกล้องของผู้ใช้และสตรีมไปยังองค์ประกอบวิดีโอ HTML Facemesh จะวิเคราะห์เฟรมจากแท็กวิดีโอเพื่อตรวจจับใบหน้า
ในโปรเจ็กต์นี้ เราจะใช้ Tensorflow ผ่าน CDN แต่ก็ยังมีให้ใช้งานบน NPM หากคุณต้องการวิธีบันเดิล:
<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 ไม่ได้ทำเคล็ดลับเอง ดังนั้นเราจึงจำเป็นต้องเพิ่ม Facemesh ซึ่งเป็นไลบรารีที่สร้างขึ้นบนสุดของเฟรมเวิร์ก ML และจัดเตรียมโมเดลที่ได้รับการฝึกฝนมาแล้วสำหรับการจดจำใบหน้า:
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/facemesh"></script>
ขั้นตอนต่อไปคือการตั้งค่าไลบรารี Facemesh เพื่อโหลดโมเดลที่ได้รับการฝึกและกำหนดฟังก์ชันที่จะประเมินข้อมูลใบหน้าจากการสตรีมวิดีโอ:
// 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); }
ตอนนี้เราพร้อมที่จะขออนุญาตผู้ใช้ในการเข้าถึงสตรีมของกล้องโดยใช้แท็กวิดีโอ:
// 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();
เมธอด navigator.mediaDevices.getUserMedia จะขออนุญาตและจะเริ่มสตรีมกล้องไปยังองค์ประกอบวิดีโอ เมื่อยอมรับแล้ว กล้องจะเริ่มสตรีมไปยังแท็กวิดีโอ ในขณะที่คอนโซลของเบราว์เซอร์จะบันทึกข้อมูลใบหน้าที่ Facemesh ตรวจพบ
โปรดทราบว่าการอนุญาตของกล้องต้องใช้การเชื่อมต่อ https ที่ปลอดภัยหรือ localhost: คุณไม่สามารถเปิดไฟล์ index.html ได้ง่ายๆ หากคุณไม่แน่ใจว่าจะตั้งค่าเซิร์ฟเวอร์ชำระเงิน http-server สำหรับ Node ได้อย่างไร หรือทำตามคำแนะนำนี้สำหรับ Python หรือคู่มือนี้สำหรับ PHP
กรณีที่ 1. ปรับรูปแบบตัวอักษรโดยใช้กล้องของสมาร์ทโฟน
เราท่องเว็บได้ทุกที่ด้วยสมาร์ทโฟนของเรา เมื่อไม่นานมานี้มีครั้งหนึ่งที่เราเคยขึ้นรถไฟหรือรถประจำทางที่แออัดและเราเก็บสมาร์ทโฟนไว้ใกล้ตาเพราะไม่มีที่ว่าง ในหลายช่วงเวลาและสถานที่ในสมัยของเรา เรามักจะเปลี่ยนตำแหน่งและความเอียงของสมาร์ทโฟน แม้ว่าเราจะดูเว็บไซต์เดียวกันก็ตาม ระยะห่างระหว่างดวงตากับสมาร์ทโฟนส่งผลต่อความสามารถในการอ่านของเรา การประเมินระยะทางนั้น เราสามารถปรับ microtypography เพื่อปรับร่ายมนตร์ให้เหมาะสมสำหรับการอ่านที่ใกล้หรือไกลมากขึ้น
แน่นอนว่าการตรวจจับใบหน้าหมายถึงการตรวจจับตำแหน่งดวงตาด้วยเช่นกัน เราสามารถใช้ข้อมูลที่ Facemesh ให้มาเพื่อคำนวณขนาดใบหน้าของเราที่สัมพันธ์กับภาพทั้งหมดที่กล้องถ่ายได้ เราสามารถสรุปได้ว่ายิ่งหน้าใหญ่เท่าไหร่ เรายิ่งอยู่ใกล้หน้าจอมากขึ้นเท่านั้น เราสามารถตั้งค่ามาตราส่วนจาก 0 (แขนข้างหนึ่งห่างกัน — ใบหน้าประมาณครึ่งหนึ่งของกล้อง) ถึง 1 (ติดกาวที่หน้าจอ) และตรวจจับค่าปัจจุบันด้วยการแบ่งส่วน:
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); }
เมื่อเราคำนวณ ratio
แล้ว ก็ได้เวลาสร้างเวทย์มนตร์ โดยส่งต่อค่าไปยังสไตล์ชีต:
document.documentElement.style.setProperty('--user-distance', ratio);
ด้วยค่านี้และการคำนวณเล็กน้อย เราสามารถใช้การเปลี่ยนแปลงเล็กน้อยกับน้ำหนัก ขนาด และสไตล์ของแบบอักษรได้เช่นกัน แต่เราสามารถทำบางสิ่งได้ดียิ่งขึ้นไปอีก การใช้ฟอนต์แบบแปรผัน ฟอนต์ที่มีรูปร่างและช่องว่างของร่ายมนตร์กำหนดพารามิเตอร์ เราสามารถปรับการรับรู้ของร่ายมนตร์ทุกตัวได้ด้วยการอัพเดตรูปแบบขนาดออปติคัลของมัน
เนื่องจากฟอนต์ตัวแปรทุกตัวใช้มาตราส่วนของตัวเองสำหรับค่าขนาดออปติคัล เราจึงต้องเชื่อมโยงค่าอัตราส่วนของเรากับสเกลนั้น นอกจากนี้ เราอาจต้องการย้ายระหว่างชุดย่อยของขนาดออปติคัลที่มีอยู่ เพื่อให้มีการปรับปรุงเพียงเล็กน้อย
.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); }
สามารถรับชมสดได้ที่นี่ โปรดทราบว่าตัวอย่างนี้เป็นเพียงการสาธิตวิธีการทำงานของเทคโนโลยี การเปลี่ยนแปลงทางตัวอักษรควรทำให้ผู้ใช้มองไม่เห็นด้วยตาเปล่าเพื่อมอบประสบการณ์การอ่านที่ดีขึ้นอย่างแท้จริง ที่นี่เราใช้ประโยชน์จากรูปร่างร่ายมนตร์ แต่การใช้สีเพื่อเพิ่มหรือลดคอนทราสต์เป็นอีกวิธีหนึ่งที่ดีในการลอง อีกการทดลองหนึ่งคือการตรวจจับมุมของใบหน้าเพื่อคำนวณมุมมองของการอ่าน ปรับเปลี่ยนจากบนลงล่าง ตามด้วยความสูงของตัวอักษร:
กรณีที่ #2: การปรับเลย์เอาต์เมื่อจำนวนคนดูเปลี่ยนไป
ในกรณีที่สองนี้ เราจะเปลี่ยนเลย์เอาต์ตามจำนวนคนที่ดูหน้าจอ เราสามารถจินตนาการถึงบทความที่แสดงบนกระดานไวท์บอร์ดแบบโต้ตอบในบริบทของห้องเรียนมัธยมปลายได้ สถานการณ์นี้แตกต่างอย่างสิ้นเชิงจากสถานการณ์ที่ตรวจพบโดยแบบสอบถามสื่อการฉายภาพที่เลิกใช้แล้ว เนื่องจากเราต้องการปรับเลย์เอาต์ของหน้าหากจำนวนนักเรียนที่ดูน้อยกว่าหรือมากกว่า 10 คน เมื่อมีนักเรียนเพียงไม่กี่คนในห้องเรียน พวกเขา สามารถเข้าใกล้กระดานได้อย่างปลอดภัย แต่ถ้าห้องเรียนทั้งหมดมีอยู่ พื้นที่อาจไม่เพียงพอและเราจำเป็นต้องเปลี่ยนเลย์เอาต์เพื่อแสดงสิ่งต่าง ๆ น้อยลง (และใหญ่ขึ้น)
เราต้องการการเปลี่ยนแปลงเล็กน้อยในสคริปต์ก่อนหน้าเพื่อตรวจจับจำนวนใบหน้าที่ดูบนไวท์บอร์ดได้อย่างถูกต้อง อันดับแรก เราต้องสั่งให้ Facemesh ตรวจพบใบหน้าหลายหน้า:
const model = await facemesh.load({ backend: 'wasm', maxFaces: 30, });
จากนั้น เราต้องส่งตัวเลขนั้นไปที่สไตล์ชีต:
async function detectFaces() { const faces = await model.estimateFaces(video); document.documentElement.style.setProperty('--watching', faces.length); // recursively detect faces requestAnimationFrame(detectFace); }
อีกครั้ง เราสามารถใช้ค่านั้นเพื่อเพิ่มขนาดฟอนต์ได้ง่ายๆ แต่เป้าหมายของเราคือการจัดหาเลย์เอาต์ที่แตกต่างไปจากเดิมอย่างสิ้นเชิง เค้าโครงกริด CSS อาจช่วยเราได้ในภารกิจนี้ เอกสารที่ฉายนี้เป็นแบบยาวพร้อมด้านข้างที่มีรูปภาพที่เกี่ยวข้อง:
<section> <article> <h1>...</h1> <h2>...</h2> <p>...</p> </article> <aside> <img src="..." alt="..." /> </aside> </section>
และนี่คือเค้าโครงเริ่มต้น:
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; }
เมื่อมีผู้ชมจำนวนมาก เราจำเป็นต้องให้สิทธิ์บริบทการอ่านแบบยาว เพิ่มพื้นที่ให้กับคอลัมน์หลัก เพิ่มขนาดฟอนต์ และลบองค์ประกอบที่รบกวน ในการทำเช่นนั้น เราเพิ่มจำนวนคอลัมน์ที่ขยาย โดยย้ายข้างใต้ข้อความหลัก
: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); }
- สามารถรับชมสดได้ที่นี่ →
ในทางกลับกัน เมื่อนักเรียนกลุ่มเล็กๆ กำลังประสบกับข้อความใกล้กระดาน เราสามารถให้รายละเอียดเพิ่มเติม เช่น ไฟล์สื่อและทริกเกอร์การดำเนินการแบบโต้ตอบ
นอกเหนือจากการจดจำใบหน้า
กรณีที่เราเผชิญ () เป็นเพียงสองตัวอย่างวิธีที่เราสามารถใช้เทคโนโลยีการจดจำใบหน้าสำหรับการจัดวางหรือขอบเขตการพิมพ์ Tensorflow มีโมเดลและไลบรารีอื่นๆ ที่สามารถเปลี่ยนสตรีมของกล้องเป็นตัวแปรสำหรับเพจของเรา นอกจากนี้ เราไม่ควรลืมว่าในสมาร์ทโฟนของเรามีเซ็นเซอร์อื่นๆ มากมายที่เราสามารถใช้ประโยชน์ได้โดยใช้ Sensor API: GPS, มาตรความเร่ง, แสงแวดล้อม ฯลฯ
เนื่องจากอารมณ์มีอิทธิพลต่อวิธีที่เราอ่าน ศึกษา และค้นหาข้อมูล ด้วยแมชชีนเลิร์นนิง เราจึงสามารถวิเคราะห์การแสดงออกของผู้ใช้เพื่อเปลี่ยนจากเลย์เอาต์ขั้นต่ำเป็นเลย์เอาต์แบบละเอียดตามอารมณ์ของผู้ใช้
เป็นเวลาหลายปีที่เราคุ้นเคยกับการใช้ CSS Media Queries สำหรับการออกแบบเว็บที่ตอบสนอง อย่างไรก็ตาม ขนาดของวิวพอร์ตเป็นเพียงหนึ่งในตัวแปรของประสบการณ์ผู้ใช้ เมื่อเร็วๆ นี้ ข้อความค้นหาสื่อรูปแบบใหม่ที่ออกแบบมาเพื่อเคารพการตั้งค่าของผู้ใช้ได้เข้ามาในเบราว์เซอร์ เช่น prefers-color-scheme
prefers-reduced-motion
วิธีนี้จะช่วยให้นักออกแบบและนักพัฒนาสามารถก้าวไปข้างหน้าในการออกแบบเว็บได้ ทำให้หน้าเว็บสามารถปรับให้เข้ากับสภาพแวดล้อมทั้งหมดได้ แทนที่จะเป็นเพียงอุปกรณ์ของผู้ใช้ ในยุคของข้อมูลขนาดใหญ่ เรามีโอกาสที่จะก้าวไปไกลกว่าการออกแบบที่ตอบสนองและปรับเปลี่ยนได้ ในที่สุด หน้าเว็บของเราสามารถ "ออกจากหน้าจอ" และกลายเป็นส่วนหนึ่งของประสบการณ์ระดับโลกของผู้ใช้ได้ การออกแบบการโต้ตอบจะเกี่ยวข้องกับความเป็นไปได้ทั้งหมด ดังนั้นการทดลองใช้การผสมผสานที่เป็นไปได้ระหว่างเทคโนโลยีและการออกแบบเว็บจึงมีความสำคัญในปีต่อๆ ไป