1. לפני שמתחילים
MediaPipe Solutions מאפשר לכם להחיל פתרונות של למידת מכונה (ML) על האפליקציות שלכם. הוא מספק מסגרת שמאפשרת להגדיר צינורות עיבוד מוכנים מראש שמספקים למשתמשים פלט מיידי, מעניין ומועיל. אפשר גם להתאים אישית את הפתרונות האלה באמצעות הכלי Model Maker כדי לעדכן את מודלי ברירת המחדל.
זיהוי אובייקטים הוא אחת מכמה משימות ראייה מבוססת-למידה ש-MediaPipe Solutions מציעה. MediaPipe Tasks זמין ל-Android, ל-Python ולאינטרנט.
בקודלאב הזה תוסיפו זיהוי אובייקטים לאפליקציית אינטרנט כדי לזהות כלבים בתמונות ובסרטון וידאו בשידור חי ממצלמת אינטרנט.
מה תלמדו
- איך לשלב משימה של זיהוי אובייקטים באפליקציית אינטרנט באמצעות MediaPipe Tasks.
מה תפַתחו
- אפליקציית אינטרנט שמזהה נוכחות של כלבים. אתם יכולים גם להתאים אישית מודל כדי לזהות סוג של אובייקטים לבחירתכם באמצעות MediaPipe Model Maker.
מה נדרש
- חשבון CodePen
- מכשיר עם דפדפן אינטרנט
- ידע בסיסי ב-JavaScript, ב-CSS וב-HTML
2. להגדרה
בקודלאב הזה הקוד שלכם יפעל ב-CodePen,סביבת פיתוח חברתית שמאפשרת לכתוב קוד בדפדפן ולבדוק את התוצאות תוך כדי פיתוח.
כדי להגדיר את השירות, פועלים לפי השלבים הבאים:
- בחשבון CodePen, עוברים אל CodePen הזה. אפשר להשתמש בקוד הזה כבסיס ליצירת גלאי אובייקטים משלכם.
- בתפריט הניווט של CodePen, לוחצים על Fork (הסתעפות) בחלק התחתון כדי ליצור עותק של קוד ההתחלה.
- בכרטיסייה JS, לוחצים על החץ להרחבה ובוחרים באפשרות Maximize JavaScript editor. בקודלאב הזה עורכים את העבודה רק בכרטיסייה JS, כך שאין צורך לראות את הכרטיסיות HTML או CSS.
בדיקת האפליקציה למתחילים
- בחלונית התצוגה המקדימה, שימו לב שיש שתי תמונות של כלבים ואפשרות להפעיל את מצלמת האינטרנט. המודל שבו משתמשים במדריך הזה אומן על שלושת הכלבים שמוצגים בשתי התמונות.
- בכרטיסייה JS, שימו לב שיש כמה תגובות בקוד. לדוגמה, אפשר למצוא את התגובה הבאה בשורה 15:
// Import the required package.
התגובות האלה מציינות איפה צריך להוסיף קטעי קוד.
3. מייבאים את החבילה tasks-vision של MediaPipe ומוסיפים את המשתנים הנדרשים
- בכרטיסייה JS, מייבאים את החבילה
tasks-vision
של MediaPipe:
// Import the required package.
import { ObjectDetector, FilesetResolver, Detection } from "https://cdn.skypack.dev/@mediapipe/tasks-vision@latest";
הקוד הזה משתמש ברשת Skypack להעברת תוכן (CDN) כדי לייבא את החבילה. מידע נוסף על השימוש ב-Skypack עם CodePen זמין במאמר Skypack + CodePen.
בפרויקטים שלכם, אתם יכולים להשתמש ב-Node.js עם npm או עם מנהל החבילות או ה-CDN שבחרתם. מידע נוסף על החבילה הנדרשת שצריך להתקין זמין במאמר חבילות JavaScript.
- מגדירים משתנים למזהה האובייקטים ולמצב ההפעלה:
// Create required variables.
let objectDetector = null;
let runningMode = "IMAGE";
המשתנה runningMode
הוא מחרוזת שמוגדרת לערך "IMAGE"
כשמזוהים אובייקטים בתמונות, או לערך "VIDEO"
כשמזוהים אובייקטים בסרטונים.
4. איך מפעילים את השירות לזיהוי אובייקטים
- כדי לאתחל את גלאי האובייקטים, מוסיפים את הקוד הבא אחרי התגובה הרלוונטית בכרטיסייה JS:
// Initialize the object detector.
async function initializeObjectDetector() {
const visionFilesetResolver = await FilesetResolver.forVisionTasks(
"https://cdn.jsdelivr.net/npm/@mediapipe/tasks-vision@latest/wasm"
);
objectDetector = await ObjectDetector.createFromOptions(visionFilesetResolver, {
baseOptions: {
modelAssetPath: "https://storage.googleapis.com/mediapipe-assets/dogs.tflite"
},
scoreThreshold: 0.3,
runningMode: runningMode
});
}
initializeObjectDetector();
השיטה FilesetResolver.forVisionTasks()
מציינת את המיקום של קובץ ה-binary של WebAssembly (Wasm) של המשימה.
השיטה ObjectDetector.createFromOptions()
יוצרת מופע של מכשיר זיהוי האובייקטים. צריך לספק נתיב למודל שמשמש לזיהוי. במקרה הזה, מודל זיהוי הכלבים מתארח ב-Cloud Storage.
המאפיין scoreThreshold
מוגדר לערך 0.3
. כלומר, המודל מחזיר תוצאות לכל אובייקט שזוהה ברמת ביטחון של 30% או יותר. אתם יכולים לשנות את הסף הזה בהתאם לצרכים של האפליקציה.
המאפיין runningMode
מוגדר במהלך האינטוליזציה של אובייקט ObjectDetector
. אפשר לשנות את האפשרות הזו ואפשרויות אחרות לפי הצורך בשלב מאוחר יותר.
5. הרצת חיזויים על תמונות
- כדי להריץ חיזויים על תמונות, עוברים לפונקציה
handleClick()
ומוסיפים את הקוד הבא לגוף הפונקציה:
// Verify object detector is initialized and choose the correct running mode.
if (!objectDetector) {
alert("Object Detector still loading. Please try again");
return;
}
if (runningMode === "VIDEO") {
runningMode = "IMAGE";
await objectDetector.setOptions({ runningMode: runningMode });
}
הקוד הזה קובע אם מכשיר זיהוי האובייקטים יופעל, ומוודא שמצב ההפעלה מוגדר לתמונות.
זיהוי אובייקטים
- כדי לזהות אובייקטים בתמונות, מוסיפים את הקוד הבא לגוף הפונקציה
handleClick()
:
// Run object detection.
const detections = objectDetector.detect(event.target);
קטע הקוד הבא כולל דוגמה לנתוני הפלט של המשימה הזו:
ObjectDetectionResult:
Detection #0:
Box: (x: 355, y: 133, w: 190, h: 206)
Categories:
index : 17
score : 0.73828
class name : aci
Detection #1:
Box: (x: 103, y: 15, w: 138, h: 369)
Categories:
index : 17
score : 0.73047
class name : tikka
עיבוד תחזיות והצגתן
- בסוף גוף הפונקציה
handleClick()
, קוראים לפונקציהdisplayImageDetections()
:
// Call the displayImageDetections() function.
displayImageDetections(detections, event.target);
- בגוף הפונקציה
displayImageDetections()
, מוסיפים את הקוד הבא כדי להציג את תוצאות זיהוי העצמים:
// Display object detection results.
const ratio = resultElement.height / resultElement.naturalHeight;
for (const detection of result.detections) {
// Description text
const p = document.createElement("p");
p.setAttribute("class", "info");
p.innerText =
detection.categories[0].categoryName +
" - with " +
Math.round(parseFloat(detection.categories[0].score) * 100) +
"% confidence.";
// Positioned at the top-left of the bounding box.
// Height is that of the text.
// Width subtracts text padding in CSS so that it fits perfectly.
p.style =
"left: " +
detection.boundingBox.originX * ratio +
"px;" +
"top: " +
detection.boundingBox.originY * ratio +
"px; " +
"width: " +
(detection.boundingBox.width * ratio - 10) +
"px;";
const highlighter = document.createElement("div");
highlighter.setAttribute("class", "highlighter");
highlighter.style =
"left: " +
detection.boundingBox.originX * ratio +
"px;" +
"top: " +
detection.boundingBox.originY * ratio +
"px;" +
"width: " +
detection.boundingBox.width * ratio +
"px;" +
"height: " +
detection.boundingBox.height * ratio +
"px;";
resultElement.parentNode.appendChild(highlighter);
resultElement.parentNode.appendChild(p);
}
הפונקציה הזו מציגה תיבות מלבניות מעל האובייקטים שזוהו בתמונות. הפונקציה מסירה הדגשות קודמות, ואז יוצרת ותצוגה תגים מסוג <p>
כדי להדגיש כל אובייקט שזוהה.
בדיקת האפליקציה
כשמבצעים שינויים בקוד ב-CodePen, חלונית התצוגה המקדימה מתעדכנת באופן אוטומטי לאחר השמירה. אם שמירת האוטומטית מופעלת, סביר להניח שהאפליקציה כבר התעדכנה, אבל מומלץ לעדכן אותה שוב.
כדי לבדוק את האפליקציה:
- בחלונית התצוגה המקדימה, לוחצים על כל תמונה כדי להציג את התחזיות. תיבת גבולות שבה מוצג שם הכלב עם רמת האמון של המודל.
- אם אין תיבת גבולות, פותחים את כלי הפיתוח ל-Chrome ובודקים אם יש שגיאות בחלונית מסוף. לחלופין, בודקים את השלבים הקודמים כדי לוודא שלא שכחתם משהו.
6. הפעלת תחזיות בסרטון בשידור חי ממצלמת אינטרנט
זיהוי אובייקטים
- כדי לזהות אובייקטים בסרטון וידאו בשידור חי ממצלמת אינטרנט, עוברים לפונקציה
predictWebcam()
ומוסיפים את הקוד הבא לגוף הפונקציה:
// Run video object detection.
// If image mode is initialized, create a classifier with video runningMode.
if (runningMode === "IMAGE") {
runningMode = "VIDEO";
await objectDetector.setOptions({ runningMode: runningMode });
}
let nowInMs = performance.now();
// Detect objects with the detectForVideo() method.
const result = await objectDetector.detectForVideo(video, nowInMs);
displayVideoDetections(result.detections);
זיהוי אובייקטים בסרטונים מתבצע באותן שיטות, בין שאתם מפעילים את ההסקה על נתוני סטרימינג ובין שאתם מפעילים אותה על סרטון שלם. השיטה detectForVideo()
דומה לשיטה detect()
שמשמשת לתמונות, אבל היא כוללת פרמטר נוסף לחותמת הזמן שמשויכת לפריים הנוכחי. הפונקציה מבצעת זיהוי בזמן אמת, לכן מעבירים את השעה הנוכחית כחותמת הזמן.
עיבוד תחזיות והצגתן
- כדי לעבד ולהציג את תוצאות הזיהוי, עוברים לפונקציה
displayVideoDetections()
ומוסיפים את הקוד הבא לגוף הפונקציה:
// Display video object detection results.
for (let child of children) {
liveView.removeChild(child);
}
children.splice(0);
// Iterate through predictions and draw them to the live view.
for (const detection of result.detections) {
const p = document.createElement("p");
p.innerText =
detection.categories[0].categoryName +
" - with " +
Math.round(parseFloat(detection.categories[0].score) * 100) +
"% confidence.";
p.style =
"left: " +
(video.offsetWidth -
detection.boundingBox.width -
detection.boundingBox.originX) +
"px;" +
"top: " +
detection.boundingBox.originY +
"px; " +
"width: " +
(detection.boundingBox.width - 10) +
"px;";
const highlighter = document.createElement("div");
highlighter.setAttribute("class", "highlighter");
highlighter.style =
"left: " +
(video.offsetWidth -
detection.boundingBox.width -
detection.boundingBox.originX) +
"px;" +
"top: " +
detection.boundingBox.originY +
"px;" +
"width: " +
(detection.boundingBox.width - 10) +
"px;" +
"height: " +
detection.boundingBox.height +
"px;";
liveView.appendChild(highlighter);
liveView.appendChild(p);
// Store drawn objects in memory so that they're queued to delete at next call.
children.push(highlighter);
children.push(p);
}
}
הקוד הזה מסיר את כל ההדגשות הקודמות, ואז יוצר ומציג תגי <p>
כדי להדגיש כל אובייקט שזוהה.
בדיקת האפליקציה
כדי לבדוק את זיהוי האובייקטים בזמן אמת, כדאי להשתמש בתמונה של אחד מהכלבים שעליהם התאמן המודל.
כדי לבדוק את האפליקציה:
- מורידים לטלפון אחת מהתמונות של הכלב.
- בחלונית התצוגה המקדימה, לוחצים על הפעלת מצלמת האינטרנט.
- אם מוצגת תיבת דו-שיח בדפדפן עם בקשה להענקת גישה למצלמת האינטרנט, מעניקים הרשאה.
- מחזיקים את התמונה של הכלב בטלפון מול מצלמת האינטרנט. תיבת גבולות שבה מוצגים שם הכלב ורמת האמון של המודל.
- אם אין תיבת גבולות, פותחים את כלי הפיתוח ל-Chrome ובודקים אם יש שגיאות בחלונית מסוף. לחלופין, בודקים את השלבים הקודמים כדי לוודא שלא שכחתם משהו.
7. מזל טוב
מעולה! פיתחתם אפליקציית אינטרנט שמזהה אובייקטים בתמונות. מידע נוסף זמין בגרסה המלאה של האפליקציה ב-CodePen.