วิธีใช้ Face Motion เพื่อโต้ตอบกับวิชาการพิมพ์

เผยแพร่แล้ว: 2022-03-10
สรุปอย่างย่อ ↬ ในบทความนี้ เราจะพูดถึงวิธีการรวม Machine Learning ฟอนต์แบบแปรผัน และกริด CSS เพื่อสร้างเลย์เอาต์ที่ตอบสนองต่อระยะใกล้ ความเอียง และจำนวนใบหน้าของผู้ใช้

นักออกแบบเว็บไซต์มักจะมองหาวิธีใหม่ๆ ในการปรับปรุงการนำเสนอเนื้อหาของหน้าอยู่เสมอ บางครั้งสิ่งนี้สามารถนำไปสู่การแก้ปัญหาที่แยบยลหรือโต้ตอบกับเทคโนโลยีที่มักถูกเก็บให้ห่างจากสาขาการออกแบบ ในบทความนี้ เราจะนำการพิมพ์มาสัมผัสกับปัญญาประดิษฐ์ โดยใช้การเรียนรู้ของเครื่องเพื่อตรวจจับสิ่งต่างๆ เช่น ความใกล้ชิดของใบหน้าของผู้ใช้ เพื่อปรับปรุงความชัดเจนของข้อความ

เราจะทดลองวิธีใช้การจดจำใบหน้ากับ 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); }
การแสดงใบหน้าของผู้ใช้ตามส่วนต่างๆ จะถูกวางไว้ภายในเฟรมของสมาร์ทโฟนเพื่อระบุว่าใบหน้าใช้พื้นที่เท่าใดของหน้าจอ
ตัวอย่างลักษณะเด่น 2 ประการที่ Facemesh ตรวจพบ เช่น ตำแหน่งและความเอียงของตา จมูก และปาก เราสามารถใช้พื้นที่ระหว่างจุดเพื่อคำนวณความใกล้ชิดกับกล้องสมาร์ทโฟนได้ (ตัวอย่างขนาดใหญ่)

เมื่อเราคำนวณ 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); }

สามารถรับชมสดได้ที่นี่ โปรดทราบว่าตัวอย่างนี้เป็นเพียงการสาธิตวิธีการทำงานของเทคโนโลยี การเปลี่ยนแปลงทางตัวอักษรควรทำให้ผู้ใช้มองไม่เห็นด้วยตาเปล่าเพื่อมอบประสบการณ์การอ่านที่ดีขึ้นอย่างแท้จริง ที่นี่เราใช้ประโยชน์จากรูปร่างร่ายมนตร์ แต่การใช้สีเพื่อเพิ่มหรือลดคอนทราสต์เป็นอีกวิธีหนึ่งที่ดีในการลอง อีกการทดลองหนึ่งคือการตรวจจับมุมของใบหน้าเพื่อคำนวณมุมมองของการอ่าน ปรับเปลี่ยนจากบนลงล่าง ตามด้วยความสูงของตัวอักษร:

ดูปากกา [Facemesh and ascenders/descenders](https://codepen.io/smashingmag/pen/oNxrYop) โดย Edoardo Cavazza

ดู Pen Facemesh และ ascenders/descenders โดย Edoardo Cavazza

กรณีที่ #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; }
ซ้าย: เมื่อมีผู้ชมมากกว่า 10 คน เราจะจัดลำดับความสำคัญของข้อความหลักโดยใช้คอลัมน์ที่มีอยู่ทั้งหมดและย้ายรูปภาพไปต่อจากข้อความ ขวา: เค้าโครงหน้าที่ใช้ 12 คอลัมน์พร้อมคำแนะนำตัวตรวจสอบกริดของ Firefox คอลัมน์ทั้งหมด 12 คอลัมน์ใช้สำหรับข้อความหลัก 4 คอลัมน์สำหรับรูปภาพหลังจากนั้น
ซ้าย : เลย์เอาต์เริ่มต้นของหน้าใช้ 8 จาก 12 คอลัมน์สำหรับข้อความแบบยาวและอีก 4 คอลัมน์ที่เหลือสำหรับรูปภาพ ขวา : เมื่อมีผู้ชมมากกว่า 10 คน เราจะจัดลำดับความสำคัญของข้อความหลักโดยใช้คอลัมน์ที่มีอยู่ทั้งหมดและย้ายรูปภาพไปต่อจากข้อความ (ตัวอย่างขนาดใหญ่)

เมื่อมีผู้ชมจำนวนมาก เราจำเป็นต้องให้สิทธิ์บริบทการอ่านแบบยาว เพิ่มพื้นที่ให้กับคอลัมน์หลัก เพิ่มขนาดฟอนต์ และลบองค์ประกอบที่รบกวน ในการทำเช่นนั้น เราเพิ่มจำนวนคอลัมน์ที่ขยาย โดยย้ายข้างใต้ข้อความหลัก

 :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 วิธีนี้จะช่วยให้นักออกแบบและนักพัฒนาสามารถก้าวไปข้างหน้าในการออกแบบเว็บได้ ทำให้หน้าเว็บสามารถปรับให้เข้ากับสภาพแวดล้อมทั้งหมดได้ แทนที่จะเป็นเพียงอุปกรณ์ของผู้ใช้ ในยุคของข้อมูลขนาดใหญ่ เรามีโอกาสที่จะก้าวไปไกลกว่าการออกแบบที่ตอบสนองและปรับเปลี่ยนได้ ในที่สุด หน้าเว็บของเราสามารถ "ออกจากหน้าจอ" และกลายเป็นส่วนหนึ่งของประสบการณ์ระดับโลกของผู้ใช้ได้ การออกแบบการโต้ตอบจะเกี่ยวข้องกับความเป็นไปได้ทั้งหมด ดังนั้นการทดลองใช้การผสมผสานที่เป็นไปได้ระหว่างเทคโนโลยีและการออกแบบเว็บจึงมีความสำคัญในปีต่อๆ ไป