You are on page 1of 38

‫נושא ‪ :‬מערכת אבטחה מבוססת זיהוי פנים‪ ,‬ענן‬

‫ובינה מלאכותית‬

‫שם התלמיד ‪ :‬יובל יורן‬


‫מס‪ .‬ת‪.‬ז‪323867499 : .‬‬
‫בית ספר ועיר ‪ :‬תיכון "רבין" כפר סבא‬
‫שם המנחה ‪ :‬טדי גלעד‬
‫שם המורה המלווה ‪ :‬שגית הראל‬

‫העבודה נעשתה במסגרת התכנית‬


‫"מדעי המחשב‪ ,‬אקדמיה‪ ,‬ותעשייה"‪,‬‬
‫מכון דוידסון לחינוך מדעי‪,‬‬
‫מכון ויצמן למדע‬

‫שנה ‪2019 :‬‬

‫‪1‬‬
‫תוכן העניינים‬

‫‪1‬‬ ‫שער‬

‫‪2‬‬ ‫תוכן העניינים‬

‫‪3‬‬ ‫תקציר‬

‫‪3‬‬ ‫מבוא ורקע כללי‬

‫‪4‬‬ ‫מטרות העבודה‬

‫‪5‬‬ ‫בעיות אלגוריתמיות‬

‫‪11‬‬ ‫תיאור המודולים‬

‫‪12‬‬ ‫סביבות העבודה‬

‫‪13‬‬ ‫הערכת הפתרון‬

‫‪14‬‬ ‫ממשק המשתמש‬

‫‪16‬‬ ‫רפלקציה‬

‫‪17‬‬ ‫בבליוגרפיה‬

‫‪18-34‬‬ ‫נספח – פירוט הקוד‬

‫‪2‬‬
‫תקציר‬

‫בינה מלאכותית‪ ,‬תחום שקיים כבר עשרות שנים אך תפס תאוצה אדירה בתעשייה ובענפים שונים‬
‫של תחום מדעי המחשב בשנים האחרונות‪ .‬זיהוי פנים הוא נושא מרתק בתוך תחום הבינה‬
‫המלאכותית‪ ,‬יש לו מגוון שימושים בחיי היומיום שלנו ולשימושיו פוטנציאל עצום בתחומים שונים‪,‬‬
‫החל מאבטחה וביטחון וכלה בפסיכולוגיה וברשתות חברתיות‪.‬‬

‫בפרויקט שלי בחרתי לרתום את זיהוי הפנים לצורך זיהוי פניהם וזהותם של אנשים מוכרים‪,‬‬
‫המורשים להיכנס למבנה‪ ,‬בית או חדר כלשהם – עבורם תנוטרל מערכת אזעקה‪ .‬אם המבקשים‬
‫להיכנס אינם מוכרים‪ ,‬תישלח תמונתם לכתובת מייל מוגדרת מראש והודעה מתאימה (המשתנה‬
‫בהתאם לכמות האנשים שהמערכת מזהה) תישלח לטלפון הנייד של בעל המקום‪ ,‬היות שהם אנשים‬
‫זרים המנסים להיכנס למקום פרטי‪.‬‬

‫מבוא ורקע כללי‬

‫בהרחבה לגבי תחום הבינה המלאכותית‪ ,‬אני מתעניין בעיקר בתחום עיבוד התמונה וזיהוי הפנים‪.‬‬
‫באמצעות זיהוי תמונה ע"י שימוש בבינה מלאכותית ניתן לזהות חפצים‪ ,‬צמחים‪ ,‬פירות‪ ,‬מכוניות‪,‬‬
‫תמרורים‪ ,‬כתובות ועוד מגוון עצמים שונים מתחומים רבים‪ .‬בעיני הדבר המעניין ביותר לזיהוי הוא‬
‫בני אדם‪ ,‬בדגש על פני האדם והדרכים השונות להבדיל בין בני אדם שונים על ידי שימוש בתמונה‬
‫של פניהם‪ .‬לכן בחרתי לפנות לתחום מערכות האבטחה‪.‬‬

‫בעיה המתעוררת פעמים רבות במערכות אבטחה ואזעקה ביתיות וציבוריות היא בעיית אזעקות‬
‫השווא‪.‬‬
‫תשאלתי חברים וגיליתי שאנשים רבים נתקלים באזעקות שווא במערכת האזעקה הביתית שלהם‪,‬‬
‫בין אם שכחו לנטרל אותה כשנכנסו לביתם או שרוח הסיטה ווילון לתוך שדה הראייה של אחד‬
‫מחיישני התנועה‪ .‬הסיבה לכך היא שמערכות אבטחה כיום הן מיושנות – הן סומכות על גלאי תנועה‬
‫פשוטים על מנת להניח שהאדם הנכנס הוא פורץ‪ ,‬כל זאת בהנחה שהתנועה שעוררה את הגלאים‬
‫נעשתה על ידי אדם‪ .‬במקרים רבים וילון או החתול הביתי עלולים להפעיל את האזעקה וכך לגרום‬
‫לאזעקות שווא‪.‬‬

‫‪3‬‬
‫הפרויקט שלי פותר את הבעיות שציינתי בכך שהוא מזהה אם בתמונות שבמצלמת האבטחה קיימים‬
‫בני אדם או לא‪ .‬אם בתמונה יש בני אדם תווי פניהם יוצלבו עם תמונות האנשים המורשים שבמאגר‬
‫ובמידה ותימצא התאמה ‪ -‬תנוטרל האזעקה‪.‬‬

‫שירות הבינה המלאכותית המזהה כמה אנשים נמצאים בתמונה נעשה בסביבת‪ ,‬זה מאפשר חיסכון‬
‫בהיקף הזיכרון הדרוש לחומרה‪ ,‬כך אני מסוגל להריץ את הפרוייקט ממחשב זעיר‪ .‬שליחת ההודעות‬
‫וההתרעות נעשית בסביבת "נוד‪-‬רד"‪.‬‬

‫שירות זיהוי הפנים והצלבתם עם מאגר תווי הפנים דורש תוכניות שיקבעו מה יקרה עם הקלט‬
‫מהמצלמה וינהלו את מאגר הנתונים‪ .‬לצורך כך נעשה שימוש בספרייה בסביבת לינוקס המסייעת‬
‫בטיפול בתווי הפנים בשם ‪.OpenCV‬‬

‫כיום קיימות תוכנות רבות המשתמשות בזיהוי פנים‪ ,‬אולם‪ ,‬רק חלק קטן מהן מבצע זיהוי ממשי‪ ,‬יש‬
‫לשים לב להבדל שבין איתור פרצוף בתוך תמונה (‪ )Detection‬ובין זיהוי של אדם מסויים‬
‫שפניו מופיעות בתמונה (‪ . )Recognition‬הפרוייקט שלי מסוגל להבדיל בין פרצופים שונים‬
‫ובכך לזהות את זהותו של אדם (‪ ,)Recognition‬כך אני בודק האם האדם מורשה להיכנס או לא‪,‬‬
‫על ידי הצלבה עם הפרצופים שבמאגר הפנים‪ .‬אם האדם אינו מזוהה על ידי המערכת‪ ,‬תמונתו‬
‫נשלחת לענן ומספר הפרצופים בה נספר על ידי בינה מלאכותית בשם ‪ Watson‬המבצעת איתור‬

‫פנים (‪ )Detection‬ובאמצעותה אני שולח התראות המתאימות למספר הפרצופים שבתמונה‪.‬‬

‫מטרות העבודה‬

‫יצירה ועריכה של מאגר נתונים (מאגר תווי הפנים)‬ ‫‪‬‬

‫קליטת פנים ‪ -‬צילום סדרת תמונות של אדם מסוים‪ ,‬קטלוגן במאגר ושיוכן לזהותו של האדם‪.‬‬ ‫‪‬‬

‫זיהוי פנים בזמן אמת – כאשר עומדים מול המצלמה‪ ,‬בזמן אמת מוצג וידאו ובו מלבנים ירוקים‬ ‫‪‬‬
‫מסמנים את כל הפרצופים שבתמונה‪ ,‬תוך הצגת שמות האנשים המזוהים‪.‬‬

‫התראה מפני פולשים – זיהוי מצבים בהם עומדים אנשים לא מוכרים מול המצלמה‪ ,‬שמירת‬ ‫‪‬‬
‫תמונה של האירוע ושליחתה במייל לכתובת המייל‪ ,‬בצירוף ‪ SMS‬והודעה מתאימים‪.‬‬

‫‪4‬‬
‫בעיה אלגוריתמית מספר ‪1‬‬

‫הבעיה הראשונה המתעוררת היא הבחירה באלגוריתם בו נעשה זיהוי הפנים ואימון הבינה המלאכותית‬
‫(למידת מכונה)‪ .‬ישנו מספר רחב של אלגוריתמים המסייעים בזיהוי אדם לפי פניו ובשמירת פרטיהם של‬
‫אנשים שונים במאגר נתונים‪ .‬האתגר הראשון הוא להבין איך ניתן לזהות פנים ומלבחור את השיטה שהכי‬
‫נוחה למימוש מטרות הפרויקט‪.‬‬

‫פתרון אפשרי לבעיה מספר ‪ + 1‬שלילה‬

‫רבים הנחשפים לתחום זיהוי הפנים רואים בשיטת הזיהוי הביומטרי והלמידה העמוקה כבחירה‬
‫הטריוויאלית לצורך פיענוח זהותו של אדם‪ ,‬באמצעות המרחקים בין העיניים‪ ,‬גובה המצח‪ ,‬האף‪ ,‬השפתיים‬
‫ושאר הפרטים המרכיבים את הפנים שלנו‪ ,‬זאת משום שאנחנו כבני אדם מזהים את מכרינו בדרך זו‪ ,‬לפי‬
‫מאפייני הפנים שלהם‪ ,‬התמונה להלן מהווה אילוסטרציה‪:‬‬

‫שיטה זו עושה שימוש בלמידה עמוקה ( ‪Deep‬‬


‫‪ , )Learning‬סוג של לימוד מכונה בו באמצעות‬
‫שליחת תמונה של עצם מסויים וקבלת מילה אחת‬
‫(‪ )Label‬או קורדינטות כפלט ‪ ,‬מאמנים תוכנית לזיהוי‬
‫עצמים בתמונה‪ .‬במהלך המחקר המקדים שלי הבנתי‬
‫שזו דרך מסובכת ולא מדויקת לזהות פרצוף של בן‬
‫אדם‪ ,‬יש בה שגיאות רבות ולעיתים קרובות אנשים‬
‫דומים או בעלי מאפיינים בעלי מידות זהות עשויים‬
‫להיקלט כאדם אחד‪ ,‬דבר שאסור שיקרה במערכת‬
‫אבטחה ולכן זו לא הדרך בה אני בחרתי לפתור את‬
‫דילמת לימוד הזיהוי‪.‬‬

‫‪5‬‬
‫הפתרון שלי לבעיה אלגוריתמית מספר ‪1‬‬

‫אני בחרתי להשתמש בלמידה מטרית עמוקה (‪ )Deep Metric Learning‬בשיטה זו לא מקבלים מילה‬
‫או מיקום כפלט אלא וקטור‪ .‬בעת יישום שיטה זו לצורכי זיהוי פנים מתייחסים לפנים כאל טבלה של ריבועי‬
‫פיקסלים (‪ 3x3‬פיקסלים) בצבע שחור ולבן‪ ,‬באמצעות פיקסלים בהירים וכהים‪ ,‬מותחים וקטור עבור כל‬
‫ריבוע שכזה‪ .‬לבסוף מהתמונה מקבלים סדרה ארוכה של מספרים המייצגים וקטורים בין הפיקסל הבהיר‬
‫ביותר בכל ריבוע לפיקסל הכהה ביותר‪ .‬סדרת המספרים הזו היא ייחודית עבור כל אדם ובאמצעות איסוף‬
‫של כמה עשרות תמונות של האדם‪ ,‬ניתן לזהותו בכל תמונה בה מופיעים פניו‪ .‬להלן תמונות הממחישות את‬
‫יצירת הוקטורים במהלך זיהוי הפנים המטרי (‪:)Deep Metric Face Recognition‬‬

‫כהה ביותר‬

‫בהיר ביותר‬

‫מצאתי שזוהי שיטה מאוד נוחה לעבודה מכיוון שהווקטורים הללו משמשים ליצירה של קטע טקסט המורכב‬
‫מ‪ 128-‬מספרים‪ ,‬אותו ניתן להצליב ל‪ 128‬וקטורים המופקים מתמונה של אנשים לא מזוהים שנקלטים‬

‫‪6‬‬
‫בעדשת המצלמה של המערכת‪ .‬זה נעשה באמצעות תהליך של מעבר ברשת נוירונים באמצעות ספריית‬
‫‪ Python‬בשם ‪ ,OpenCV‬עליה ארחיב בהמשך‪.‬‬

‫אימון של רשת נוירונים לצורך זיהוי פנים ברמה של שיוך פנים לזהות הוא תהליך הדורש איסוף של מספר‬
‫רב מאוד של פרצופים‪ ,‬לפחות כמה אלפי תמונות‪ ,‬רובן מוכרחות להיות בזוגות של תמונות‪ ,‬שבשתיהן נמצא‬
‫אותו האדם‪ .‬כל זוג שכזה מוכרח להיות מסומן כזוג תמונות של אותו האדם‪ .‬כיום‪ ,‬אנשים בודדים מאמנים את‬
‫רשתות הנוירונים של עצמם‪ ,‬בעוד שהרוב המוחץ של המפתחים משתמשים ברשתות נוירונים שאומנו כבר‬
‫במסגרת ספריות קוד פתוח (‪ )Open Source‬וכך נחסכות מהם שעות רבות של אימון רשת נוירונים על מנת‬
‫שתהיה מדויקת מספיק‪.‬‬

‫כדי לפתור את הקושי שבאימון רשת הנוירונים לזיהוי פנים‪ ,‬השתמשתי בספריית ‪ OpenCV‬שהיא פרויקט‬
‫קוד פתוח בו נאספו למעלה מ‪ 3-‬מליון תמונות של אנשים‪ ,‬אותן העבירו דרך רשת הנוירונים ושינו אותה מעט‬
‫בכל פעם על מנת להגיע לתוצאות מדויקות ככל האפשר בהצלבה וזיהוי של שני פרצופים של אותו האדם (על‬
‫ידי הגעה לוקטורים קרובים ככל הניתן מתמונות שונות של אותו האדם)‪ .‬בספרייה הזו נעשה שימוש במסגרת‬
‫הפרוייקט על מנת להפוך את הפרצופים הנראים בדלת לוקטורים‪ ,‬לאחר מכן למספרים ולבסוף להצליב אותם‬
‫עם המספרים שהופקו מהעברת התמונות שבמאגר הנתונים דרך רשת הנוירונים‪.‬‬

‫ההיבט של רמת הדיוק הוא קריטי בתחום האבטחה ואלגוריתם הזיהוי של רשת הנוירונים המאומנת מדויק‬
‫ב‪ 99.38%-‬מהמקרים‪ ,‬לפי דייויס קינג‪ ,‬האדם שניהל את פרויקט האימון של רשת הנוירונים‪ .‬אלו אחוזים‬
‫גבוהים מאוד כשזה נוגע לזיהוי פנים ולכן שיטת הלמידה המטרית העמוקה היא פתרון מעולה לבעיה‬
‫האלגוריתמית שבפניה ניצבתי‪.‬‬

‫‪7‬‬
‫סקיצה המתארת את תהליך אימון רשת הנוירונים באמצעות ‪ 2‬תמונות של אותו האדם ותמונה אחת של אדם שונה אך דומה‪:‬‬

‫‪8‬‬
‫בעיה אלגוריתמית מספר ‪2‬‬

‫לאחר סיום הפיתוח הראשוני (אב‪-‬טיפוס) נתקלתי בבעיה בפעולת קטע התוכנית העוסק בסינון פרצופים‬
‫לשתי קטגוריות – מזוהים ולא מזוהים‪ ,‬כמוצג להלן‪:‬‬

‫הצלבה עם מאגר הפנים‬

‫אין התאמה‬ ‫יש התאמה‬


‫האדם לא מזוהה‬ ‫האדם מזוהה‬
‫[נשלחת התראה]‬ ‫[ניתנת גישה]‬

‫הבעיה הייתה פשוטה – לעיתים‪ ,‬כאשר אדם מורשה נעמד מול המצלמה‪ ,‬במשך מספר פריימים בודדים‬
‫הייתה מוצגת הודעה לפיה האדם לא מזוהה‪ .‬לאחר רגע ההודעה הייתה מתחלפת לשמו של האדם המזוהה אך‬
‫קטע הקוד שעסק בטיפול בהודעות הגישה (‪ ACCESS DENIED‬ו‪ )ACCESS GRANTED-‬היה שולח‬
‫הודעת "‪ "ACCESS DENIED‬לאחר פריים בודד בו המערכת לא זיהתה את פני האדם העומד בכניסה‪ .‬זה‬
‫גרם לכך שגם אנשים בעלי הרשאה קיבלו הודעת "‪ "ACCESS DENIED‬בגלל הדיליי בקליטה‪.‬‬

‫פתרון אפשרי לבעיה מספר ‪ + 2‬שלילה‬

‫ניתן להוסיף דיליי (‪ )Delay‬בין זיהוי הפנים ובין רגע שליחת הודעת הגישה‪ .‬בעצם‪ ,‬לאחר שזוהו פנים‪ ,‬בין‬
‫אם כפנים של אדם מורשה ובין אם לא‪ ,‬המערכת תחכה מספר שניות עד שתיתן כל התראה‪ .‬השיטה הזו לא‬
‫טובה בעיני מכיוון שכאשר אדם מבקש להיכנס לביתו או לחדר מסויים‪ ,‬הוא רוצה לעשות זאת באופן מיידי‬

‫‪9‬‬
‫ובלי עיכובים‪ .‬דיליי של ‪ 5‬שניות עשוי להיות משמעותי בחוויית המשתמש ואני מעדיף לבחור בפתרון שבו‬
‫הודעות הגישה יגיעו מהר יותר‪.‬‬

‫‪10‬‬
‫הפתרון שלי לבעיה אלגוריתמית מספר ‪2‬‬

‫את הבעיה פתרתי באמצעות משתנה סוכם ‪ . int count1‬המשתנה גדל בכל פעם שמישהו מזוהה נקלט‬
‫במצלמה‪ ,‬המשתנה יורד בכל פעם שמישהו לא מזוהה נקלט במצלמה‪.‬‬
‫הודעות הגישה (‪ ACCESS DENIED‬ו‪ )ACCESS GRANTED-‬נשלחות רק כאשר המשתנה הסוכם עובר‬
‫מספר מסויים וכך בעצם נדרש מספר מסויים של פריימים רצופים שבהם ייקלט אדם מזוהה או לא מזוהה על‬
‫מנת לאפשר גישה או למנוע אותה‪ .‬זו בעצם רשת בטחון המאפשרת לצמצם משמעותית את שגיאות המערכת‬
‫על ידי הקטנת אחוז הטעות מ‪( 0.0062-‬אזכיר כי אחוז הדיוק של רשת הנוירונים הוא ‪ ,99.38%‬מכאן‬
‫אחוז השגיאה הוא ‪ )0.62%‬ל‪ 0.0062-‬בחזקת מספר הפריימים בהם נדרש זיהוי על מנת שהמשתנה הסוכם‬
‫יעבור את הרף שהצבתי‪.‬‬

‫הפתרון לבעיה אלגוריתמית ‪ 2‬איננו מושלם ובעקבותיו נחשפה בעיה אלגוריתמית נוספת‪:‬‬

‫בעיה אלגוריתמית מספר ‪3‬‬

‫כעת‪ ,‬עבור קליטת פנים מזוהות ‪ count1‬עולה ועבור קליטת פנים בלתי מזוהות ‪ count1‬יורד‪ ,‬אולם‪,‬‬
‫עלולה להתעורר בעיה כאשר מגיע אדם מזוהה בליווי אדם שאינו מזוהה; חבר‪ ,‬שותף‪ ,‬קרוב משפחה רחוק‬
‫או כל אורח אחר‪ .‬במקרה כזה‪ ,‬יקלטו פנים מזוהות ויעלו את הסוכם ובו בזמן יקלטו גם פנים בלתי מזוהות‬
‫ויורידו את הסוכם בחזרה‪ .‬במקרה שכזה‪ ,‬המערכת לא תציג שום הודעה מאחר שהסוכם לא יעלה ולא ירד‬
‫מנקודת שיווי המשקל שבה הוא נמצא‪.‬‬

‫פתרון אפשרי לבעיה מספר ‪+ 3‬שלילה‬

‫ניתן לקבוע כי ברגע שבו יקלטו פנים מזוהות‪ ,‬תינתן הודעת גישה חיובית "‪ ,"ACCESS GRANTED‬אולם‪,‬‬
‫כאשר אדם עובר ליד ביתו מבלי כוונה להיכנס‪ ,‬או בעת שהוא יוצא מן הבית (לעבודה או לקניות) פניו‬
‫עלולים להיקלט לשבריר שנייה בעדשת המצלמה‪ .‬מתן גישה באופן מיידי עלולה להוביל לנטרול לא מכוון‬
‫של מערכת האזעקה‪ .‬לכן יש למצוא פתרון שבו עדיין מוכרחים להביע כוונה להיכנס על ידי חשיפת הפנים‬
‫לאורך מספר פריימים‪.‬‬

‫‪11‬‬
‫הפתרון שלי לבעיה אלגוריתמית מספר ‪3‬‬

‫הפתרון שמצאתי הוא פשוט למדי‪ .‬פשוט שיניתי את הקוד כך שבעת מציאת פנים מזוהות הסוכם יגדל בסכום‬
‫גדול ובעת גילוי פנים בלתי מזוהות הסוכם יגדל בסכום קטן‪ ,‬כך שלא יהיה גדול מספיק בשביל לבטל את‬
‫השפעת הפנים המזוהות על הסוכם‪ ,‬אך גדול מספיק בשביל לרדת מתחת לרף התחתון ולספק התראה‬
‫במהירות האפשרית בעת מפגש עם אדם לא מזוהה בלבד‪.‬‬

‫לאחר השינוי הזה מערכת הודעות הגישה פעלה כראוי‪ ,‬זיהתה אנשים מורשים והעניקה להם הודעת‬
‫‪ ACCESS GRANTED‬ולאנשים בלתי מזוהים העניקה הודעת ‪ .ACCESS DENIED‬בנוסף‪ ,‬כאשר עומד‬
‫אדם מוכר יחד עם אדם לא מוכר‪ ,‬המערכת תעניק להם גישה‪.‬‬

‫‪12‬‬
‫תיאור המודולים של מערכת התוכנה‬

‫‪Run_Project.py‬‬
‫תפריט השליטה והניווט בין חלקי הפרויקט‪ ,‬באמצעות הטרמינל ניתן לגשת לכל אחת מהתוכניות העיקריות של הפרויקט‪.‬‬
‫זוהי למעשה תוכנית שבאמצעותה ניתן לפתוח ולהשתמש בשאר התוכניות‪ .‬התוכנית מכילה תפריט ומאפשרת פתיחה של‬
‫התוכניות האחרות באמצעות קלטים שונים‪ ,‬תוך מתן עדכוני מצב המסייעים ומקלים את חווית המשתמש‪.‬‬

‫‪record_face.py‬‬ ‫‪trainer.py‬‬ ‫‪detector.py‬‬ ‫‪short_detector.py‬‬


‫תוכנית המצלמת ‪50‬‬ ‫תוכנית המעבירה את‬ ‫משמשת לבדיקה (ריצת‬ ‫הפעלת מערכת האזעקה‪,‬‬
‫תמונות של פנים מסויימות‬ ‫התמונות שבמאגר הפנים‬ ‫מבחן) ‪ -‬תוכנית המציגה‬ ‫זיהוי פרצופים ושליחת‬
‫וקולטת שם עבורן‪.‬‬ ‫(זוהי למעשה תיקייה שבה‬ ‫סרטון ובו מלבן ירוק ושם‬ ‫הודעות גישה מתאימות‪.‬‬
‫התוכנית שומרת את‬ ‫שמורות התמונות שנקלטו‬ ‫מוצגים מסביב לפניו של כל‬ ‫במקרה של זיהוי חיובי‪,‬‬
‫התמונות תחת השם‬ ‫מ‪)Record_face.py-‬‬ ‫אדם הנראה בעדשת‬ ‫התוכנית נסגרת‪ .‬התוכנית‬
‫הנקלט‪.‬‬ ‫המצלמה בזמן אמת‪.‬‬ ‫הזו היא למעשה יישום‬
‫מטרות הפרויקט כמערכת‬
‫אבטחה אמיתית‪.‬‬

‫‪Node RED flow‬‬


‫תוכנית (‪ )flow‬בסביבת ‪ .NodeRED‬התוכנית מקבלת תמונה שהמערכת‬
‫שלחה כתמונה של אנשים לא מזוהים (פורצים פוטנציאליים)‪ ,‬שולחת אותה‬
‫לבינה מלאכותית בשם ‪ Watson‬שסופרת כמה פרצופים יש בתמונה‪ .‬לאחר‬
‫מכן התוכנית הזו שולחת הודעה מתאימה למייל (בצירוף התמונה) והודעת‬
‫טקסט מתאימה לטלפון הנייד‪ .‬התוכנית הזו שמורה ב‪ BROWSER-‬ולא ניתן‬
‫לשמור אותה בתיקייה‪ ,‬מכיוון ש ‪ NodeRED‬היא סביבת עבודה מיוחדת‪.‬‬

‫‪13‬‬
‫אני משתמש גם במסד נתונים בשם ‪ database.db‬המסד מכיל את פרטי המשתמשים בטבלה‪:‬‬

‫שם הטבלה‪users :‬‬

‫קיימים שני טורים בטבלה‪:‬‬

‫‪ – id )1‬מספר מזהה למשתמש (משתמש ראשון שנקלט מקבל את מספר ‪ ,1‬השני את‬
‫‪ ,2‬השלישי את ‪ 3‬וכו')‬

‫‪ – name )2‬שם המשתמש שנקלט על ידי המערכת בעת השימוש בתוכנית "‪."record_face.py‬‬

‫סביבות העבודה‬

‫‪ )1‬שפה‪Python 3 :‬‬
‫סביבת העבודה‪( Geany :‬סביבת עבודה בפייטון ללינוקס)‬
‫כלים‪ :‬ספריית )‪ OpenCV (cv2‬להתעסקות עם זיהוי הפנים‬
‫ספריות נוספות‪numpy, sqlite3, sys, os, time, termcolor, :‬‬

‫‪ )2‬שפה‪Node-RED :‬‬
‫סביבת העבודה‪Node-RED (nodered.org) :‬‬

‫‪14‬‬
‫הערכת הפתרון‬

‫כיום קיימות מספר מערכות אבטחה חכמות בעולם‪ ,‬אך ברובן המוחלט נעשה שימוש בסורק רשתית או‬
‫טביעת אצבע‪ .‬מאחר שלא נתקלתי במערכת לזיהוי פנים כמערכת אבטחה לחדר או לבית‪ ,‬אפנה למערכת‬
‫האבטחה הדומה ביותר שגם מוכרת בציבור הרחב – פתיחת טלפונים באמצעות זיהוי פנים‪.‬‬

‫המערכת שלי מאפשרת גישה באופן כמעט מיידי‪ ,‬לא מורגש שום עיכוב ולכן אני מאמין שמבחינת מהירות‪,‬‬
‫המערכת שלי שווה למערכות הקיימות בטלפונים חכמים בפריסה עולמית‪.‬‬
‫ההיבט השני שדורש השוואה הוא היבט האבטחה‪.‬‬

‫האם ניתן לרמות את מערכת האבטחה שלי? בוודאי שכן‪ .‬באמצעות תמונה באיכות מספיק טובה ומזווית‬
‫משכנעת ניתן לגרום לזיהוי חיובי על ידי המערכת‪ ,‬בדיוק כמו שניתן היה לעשות גם ברוב הטלפונים‬
‫החכמים שהשתמשו בזיהוי פנים בשנים האחרונות‪ .‬אולם‪ ,‬מאז השנתיים האחרונות‪ ,‬טלפונים מתחילים‬
‫לדרוש סימנים לחיים אצל הפנים המוצגות בפניהם – מצמוץ‪ ,‬נשימות‪ ,‬דופק ועוד סממנים היחודיים לאנשים‬
‫בשר ודם הופכים לדרישה אצל יצרני הטלפונים‪ .‬באייפונים החדשים נעשה שימוש באלפי קרני לייזר זעירות‬
‫שממפות את פני המשתמש בתלת מימד וכתוצאה מכך לא ניתן לזייף את פניו של בעל הגישה למכשיר‪.‬‬
‫הפרויקט שלי הוא פרויקט לימודי ואיננו מוצר שיוצא לשוק‪ ,‬בהיקף התקציב שלי לא ניתן להשיג טכנולוגיית‬
‫מיפוי תלת מימדי באמצעות קרני לייזר זעירות ואני מרוצה מזיהוי הפנים שאני מבצע במסגרת הפרוייקט‬
‫שלי כרגע‪ .‬אפשרות ההתחזות אינה מדאיגה אותי בשלב זה‪.‬‬

‫‪15‬‬
‫שימוש במסכה שיכול לשמש על מנת‬ ‫אילוסטרציה של זיהוי‬
‫לרמות את מערכת האבטחה שלי‬ ‫הפנים במכשירי האייפון‬

‫תיאור ממשק המשתמש‬

‫צילום מסך‪:‬‬
‫ממשק המשתמש הוא תפריט בחירה בין ‪ 5‬אפשרויות‪:‬‬

‫‪R‬‬ ‫‪)1‬הקלטת פנים – ‪Record Face‬‬

‫‪T‬‬ ‫‪)2‬אימון המידע שהוקלט – ‪Train Data‬‬

‫‪D‬‬ ‫‪)3‬תוכנית בדיקת זיהוי – ‪Detector Testing Program‬‬

‫‪S‬‬ ‫‪)4‬התחל זיהוי – ‪Start Detector‬‬

‫‪X‬‬ ‫‪)5‬יציאה – ‪Exit‬‬

‫הבחירה באחת מן האפשרויות נעשית על ידי הקלדת האות האנגלית המתאימה לבחירת המשתמש (‪,D ,T ,R‬‬
‫‪ – )X ,S‬זה נעשה בתוך התוכנית ‪.Run_Project.py‬‬

‫כל אפשרות מפעילה פעולה בתוך תוכנית ה‪ Run_Project.py-‬ולהלן פעולותיהן בהתאמה‪:‬‬

‫‪)1‬הפעלת תוכנית ‪record_face.py‬‬

‫הסברים לתוכניות בפרק "תיאור‬ ‫‪16‬‬

‫המודולים של מערכת התוכנה"‬


‫‪ )2‬הפעלת תוכנית ‪trainer.py‬‬

‫‪ )3‬הפעלת תוכנית ‪detector.py‬‬

‫‪ )4‬הפעלת תוכנית ‪short_detector.py‬‬

‫‪ )5‬סגירת תוכנית ‪( Run_Project.py‬יציאה)‬

‫הסברים לכל בחירה‪:‬‬

‫‪R‬‬ ‫‪)1‬הקלטת פנים – ‪Record Face‬‬

‫לאחר הבחירה באפשרות זו‪ ,‬יש לכתוב את שם האדם שפניו מצולמים וללחוץ על ‪. Enter‬‬

‫לאחר מכן‪ ,‬יצולמו ‪ 50‬תמונות של פניו וישמרו תחת השם שהוקלד‪ .‬לאחר ביצוע שלב זה יש לבחור‬
‫באפשרות ‪ Train Data‬על מנת שהשינויים ישמרו ויאומנו על ידי המערכת‪.‬‬

‫‪T‬‬ ‫‪)2‬אימון המידע שהוקלט – ‪Train Data‬‬

‫בחירה באפשרות זו תרוץ בין כל התמונות שבמערכת ו"תלמד" את הבינה המלאכותית‪ .‬אין צורך בפעילות‬
‫נוספת‪.‬‬

‫‪D‬‬ ‫‪)3‬תוכנית בדיקת זיהוי – ‪Detector Testing Program‬‬

‫תוכנית זו תדגים את פעילות המערכת מבלי לשלוח התראות ומבלי לסגור את התוכנית‪ .‬על מנת לצאת ממנה‬
‫יש ללחוץ על מקש ה‪.Esc-‬‬

‫‪17‬‬
‫‪S‬‬ ‫‪)4‬התחל זיהוי – ‪Start Detector‬‬

‫תוכנית זו תפעיל את מערכת האבטחה במצב אמת‪ ,‬תתריע מפני פולשים ותיסגר במקרה של זיהוי אדם‬
‫מורשה‪ .‬על מנת לצאת ממנה ללא זיהוי אדם מורשה יש ללחוץ על ‪.Esc‬‬

‫‪X‬‬ ‫‪)5‬יציאה – ‪Exit‬‬

‫בחירת אפשרות זו תסגור את התוכנית‪.‬‬

‫תוכנית בדיקת הזיהוי בפעולה‪:‬‬ ‫כתיבת שם האדם המצולם בתוכנית הקלטת הפנים‪:‬‬

‫רפלקציה‬

‫למדתי הרבה מאוד במהלך פיתוח הפרויקט‪ .‬דרך סרטוני הדרכה וחוברות אינטרנטיות שונות למדתי את העקרונות‬
‫שהנחו אותי ביצירת הפרויקט הזה‪ .‬אני מרוצה מהתוצאה של העבודה הקשה שעשיתי לאורך השנה ואני מאוד גאה‬
‫בפרויקט שלי‪.‬‬

‫‪18‬‬
‫התהליך שעברתי הוא משמעותי מכיוון שבתחילת שלב המחקר‪ ,‬הידע שלי הסתכם בידע הנדרש לבגרות במדעי‬
‫המחשב‪ ,‬לעומת זאת‪ ,‬היום אני יודע לתכנת בשפות שלא ידעתי לפני כן‪ ,‬יש לי ידע רחב בנושאים מעניינים כמו עיבוד‬
‫תמונה‪ ,‬זיהוי פנים‪ ,‬למידת תכונה‪ ,‬בינה מלאכותית ועוד‪.‬‬

‫את העבודה חילקתי למספר חלקים‪:‬‬

‫‪ )1‬מחקר – שלב צבירת המידע‪ ,‬הידע וההתמצאות בתחום‪ .‬בשלב זה חיפשתי ברחבי הרשת אנשים שעשו פרויקטים‬
‫דומים לשלי‪ ,‬על מנת ללמוד מה היו הקשיים שלהם‪ ,‬מה עובד טוב יותר ופחות‪ ,‬לצורך תכנון נכון וביצוע מדויק של‬
‫הפרויקט שלי‪ .‬בשלב זה למדתי באילו רכיבי חומרה כדאי לי להשתמש‪.‬‬

‫‪ )2‬פיתוח – אחרי שאספתי אץ המידע הנחוץ שכלל ידע בסיסי בפייתון‪ ,‬מדריכים‪ ,‬סרטונים וכתבות בנושא זיהוי פנים;‬
‫ואת החומרה הדרושה שכללה ראספברי פיי‪ ,‬מצלמה‪ ,‬מקלדת ועכבר; התחלתי את כתיבת התוכניות השונות שמרכיבות‬
‫את ספריית הפרוייקט‪ .‬נעזרתי רבות בכתבות ומדריכים והתאמתי מספר תוכניות לצרכים של הפרוייקט שלי‪.‬‬

‫‪ )3‬שיפור – לאחר שהמערכת הייתה קיימת ועבדה כהלכה התחלתי את שלב השיפור‪ .‬שלב זה כלל את כתיבת תוכנית‬
‫התפריט וממשק המשתמש‪ ,‬ייעול של התוכניות ומתן מענה לבעיות אלגוריתמיות שונות‪.‬‬

‫החלוקה הזו עזרה לי מאוד ואני ממליץ לכל תלמידי התוכנית בעתיד לעבוד בצורה זו‪.‬‬

‫אני שמח מאוד שבחרתי לקחת חלק בתוכנית והעובדה שפיתחתי פרוייקט גמור היא מקור לגאווה עבורי שילווה אותי‬
‫גם בהמשך החיים ובפיתוח הקריירה שלי‪.‬‬

‫‪19‬‬
‫בבליוגרפיה‬

:‫רשימת סרטונים‬

)‫(הדגמות של פרוייקטים בנושא זיהוי פנים באמצעות ראספברי פיי‬

 Raspberry Pi Face Recognition Demo - Adrian Rosebrock


https://www.youtube.com/watch?v=DMwk4c4bTJE
 Face recognition OpenCV Raspberry Pi – Jacky Le
 https://www.youtube.com/watch?v=Fggavxx-Kds

:‫רשימת כתבות‬

)‫ רכיבים אלקטרוניים ואלגוריתמים לביצוע זיהוי פנים‬,‫(כתבות המכילות קטעי קוד‬

 Facial recognition: OpenCV on the camera board -


https://www.raspberrypi.org/blog/facial-recognition-opencv-on-the-camera-
board/
 How to Set Up OpenCV on Raspberry Pi for Face Detection
https://maker.pro/raspberry-pi/tutorial/how-to-set-up-opencv-on-raspberry-pi-
for-face-detection
 Real-Time Face Recognition: An End-to-End Project
https://www.hackster.io/mjrobot/real-time-face-recognition-an-end-to-end-
project-a10826
 Real Time Face Recognition with Raspberry Pi and OpenCV
https://circuitdigest.com/microcontroller-projects/raspberry-pi-and-opencv-
based-face-recognition-system

:‫רשימת אתרים‬

)‫(אתרים שעוסקים או שיש בהם קהילות שעוסקות בזיהוי פנים באמצעות ראספברי פיי‬

20
 https://www.pyimagesearch.com/
 https://circuitdigest.com/
 https://maker.pro/
 https://www.hackster.io/

21
‫נספח – פירוט הקוד‬

‫‪PYTHON‬‬

‫‪22‬‬
Run_Project.py
1. import os Run_Project.py
2. import cv2
3. import time ,‫תפריט השליטה והניווט בין חלקי הפרויקט‬
4. import sys
5. from termcolor import colored, cprint
‫באמצעות הטרמינל ניתן לגשת לכל אחת‬
6. .‫מהתוכניות העיקריות של הפרויקט‬
7. def action(): ‫זוהי למעשה תוכנית שבאמצעותה ניתן לפתוח‬
8. os.system("clear")
9. nodered = input("Is NODE-RED on? [Y/N]") ‫ התוכנית מכילה‬.‫ולהשתמש בשאר התוכניות‬
10. if nodered == "y": ‫תפריט ומאפשרת פתיחה של התוכניות האחרות‬
11. loop = True ‫ תוך מתן עדכוני מצב‬,‫באמצעות קלטים שונים‬
12. else:
13. loop = False .‫המסייעים ומקלים את חווית המשתמש‬
14. cprint("Type 'node-red-
start' in Terminal before you activate the program again",'red')
15. if loop:
16. os.system("clear")
17. cprint("Welcome to A-eye Security System",'yellow','on_white')
18. cprint(" by Yuval Yoran - Davidson inst.",'yellow','on_white')
19. while loop:
20. print()
21. print(colored(' Menu ','blue','on_white'))
22. #print(colored('C - Create Database','blue','on_white'))
23. print(colored('R - Record Face','blue','on_white'))
24. print(colored('T - Train Data','blue','on_white'))
25. print(colored('D - Detector Testing Program','blue','on_white'))
26. print(colored('S - Start Detector','blue','on_white'))
27. print(colored('X - Exit','red','on_white'))
28. user_action = input("Choose Action:")
29.
30. if user_action == 'r':
31. os.system("clear")
32. record_face()
33.
34. elif user_action == 't':
35. os.system("clear")
36. train_data()
37.
38. elif user_action == 's':
39. os.system("clear")
40. run_detector()
41.
42. elif user_action == 'd':
43. os.system("clear")
44. run_test()
45.
46. elif user_action == 'x':
47. os.system("clear")
48. print(colored(' [Program Closed] ','red'))
49. sys.exit()
50.
51. #elif user_action == 'c':
52. # create_database() # call the respective action function here
53.
54. else:
55. print()

23
56. print(colored("Please only type \'R\', \'T\', \'D\', \'S\'or \'X\'",
'red'))
57. print()
58.
59. #def create_database():
60. # print()
61. # print("Creating Database...")
62. # os.system("cd /home/pi/Desktop/opencv_face_recognition-
master; python3 create_database")
63. # print()
64. # print(colored("[Database Created Successfully]",'magenta'))
65. # print()
66.
67. def record_face():
68. print()
69. print(colored(" Face Recording Engaged... ",'blue', 'on_white'))
70. face_name = input("Please enter your name:")
71. print(colored("Say cheese! 50 pictures of you will now be taken...",'yellow'
))
72. os.system("cd /home/pi/Desktop/opencv_face_recognition-
master; python3 record_face.py "+face_name)
73. print()
74.
75. def train_data():
76. print()
77. print(colored(" Training Data... ",'blue', 'on_white'))
78. os.system("cd /home/pi/Desktop/opencv_face_recognition-
master; python3 trainer.py")
79. print()
80. print(colored("[Training Finished Successfully]", 'green'))
81. print()
82.
83. def run_test():
84. print()
85. print(colored(" Running Testing Program... ",'blue', 'on_white'))
86. print(colored(" Press 'esc' to Exit to Menu ",'blue', 'on_white'))
87. os.system("cd /home/pi/Desktop/opencv_face_recognition-
master; python3 detector.py")
88.
89. def run_detector():
90. print()
91. print(colored(" Running Program... ",'blue', 'on_white'))
92. os.system("cd /home/pi/Desktop/opencv_face_recognition-
master; python3 short_detector.py")
93.
94. action()

24
Record_face.py
1. import cv2
2. import numpy as np record_face.py
3. import sqlite3
4. import os
5. import sys 50 ‫תוכנית המצלמת‬
6. from termcolor import colored, cprint ‫תמונות של פנים מסויימות‬
7. .‫וקולטת שם עבורן‬
8.
9. conn = sqlite3.connect('database.db') ‫התוכנית שומרת את‬
10. if not os.path.exists('./dataset'): ‫התמונות תחת השם‬
11. os.makedirs('./dataset')
12.
.‫הנקלט‬
13. c = conn.cursor()
14.
15. face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
16.
17. cap = cv2.VideoCapture(0)
18.
19. uname= sys.argv[1] #name input goes here
20.
21. c.execute('INSERT INTO users (name) VALUES (?)', (uname,))
22.
23. uid = c.lastrowid
24.
25. sampleNum = 0
26.
27. while True:
28. ret, img = cap.read()
29. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
30. faces = face_cascade.detectMultiScale(gray, 1.3, 5)
31. for (x,y,w,h) in faces:
32. sampleNum = sampleNum+1
33. cv2.imwrite("dataset/User."+str(uid)+"."+str(sampleNum)+".jpg",gray[y:y+
h,x:x+w])
34. cv2.rectangle(img, (x,y), (x+w, y+h), (255,0,0), 2)
35. cv2.waitKey(100)
36. cv2.imshow('img',img)
37. cv2.waitKey(1);
38. #print ('['+str(sampleNum)+'% completed]')
39. if sampleNum > 49:
40. print(colored("[Face Recording is Successful for "+uname+"]", 'green'))

41. break
42. cap.release()
43.
44. conn.commit()
45.
46. conn.close()
47. cv2.destroyAllWindows()

25
Trainer.py
trainer.py
‫תוכנית המעבירה את‬
‫התמונות שבמאגר הפנים‬
1. import os ‫(זוהי למעשה תיקייה שבה‬
2. import cv2 ‫שמורות התמונות שנקלטו‬
3. import numpy as np
)Record_face.py-‫מ‬
4. from PIL import Image
5.
6. recognizer = cv2.face.LBPHFaceRecognizer_create()
7. path = 'dataset'
8. if not os.path.exists('./recognizer'):
9. os.makedirs('./recognizer')
10.
11. def getImagesWithID(path):
12. imagePaths = [os.path.join(path,f) for f in os.listdir(path)]
13. faces = []
14. IDs = []
15. for imagePath in imagePaths:
16. faceImg = Image.open(imagePath).convert('L')
17. faceNp = np.array(faceImg,'uint8')
18. ID = int(os.path.split(imagePath)[-1].split('.')[1])
19. faces.append(faceNp)
20. IDs.append(ID)
21. cv2.imshow("training",faceNp)
22. cv2.waitKey(10)
23. return np.array(IDs), faces
24.
25. Ids, faces = getImagesWithID(path)
26. recognizer.train(faces,Ids)
27. recognizer.save('recognizer/trainingData.yml')
28. cv2.destroyAllWindows()

26
Detector.py detector.py
1. import cv2 ‫משמשת לבדיקה (ריצת‬
2. import numpy as np
3. import sqlite3
‫המציגה‬ ‫ תוכנית‬- )‫מבחן‬
4. import os ‫סרטון ובו מלבן ירוק ושם‬
5. conn = sqlite3.connect('database.db') ‫מוצגים מסביב לפניו של כל‬
6. c = conn.cursor()
7. fname = "recognizer/trainingData.yml" ‫אדם הנראה בעדשת‬
8. if not os.path.isfile(fname): .‫המצלמה בזמן אמת‬
9. print("Please train the data first")
10. exit(0)
11. face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
12. cap = cv2.VideoCapture(0)
13. recognizer = cv2.face.LBPHFaceRecognizer_create()
14. recognizer.read(fname)
15. while True:
16. ret, img = cap.read()
17. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
18. faces = face_cascade.detectMultiScale(gray, 1.3, 5)
19. for (x,y,w,h) in faces:
20. cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),3)
21. ids,conf = recognizer.predict(gray[y:y+h,x:x+w])
22. c.execute("select name from users where id = (?);", (ids,))
23. result = c.fetchall()
24. name = result[0][0]
25. if conf < 50:
26. cv2.putText(img, name, (x+2,y+h-
5), cv2.FONT_HERSHEY_SIMPLEX, 1, (150,255,0),2)
27. else:
28. cv2.putText(img, 'No Match', (x+2,y+h-
5), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255),2)
29. cv2.imshow('Face Recognizer',img)
30. k = cv2.waitKey(30) & 0xff
31. if k == 27:
32. break
33.
34. cap.release()
35. cv2.destroyAllWindows()

27
Short_detector.py short_detector.py

1. import cv2 ,‫הפעלת מערכת האזעקה‬


2. import numpy as np ‫זיהוי פרצופים ושליחת‬
3. import sqlite3
.‫הודעות גישה מתאימות‬
4. import os
5. import sys ,‫במקרה של זיהוי חיובי‬
6. from pynput.keyboard import Key, Controller ‫ התוכנית‬.‫התוכנית נסגרת‬
7. import time
8. from PIL import Image ‫הזו היא למעשה יישום‬
9. from termcolor import colored, cprint ‫מטרות הפרויקט כמערכת‬
10. .‫אבטחה אמיתית‬
11. #os.system("node-red start")
12. keyboard = Controller()
13. #warning_pic = Image.open("/home/pi/Pictures/accessdenied.jpg")
14. conn = sqlite3.connect('database.db')
15. c = conn.cursor()
16.
17. fname = "recognizer/trainingData.yml"
18. if not os.path.isfile(fname):
19. print(colored("Please train the data first", 'red'))
20. exit(0)
21.
22. face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
23. cap = cv2.VideoCapture(0)
24. recognizer = cv2.face.LBPHFaceRecognizer_create()
25. recognizer.read(fname)
26. count1=5
27. imgcount = 0
28. while True:
29. ret, img = cap.read()
30. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
31. faces = face_cascade.detectMultiScale(gray, 1.3, 5)
32. for (x,y,w,h) in faces:
33. cv2.rectangle(img,(x,y),(x+w,y+h),(0,255,0),3)
34. ids,conf = recognizer.predict(gray[y:y+h,x:x+w])
35. c.execute("select name from users where id = (?);", (ids,))
36. result = c.fetchall()
37. name = result[0][0]
38. if conf < 50:
39. count1=count1+30
40. if count1>19:
41. os.system("clear")
42. print(colored('[ ACCESS GRANTED ]', 'green'))
43. print(' Hello '+name)
44. count1=0
45. keyboard.press(Key.esc)
46. keyboard.release(Key.esc)
47. cv2.putText(img, name, (x+2,y+h-
5), cv2.FONT_HERSHEY_SIMPLEX, 1, (150,255,0),2)
48.
49. else:
50. count1=count1-1
51. if count1<-7:
52. print(colored('[ ACCESS DENIED ]', 'red'))
53. cv2.imwrite("Alarm_%d.jpg" % imgcount, img)
54. count1=5
55. imgcount = imgcount+0 #change for creating multiple files

28
56. cv2.putText(img, '?', (x+2,y+h-
5), cv2.FONT_HERSHEY_SIMPLEX, 1, (0,0,255),2)
57. cv2.imshow('Face Recognizer',img)
58. k = cv2.waitKey(30) & 0xff
59. if k == 27:
60. break
61.
62. cap.release()
63. cv2.destroyAllWindows()

29
NODE-RED

:‫ייצוא של הקוד המיוצג על ידי התרשים הנ"ל‬


1. [
2. {
3. "id": "4edba4fe.18885c",
4. "type": "tab",
5. "label": "Analyze + Alert",
6. "disabled": false,
7. "info": ""
8. },
9. {
10. "id": "eaf140f0.9f05f",
11. "type": "comment",
12. "z": "4edba4fe.18885c",
13. "name": "Watson Credentials",
14. "info": "HYK_cL801Dfk9xEeTY8-aVuAbWN55hAq7puQhgqFBgXx",
15. "x": 150,
16. "y": 400,
17. "wires": []
18. },
19. {
20. "id": "13aede75.c15582",
21. "type": "switch",
22. "z": "4edba4fe.18885c",
23. "name": "Not Null",
24. "property": "result.images[0].faces[0]",

30
25. "propertyType": "msg",
26. "rules": [
27. {
28. "t": "null"
29. },
30. {
31. "t": "nnull"
32. }
33. ],
34. "checkall": "true",
35. "repair": false,
36. "outputs": 2,
37. "x": 340,
38. "y": 360,
39. "wires": [
40. [
41. "8cd777ab.368c68",
42. "22fb8571.82cf0a"
43. ],
44. [
45. "954bfdbe.4cd3f"
46. ]
47. ]
48. },
49. {
50. "id": "bf059eb3.74679",
51. "type": "template",
52. "z": "4edba4fe.18885c",
53. "name": "Person SMS",
54. "field": "payload",
55. "fieldType": "msg",
56. "format": "handlebars",
57. "syntax": "mustache",
58. "template": "[Unknown Person Detected]",
59. "x": 790,
60. "y": 440,
61. "wires": [
62. [
63. "9b138f58.6d46b"
64. ]
65. ]
66. },
67. {
68. "id": "56b3daa3.a03f04",
69. "type": "template",
70. "z": "4edba4fe.18885c",
71. "name": "No Face SMS",
72. "field": "payload",
73. "fieldType": "msg",
74. "format": "handlebars",
75. "syntax": "mustache",
76. "template": "[Unspecified Detection Alert]",
77. "x": 780,
78. "y": 500,
79. "wires": [
80. [
81. "9b138f58.6d46b"
82. ]
83. ]
84. },
85. {

31
86. "id": "8cd777ab.368c68",
87. "type": "template",
88. "z": "4edba4fe.18885c",
89. "name": "Error SMS",
90. "field": "payload",
91. "fieldType": "msg",
92. "format": "handlebars",
93. "syntax": "mustache",
94. "template": "Error Message: Watson is having trouble right now.",
95. "x": 790,
96. "y": 320,
97. "wires": [
98. [
99. "9b138f58.6d46b"
100. ]
101. ]
102. },
103. {
104. "id": "9b752ef5.9da57",
105. "type": "e-mail",
106. "z": "4edba4fe.18885c",
107. "server": "smtp.gmail.com",
108. "port": "465",
109. "secure": true,
110. "name": "yuval.yoran@gmail.com",
111. "dname": "Send Email",
112. "x": 1190,
113. "y": 460,
114. "wires": []
115. },
116. {
117. "id": "57028a72.3cf274",
118. "type": "change",
119. "z": "4edba4fe.18885c",
120. "name": "Person Mail",
121. "rules": [
122. {
123. "t": "set",
124. "p": "attachments",
125. "pt": "msg",
126. "to": "[{\t \"filename\": msg.file, \t \"path\": m
sg.filename,\t \"content\": $$.payload\t}]",
127. "tot": "jsonata"
128. },
129. {
130. "t": "set",
131. "p": "payload",
132. "pt": "msg",
133. "to": "<br><br>Dear Yuval,<br><br>An unknown person has
been detected by the system!<br>A snapshot of them is attached below:<br><br>",

134. "tot": "str"


135. },
136. {
137. "t": "set",
138. "p": "topic",
139. "pt": "msg",
140. "to": "[Unknown Person Detected]",
141. "tot": "str"
142. }
143. ],

32
144. "action": "",
145. "property": "",
146. "from": "",
147. "to": "",
148. "reg": false,
149. "x": 790,
150. "y": 460,
151. "wires": [
152. [
153. "9b752ef5.9da57"
154. ]
155. ]
156. },
157. {
158. "id": "56c6be39.03b6b",
159. "type": "change",
160. "z": "4edba4fe.18885c",
161. "name": "People Mail",
162. "rules": [
163. {
164. "t": "set",
165. "p": "attachments",
166. "pt": "msg",
167. "to": "[{\t \"filename\": msg.file, \t \"path\": m
sg.filename,\t \"content\": $$.payload\t}]",
168. "tot": "jsonata"
169. },
170. {
171. "t": "set",
172. "p": "payload",
173. "pt": "msg",
174. "to": "<br><br>Dear Yuval,<br><br>Some unknown people ha
ve been detected by the system!<br>A snapshot of them is attached below:<br><br>
",
175. "tot": "str"
176. },
177. {
178. "t": "set",
179. "p": "topic",
180. "pt": "msg",
181. "to": "[Unknown People Detected] ",
182. "tot": "str"
183. }
184. ],
185. "action": "",
186. "property": "",
187. "from": "",
188. "to": "",
189. "reg": false,
190. "x": 790,
191. "y": 400,
192. "wires": [
193. [
194. "9b752ef5.9da57"
195. ]
196. ]
197. },
198. {
199. "id": "5059d8e0.a7f788",
200. "type": "change",
201. "z": "4edba4fe.18885c",

33
202. "name": "No Face Mail",
203. "rules": [
204. {
205. "t": "set",
206. "p": "attachments",
207. "pt": "msg",
208. "to": "[{\t \"filename\": msg.file, \t \"path\": m
sg.filename,\t \"content\": $$.payload\t}]",
209. "tot": "jsonata"
210. },
211. {
212. "t": "set",
213. "p": "payload",
214. "pt": "msg",
215. "to": "Something was detected by the system, but unfortu
nately no faces were found.",
216. "tot": "str"
217. },
218. {
219. "t": "set",
220. "p": "topic",
221. "pt": "msg",
222. "to": "[Unspecified Detection Alert]",
223. "tot": "str"
224. }
225. ],
226. "action": "",
227. "property": "",
228. "from": "",
229. "to": "",
230. "reg": false,
231. "x": 780,
232. "y": 520,
233. "wires": [
234. [
235. "9b752ef5.9da57"
236. ]
237. ]
238. },
239. {
240. "id": "22fb8571.82cf0a",
241. "type": "change",
242. "z": "4edba4fe.18885c",
243. "name": "Error Mail",
244. "rules": [
245. {
246. "t": "set",
247. "p": "payload",
248. "pt": "msg",
249. "to": "Error Message: Watson is having trouble right now
.",
250. "tot": "str"
251. }
252. ],
253. "action": "",
254. "property": "",
255. "from": "",
256. "to": "",
257. "reg": false,
258. "x": 800,
259. "y": 340,

34
260. "wires": [
261. [
262. "9b752ef5.9da57"
263. ]
264. ]
265. },
266. {
267. "id": "6c682d3a.21ceb4",
268. "type": "comment",
269. "z": "4edba4fe.18885c",
270. "name": "Twilio Credentials",
271. "info": "Account SID:\n\nAC0904b04abd5d2551b3196a92603aa88e\n\n\
nFrom (my number):\n\n+18144144350\n\n\n\nToken:\n\nfc2f748a8667d9cd2ec424f8239a
9c1c\n",
272. "x": 1210,
273. "y": 380,
274. "wires": []
275. },
276. {
277. "id": "f134c75.dc42e38",
278. "type": "template",
279. "z": "4edba4fe.18885c",
280. "name": "People SMS",
281. "field": "payload",
282. "fieldType": "msg",
283. "format": "handlebars",
284. "syntax": "mustache",
285. "template": "[Unknown People Detected]",
286. "x": 790,
287. "y": 380,
288. "wires": [
289. [
290. "9b138f58.6d46b"
291. ]
292. ]
293. },
294. {
295. "id": "e675e7ab.51daa8",
296. "type": "delay",
297. "z": "4edba4fe.18885c",
298. "name": "5 s",
299. "pauseType": "delay",
300. "timeout": "5",
301. "timeoutUnits": "seconds",
302. "rate": "1",
303. "nbRateUnits": "1",
304. "rateUnits": "second",
305. "randomFirst": "1",
306. "randomLast": "5",
307. "randomUnits": "seconds",
308. "drop": false,
309. "x": 590,
310. "y": 180,
311. "wires": [
312. [
313. "b4f8bbc5.93fbd8"
314. ]
315. ]
316. },
317. {
318. "id": "b4f8bbc5.93fbd8",

35
319. "type": "file in",
320. "z": "4edba4fe.18885c",
321. "name": "Pull File",
322. "filename": "/home/pi/Desktop/opencv_face_recognition-
master/Alarm_0.jpg",
323. "format": "",
324. "chunk": false,
325. "sendError": false,
326. "x": 780,
327. "y": 180,
328. "wires": [
329. [
330. "553592c0.80e7cc"
331. ]
332. ]
333. },
334. {
335. "id": "9b138f58.6d46b",
336. "type": "twilio out",
337. "z": "4edba4fe.18885c",
338. "service": "_ext_",
339. "twilio": "15a7bab2.ecdf85",
340. "from": "",
341. "number": "+972508564907",
342. "name": "Send SMS",
343. "x": 1190,
344. "y": 340,
345. "wires": []
346. },
347. {
348. "id": "af837b61.418dd8",
349. "type": "watch",
350. "z": "4edba4fe.18885c",
351. "name": "Check For Changes",
352. "files": "/home/pi/Desktop/opencv_face_recognition-
master/Alarm_0.jpg",
353. "recursive": "",
354. "x": 200,
355. "y": 180,
356. "wires": [
357. [
358. "a0a0d926.8bde18"
359. ]
360. ]
361. },
362. {
363. "id": "a0a0d926.8bde18",
364. "type": "deduplicate",
365. "z": "4edba4fe.18885c",
366. "name": "1/30sec",
367. "keyproperty": "",
368. "expiry": "30",
369. "x": 420,
370. "y": 180,
371. "wires": [
372. [
373. "e675e7ab.51daa8"
374. ],
375. []
376. ]
377. },

36
378. {
379. "id": "553592c0.80e7cc",
380. "type": "visual-recognition-v3",
381. "z": "4edba4fe.18885c",
382. "name": "How Many Faces",
383. "vr-service-
endpoint": "https://gateway.watsonplatform.net/visual-recognition/api",
384. "image-feature": "detectFaces",
385. "lang": "en",
386. "x": 150,
387. "y": 360,
388. "wires": [
389. [
390. "13aede75.c15582",
391. "a87608ee.ce97d8"
392. ]
393. ]
394. },
395. {
396. "id": "954bfdbe.4cd3f",
397. "type": "switch",
398. "z": "4edba4fe.18885c",
399. "name": "Message Sort",
400. "property": "result.images[0].faces.length",
401. "propertyType": "msg",
402. "rules": [
403. {
404. "t": "gt",
405. "v": "1",
406. "vt": "num"
407. },
408. {
409. "t": "eq",
410. "v": "1",
411. "vt": "str"
412. },
413. {
414. "t": "else"
415. }
416. ],
417. "checkall": "true",
418. "repair": false,
419. "outputs": 3,
420. "x": 540,
421. "y": 420,
422. "wires": [
423. [
424. "f134c75.dc42e38",
425. "56c6be39.03b6b"
426. ],
427. [
428. "bf059eb3.74679",
429. "57028a72.3cf274"
430. ],
431. [
432. "56b3daa3.a03f04",
433. "5059d8e0.a7f788"
434. ]
435. ]
436. },
437. {

37
438. "id": "a87608ee.ce97d8",
439. "type": "debug",
440. "z": "4edba4fe.18885c",
441. "name": "",
442. "active": true,
443. "tosidebar": true,
444. "console": false,
445. "tostatus": false,
446. "complete": "true",
447. "x": 320,
448. "y": 540,
449. "wires": []
450. },
451. {
452. "id": "54df21e7.ca3ad",
453. "type": "comment",
454. "z": "4edba4fe.18885c",
455. "name": "Twilio Credentials 2",
456. "info": "Account SID:\n\nAC7b33e01fde98620addbe976232934773\n\n\
nFrom (my number):\n\n+19494611969\n\n\n\nToken:\n\nb198f115e850303ac89ecba50691
6a97",
457. "x": 1210,
458. "y": 400,
459. "wires": []
460. },
461. {
462. "id": "15a7bab2.ecdf85",
463. "type": "twilio-api",
464. "z": "",
465. "sid": "AC7b33e01fde98620addbe976232934773",
466. "from": "+19494611969",
467. "name": "MyTwilio 2.0"
468. }
469. ]

38

You might also like