Professional Documents
Culture Documents
ובינה מלאכותית
1
תוכן העניינים
1 שער
3 תקציר
16 רפלקציה
17 בבליוגרפיה
2
תקציר
בינה מלאכותית ,תחום שקיים כבר עשרות שנים אך תפס תאוצה אדירה בתעשייה ובענפים שונים
של תחום מדעי המחשב בשנים האחרונות .זיהוי פנים הוא נושא מרתק בתוך תחום הבינה
המלאכותית ,יש לו מגוון שימושים בחיי היומיום שלנו ולשימושיו פוטנציאל עצום בתחומים שונים,
החל מאבטחה וביטחון וכלה בפסיכולוגיה וברשתות חברתיות.
בפרויקט שלי בחרתי לרתום את זיהוי הפנים לצורך זיהוי פניהם וזהותם של אנשים מוכרים,
המורשים להיכנס למבנה ,בית או חדר כלשהם – עבורם תנוטרל מערכת אזעקה .אם המבקשים
להיכנס אינם מוכרים ,תישלח תמונתם לכתובת מייל מוגדרת מראש והודעה מתאימה (המשתנה
בהתאם לכמות האנשים שהמערכת מזהה) תישלח לטלפון הנייד של בעל המקום ,היות שהם אנשים
זרים המנסים להיכנס למקום פרטי.
בהרחבה לגבי תחום הבינה המלאכותית ,אני מתעניין בעיקר בתחום עיבוד התמונה וזיהוי הפנים.
באמצעות זיהוי תמונה ע"י שימוש בבינה מלאכותית ניתן לזהות חפצים ,צמחים ,פירות ,מכוניות,
תמרורים ,כתובות ועוד מגוון עצמים שונים מתחומים רבים .בעיני הדבר המעניין ביותר לזיהוי הוא
בני אדם ,בדגש על פני האדם והדרכים השונות להבדיל בין בני אדם שונים על ידי שימוש בתמונה
של פניהם .לכן בחרתי לפנות לתחום מערכות האבטחה.
בעיה המתעוררת פעמים רבות במערכות אבטחה ואזעקה ביתיות וציבוריות היא בעיית אזעקות
השווא.
תשאלתי חברים וגיליתי שאנשים רבים נתקלים באזעקות שווא במערכת האזעקה הביתית שלהם,
בין אם שכחו לנטרל אותה כשנכנסו לביתם או שרוח הסיטה ווילון לתוך שדה הראייה של אחד
מחיישני התנועה .הסיבה לכך היא שמערכות אבטחה כיום הן מיושנות – הן סומכות על גלאי תנועה
פשוטים על מנת להניח שהאדם הנכנס הוא פורץ ,כל זאת בהנחה שהתנועה שעוררה את הגלאים
נעשתה על ידי אדם .במקרים רבים וילון או החתול הביתי עלולים להפעיל את האזעקה וכך לגרום
לאזעקות שווא.
3
הפרויקט שלי פותר את הבעיות שציינתי בכך שהוא מזהה אם בתמונות שבמצלמת האבטחה קיימים
בני אדם או לא .אם בתמונה יש בני אדם תווי פניהם יוצלבו עם תמונות האנשים המורשים שבמאגר
ובמידה ותימצא התאמה -תנוטרל האזעקה.
שירות הבינה המלאכותית המזהה כמה אנשים נמצאים בתמונה נעשה בסביבת ,זה מאפשר חיסכון
בהיקף הזיכרון הדרוש לחומרה ,כך אני מסוגל להריץ את הפרוייקט ממחשב זעיר .שליחת ההודעות
וההתרעות נעשית בסביבת "נוד-רד".
שירות זיהוי הפנים והצלבתם עם מאגר תווי הפנים דורש תוכניות שיקבעו מה יקרה עם הקלט
מהמצלמה וינהלו את מאגר הנתונים .לצורך כך נעשה שימוש בספרייה בסביבת לינוקס המסייעת
בטיפול בתווי הפנים בשם .OpenCV
כיום קיימות תוכנות רבות המשתמשות בזיהוי פנים ,אולם ,רק חלק קטן מהן מבצע זיהוי ממשי ,יש
לשים לב להבדל שבין איתור פרצוף בתוך תמונה ( )Detectionובין זיהוי של אדם מסויים
שפניו מופיעות בתמונה ( . )Recognitionהפרוייקט שלי מסוגל להבדיל בין פרצופים שונים
ובכך לזהות את זהותו של אדם ( ,)Recognitionכך אני בודק האם האדם מורשה להיכנס או לא,
על ידי הצלבה עם הפרצופים שבמאגר הפנים .אם האדם אינו מזוהה על ידי המערכת ,תמונתו
נשלחת לענן ומספר הפרצופים בה נספר על ידי בינה מלאכותית בשם Watsonהמבצעת איתור
מטרות העבודה
קליטת פנים -צילום סדרת תמונות של אדם מסוים ,קטלוגן במאגר ושיוכן לזהותו של האדם.
זיהוי פנים בזמן אמת – כאשר עומדים מול המצלמה ,בזמן אמת מוצג וידאו ובו מלבנים ירוקים
מסמנים את כל הפרצופים שבתמונה ,תוך הצגת שמות האנשים המזוהים.
התראה מפני פולשים – זיהוי מצבים בהם עומדים אנשים לא מוכרים מול המצלמה ,שמירת
תמונה של האירוע ושליחתה במייל לכתובת המייל ,בצירוף SMSוהודעה מתאימים.
4
בעיה אלגוריתמית מספר 1
הבעיה הראשונה המתעוררת היא הבחירה באלגוריתם בו נעשה זיהוי הפנים ואימון הבינה המלאכותית
(למידת מכונה) .ישנו מספר רחב של אלגוריתמים המסייעים בזיהוי אדם לפי פניו ובשמירת פרטיהם של
אנשים שונים במאגר נתונים .האתגר הראשון הוא להבין איך ניתן לזהות פנים ומלבחור את השיטה שהכי
נוחה למימוש מטרות הפרויקט.
רבים הנחשפים לתחום זיהוי הפנים רואים בשיטת הזיהוי הביומטרי והלמידה העמוקה כבחירה
הטריוויאלית לצורך פיענוח זהותו של אדם ,באמצעות המרחקים בין העיניים ,גובה המצח ,האף ,השפתיים
ושאר הפרטים המרכיבים את הפנים שלנו ,זאת משום שאנחנו כבני אדם מזהים את מכרינו בדרך זו ,לפי
מאפייני הפנים שלהם ,התמונה להלן מהווה אילוסטרציה:
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בגלל הדיליי בקליטה.
ניתן להוסיף דיליי ( )Delayבין זיהוי הפנים ובין רגע שליחת הודעת הגישה .בעצם ,לאחר שזוהו פנים ,בין
אם כפנים של אדם מורשה ובין אם לא ,המערכת תחכה מספר שניות עד שתיתן כל התראה .השיטה הזו לא
טובה בעיני מכיוון שכאשר אדם מבקש להיכנס לביתו או לחדר מסויים ,הוא רוצה לעשות זאת באופן מיידי
9
ובלי עיכובים .דיליי של 5שניות עשוי להיות משמעותי בחוויית המשתמש ואני מעדיף לבחור בפתרון שבו
הודעות הגישה יגיעו מהר יותר.
10
הפתרון שלי לבעיה אלגוריתמית מספר 2
את הבעיה פתרתי באמצעות משתנה סוכם . int count1המשתנה גדל בכל פעם שמישהו מזוהה נקלט
במצלמה ,המשתנה יורד בכל פעם שמישהו לא מזוהה נקלט במצלמה.
הודעות הגישה ( ACCESS DENIEDו )ACCESS GRANTED-נשלחות רק כאשר המשתנה הסוכם עובר
מספר מסויים וכך בעצם נדרש מספר מסויים של פריימים רצופים שבהם ייקלט אדם מזוהה או לא מזוהה על
מנת לאפשר גישה או למנוע אותה .זו בעצם רשת בטחון המאפשרת לצמצם משמעותית את שגיאות המערכת
על ידי הקטנת אחוז הטעות מ( 0.0062-אזכיר כי אחוז הדיוק של רשת הנוירונים הוא ,99.38%מכאן
אחוז השגיאה הוא )0.62%ל 0.0062-בחזקת מספר הפריימים בהם נדרש זיהוי על מנת שהמשתנה הסוכם
יעבור את הרף שהצבתי.
הפתרון לבעיה אלגוריתמית 2איננו מושלם ובעקבותיו נחשפה בעיה אלגוריתמית נוספת:
כעת ,עבור קליטת פנים מזוהות count1עולה ועבור קליטת פנים בלתי מזוהות count1יורד ,אולם,
עלולה להתעורר בעיה כאשר מגיע אדם מזוהה בליווי אדם שאינו מזוהה; חבר ,שותף ,קרוב משפחה רחוק
או כל אורח אחר .במקרה כזה ,יקלטו פנים מזוהות ויעלו את הסוכם ובו בזמן יקלטו גם פנים בלתי מזוהות
ויורידו את הסוכם בחזרה .במקרה שכזה ,המערכת לא תציג שום הודעה מאחר שהסוכם לא יעלה ולא ירד
מנקודת שיווי המשקל שבה הוא נמצא.
ניתן לקבוע כי ברגע שבו יקלטו פנים מזוהות ,תינתן הודעת גישה חיובית " ,"ACCESS GRANTEDאולם,
כאשר אדם עובר ליד ביתו מבלי כוונה להיכנס ,או בעת שהוא יוצא מן הבית (לעבודה או לקניות) פניו
עלולים להיקלט לשבריר שנייה בעדשת המצלמה .מתן גישה באופן מיידי עלולה להוביל לנטרול לא מכוון
של מערכת האזעקה .לכן יש למצוא פתרון שבו עדיין מוכרחים להביע כוונה להיכנס על ידי חשיפת הפנים
לאורך מספר פריימים.
11
הפתרון שלי לבעיה אלגוריתמית מספר 3
הפתרון שמצאתי הוא פשוט למדי .פשוט שיניתי את הקוד כך שבעת מציאת פנים מזוהות הסוכם יגדל בסכום
גדול ובעת גילוי פנים בלתי מזוהות הסוכם יגדל בסכום קטן ,כך שלא יהיה גדול מספיק בשביל לבטל את
השפעת הפנים המזוהות על הסוכם ,אך גדול מספיק בשביל לרדת מתחת לרף התחתון ולספק התראה
במהירות האפשרית בעת מפגש עם אדם לא מזוהה בלבד.
לאחר השינוי הזה מערכת הודעות הגישה פעלה כראוי ,זיהתה אנשים מורשים והעניקה להם הודעת
ACCESS GRANTEDולאנשים בלתי מזוהים העניקה הודעת .ACCESS DENIEDבנוסף ,כאשר עומד
אדם מוכר יחד עם אדם לא מוכר ,המערכת תעניק להם גישה.
12
תיאור המודולים של מערכת התוכנה
Run_Project.py
תפריט השליטה והניווט בין חלקי הפרויקט ,באמצעות הטרמינל ניתן לגשת לכל אחת מהתוכניות העיקריות של הפרויקט.
זוהי למעשה תוכנית שבאמצעותה ניתן לפתוח ולהשתמש בשאר התוכניות .התוכנית מכילה תפריט ומאפשרת פתיחה של
התוכניות האחרות באמצעות קלטים שונים ,תוך מתן עדכוני מצב המסייעים ומקלים את חווית המשתמש.
13
אני משתמש גם במסד נתונים בשם database.dbהמסד מכיל את פרטי המשתמשים בטבלה:
– 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אפשרויות:
הבחירה באחת מן האפשרויות נעשית על ידי הקלדת האות האנגלית המתאימה לבחירת המשתמש (,D ,T ,R
– )X ,Sזה נעשה בתוך התוכנית .Run_Project.py
לאחר הבחירה באפשרות זו ,יש לכתוב את שם האדם שפניו מצולמים וללחוץ על . Enter
לאחר מכן ,יצולמו 50תמונות של פניו וישמרו תחת השם שהוקלד .לאחר ביצוע שלב זה יש לבחור
באפשרות Train Dataעל מנת שהשינויים ישמרו ויאומנו על ידי המערכת.
בחירה באפשרות זו תרוץ בין כל התמונות שבמערכת ו"תלמד" את הבינה המלאכותית .אין צורך בפעילות
נוספת.
תוכנית זו תדגים את פעילות המערכת מבלי לשלוח התראות ומבלי לסגור את התוכנית .על מנת לצאת ממנה
יש ללחוץ על מקש ה.Esc-
17
S )4התחל זיהוי – Start Detector
תוכנית זו תפעיל את מערכת האבטחה במצב אמת ,תתריע מפני פולשים ותיסגר במקרה של זיהוי אדם
מורשה .על מנת לצאת ממנה ללא זיהוי אדם מורשה יש ללחוץ על .Esc
תוכנית בדיקת הזיהוי בפעולה: כתיבת שם האדם המצולם בתוכנית הקלטת הפנים:
רפלקציה
למדתי הרבה מאוד במהלך פיתוח הפרויקט .דרך סרטוני הדרכה וחוברות אינטרנטיות שונות למדתי את העקרונות
שהנחו אותי ביצירת הפרויקט הזה .אני מרוצה מהתוצאה של העבודה הקשה שעשיתי לאורך השנה ואני מאוד גאה
בפרויקט שלי.
18
התהליך שעברתי הוא משמעותי מכיוון שבתחילת שלב המחקר ,הידע שלי הסתכם בידע הנדרש לבגרות במדעי
המחשב ,לעומת זאת ,היום אני יודע לתכנת בשפות שלא ידעתי לפני כן ,יש לי ידע רחב בנושאים מעניינים כמו עיבוד
תמונה ,זיהוי פנים ,למידת תכונה ,בינה מלאכותית ועוד.
)1מחקר – שלב צבירת המידע ,הידע וההתמצאות בתחום .בשלב זה חיפשתי ברחבי הרשת אנשים שעשו פרויקטים
דומים לשלי ,על מנת ללמוד מה היו הקשיים שלהם ,מה עובד טוב יותר ופחות ,לצורך תכנון נכון וביצוע מדויק של
הפרויקט שלי .בשלב זה למדתי באילו רכיבי חומרה כדאי לי להשתמש.
)2פיתוח – אחרי שאספתי אץ המידע הנחוץ שכלל ידע בסיסי בפייתון ,מדריכים ,סרטונים וכתבות בנושא זיהוי פנים;
ואת החומרה הדרושה שכללה ראספברי פיי ,מצלמה ,מקלדת ועכבר; התחלתי את כתיבת התוכניות השונות שמרכיבות
את ספריית הפרוייקט .נעזרתי רבות בכתבות ומדריכים והתאמתי מספר תוכניות לצרכים של הפרוייקט שלי.
)3שיפור – לאחר שהמערכת הייתה קיימת ועבדה כהלכה התחלתי את שלב השיפור .שלב זה כלל את כתיבת תוכנית
התפריט וממשק המשתמש ,ייעול של התוכניות ומתן מענה לבעיות אלגוריתמיות שונות.
החלוקה הזו עזרה לי מאוד ואני ממליץ לכל תלמידי התוכנית בעתיד לעבוד בצורה זו.
אני שמח מאוד שבחרתי לקחת חלק בתוכנית והעובדה שפיתחתי פרוייקט גמור היא מקור לגאווה עבורי שילווה אותי
גם בהמשך החיים ובפיתוח הקריירה שלי.
19
בבליוגרפיה
:רשימת סרטונים
:רשימת כתבות
:רשימת אתרים
)(אתרים שעוסקים או שיש בהם קהילות שעוסקות בזיהוי פנים באמצעות ראספברי פיי
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
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
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>",
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