עם רספבריי פיי, מצלמה ופייתון למדתי שדגים מתנהגים קצת כמו הייטקיסטים

אלכסנדר שרשבסקי, ML Architect, השתתף בהאקתון של החברה, ובעזרת מצלמה וקצת ML חזר עם תובנות על הדגים הארגוניים. כך הוא עשה זאת

מאת: אלכסנדר שרשבסקי

לפני כשנה, כשהתחלתי את העבודה הנוכחית שלי, גיליתי שלמנהל שלי, עירא, יש תפקיד נוסף מלבד היותו Chief Data Scientist. ניתן להגדיר תפקיד זה כ-VP Fish Care. כן, מתברר שבחברה שלנו ממש אוהבים דגים. בכל משרדי החברה בעולם ניצבים אקווריומים, כשהיפה ביותר ביניהם הוא זה שבסייט הישראלי. משתמשים עבורו בערכות ניטור משוכללות הבודקות בכל עת נתונים קריטיים כטמפרטורה ומוליכות מים, הכל לרווחתם של בעלי הקשקשים החיים בו. עירא, מצידו, מקפיד להאכיל את הדגים מדי בוקר עם הגיעו למשרד, עוד לפני שהוא מניח את התיק ובודק מיילים.

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

הסטאפ שבניתי

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

לקסם הבא נצטרך רספברי פיי, מצלמה וכמה שורות בפייתון

כדי לתעד את הדגים הצבתי מול האקווריום מחשב Raspberry Pi המקושר לאינטרנט, ושאליו מחוברת מצלמה. מכיוון שמדובר במחשב קטן וחלש יחסית לא יכולתי להשתולל ולהריץ רשתות נוירונים ושאר כלים הדורשים כוח חישוב משמעותי. במקום זה השתמשתי ביכולת Codec וידאו חכם המבצע דחיסה מובנית ומכווץ את הדאטה, כך שאינו תופס מקום רב מדי. הדרך בה המחשב עושה זאת היא לקיחת מעין Snapshot, תמונת מצב, ולאחר מכן בדיקה שוטפת של מה שמשתנה בה. במידה ושום דבר משמעותי לא השתנה ה-Codec יודע שאין צורך לשמור שוב את כל התמונה אלא רק את הדלתא. בתכונה הזאת השתמשתי כדי לכתוב תוכנה קטנה ב-Python, שמתשאלת את המצלמה, ומחשבת את התנועתיות הממוצעת. מתוך ההבנה שאני יכול לבצע שאילתה על דלתאות שכאלו בכל זמן שאגדיר וכך להפוך את המידע למטריקה עם ה-Rollup הרצוי. את המטריקה ניתן להזין למערכת שפיתחנו בחברה, שתבנה ממנה Baseline, תזהה מחזוריות בתנועה ותציג קשרים וקורלציות.

לא רק אתם עייפים אחרי ארוחת הצהריים

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

#!/usr/bin/env python3

import time
import numpy as np
import pandas as pd
import picamera
import picamera.array
import logging

TOKEN = '***'
CUSTOMER_ID = '***'
env = 'app-poc.anodot.com'

from common.anodot_api.anodotd_client import Client

logger = logging.getLogger(__name__)

client = Client(endpoint=f'{env}', scheme='https', v1_token=TOKEN)


class PiMotion:

    def __init__(self, verbose=False, post_capture_callback=None):
        self.working = False
        self.verbose = verbose
        self.post_capture_callback = post_capture_callback
        self.detected = False

    def motion_detected(self):
        if not self.working:
            self.detected = True

    def start(self):
        with picamera.PiCamera(resolution='VGA') as camera:
            camera.resolution = (1280, 960)
            camera.framerate = 10

            handler = CaptureHandler(camera, self.post_capture_callback)

            # warmup
            time.sleep(2)

            try:
                # Start recording, sending the output to the handler
                camera.start_recording('/dev/null', format='h264', motion_output=MotionDetector(camera, handler))

                while True:
                    handler.tick()
                    time.sleep(1)

            except Exception as e:
                logger.error(e)

            finally:
                camera.stop_recording()
                logger.debug('Stopped recording')


class MotionDetector(picamera.array.PiMotionAnalysis):

    def __init__(self, camera, handler):
        super(MotionDetector, self).__init__(camera)
        self.handler = handler
        self.first = True
        self.res = []

    def analyse(self, matrix):
        ts = int(time.time())
        if ts % 60 == 0:
            try:
                r = np.array(self.res)
                client.send_metric(pd.Series([r.mean()], [ts]),  "what=fish_movement_mean")
                client.send_metric(pd.Series([r.min()], [ts]),  "what=fish_movement_min")
                client.send_metric(pd.Series([r.max()], [ts]),  "what=fish_movement_max")
                client.send_metric(pd.Series([r.std()], [ts]),  "what=fish_movement_std")
            except Exception as e:
                print(e)
            self.res = []
        matrix = np.sqrt(
            np.square(matrix['x'].astype(np.float)) +
            np.square(matrix['y'].astype(np.float))
        ).clip(0, 255).astype(np.uint8)
        self.res.append(int(matrix.sum()))


class CaptureHandler:
    def __init__(self, camera, post_capture_callback=None):
        self.camera = camera
        self.callback = post_capture_callback
        self.detected = False
        self.working = False
        self.i = 0

    def motion_detected(self):
        if not self.working:
            self.detected = True

    def tick(self):
        if self.detected:
            self.working = True
            self.detected = False
            self.i += 1
            self.working = False


if __name__ == '__main__':

    p = PiMotion()
    p.start()
הסקריפט לזיהוי התנועה בפייתון - סך הכל כמאה שורות קוד

כמובן שאפשר לפתור את זיהוי התנועה בעזרת OpenCV או לעשות סגמנטציה עם רשתות, תוך שימוש ב-TensorFlow או PyTorch – בצורה כזאת אפשר לזהות את הדמות ולבדוק את התזוזה שלה פריים אחרי פריים. אבל השיטה הזאת דרשה הרבה יותר חישובים, וכיוון שהזיהוי רץ על מחשב קטן מאוד (בעל יכולת חישוב מוגבלת), אפילו לא ניסיתי ללכת בכיוון הזה. בכל מקרה, החבילות שהשתמשתי בהן היו NumPy לחישוב סטטיסטיקה על התנועה, ועבודה עם המטריצה של דלתאות-התנועה, ו-picamera, חבילה של רספברי-פיי לעבודה עם מצלמה וקודק.

מה שעובד על דגים יכול גם על אנשים

אם כן, תוצאת פרויקט ההאקתון שלי הייתה ברורה: קיימת תבנית בהתנהגותם של הדגים, תבנית אותה ניתן ללמוד. המערכת שלנו יכולה לזהות חריגה ממנה ואנומליות, וכפי שהיא יודעת לזהות שהתנועה של דגים עולה לפתע ב-80% ומכך להסיק שייתכן שקרה משהו ששווה לבדוק כך היא יכולה לזהות חריגות כאלו במקומות אחרים ובנסיבות אחרות. את ה-Set Up שבניתי מול האקווריום אפשר להרים גם במפעל כדי לנטר את התנהגות העובדים, או במועדון, כדי לפלח את התנהגות המבלים. כך, למשל, יכול בעל המועדון לגלות מהן השעות בהן יש צפיפות רבה בבר ולתגבר משמרות ברמנים בהתאם. למעשה, לכל מה שניתן לתרגם למטריקה רציפה ניתן גם לבנות תחזית התנהגות עתידית

ומה עם הדגים? המצלמה עדיין מתעדת אותם ושומרת את דלתאות התנועה כדי להגיע למסקנות נוספות. עירא, בתפקיד ה-HR, מקפיד להאכיל אותם מדי בוקר, אבל עכשיו כבר יש לו את המטריקה שמוכיחה שהם ממש מודים לו על כך.

הכותב הינו ML Architect בצוות Data Science של Anodot

 

כתב אורח

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

הגב

10 תגובות על "עם רספבריי פיי, מצלמה ופייתון למדתי שדגים מתנהגים קצת כמו הייטקיסטים"

avatar
Photo and Image Files
 
 
 
Audio and Video Files
 
 
 
Other File Types
 
 
 

* היי, אנחנו אוהבים תגובות!
תיקונים, תגובות קוטלות וכמובן תגובות מפרגנות - בכיף.
חופש הביטוי הוא ערך עליון, אבל לא נוכל להשלים עם תגובות שכוללות הסתה, הוצאת דיבה, תגובות שכוללות מידע המפר את תנאי השימוש של Geektime, תגובות שחורגות מהטעם הטוב ותגובות שהן בניגוד לדין. תגובות כאלו יימחקו מייד.

סידור לפי:   חדש | ישן | הכי מדורגים
עוז
Guest

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

aaaa
Guest

כתבה חמודה ודגים מקסימים!
אבל מה עם Typing??? לא היה עובר CR אצלנו

איתי
Guest

כבר אין כתבות אינפורמטיביות. הכל כולל הכל זה תוכן פרסומי לאדם או לחברה או למוצר. גם תוכן משולם וזה נמאס.

דןדן
Guest

לא מבין את התגובות השליליות, יש פה פרוייקט חביב, שיתוף מידע ודרך חשיבה, עוד כתבות כאלה אני ממש אשמח תודה

קאטו
Guest
המודל הכלכלי של האתר, ככל שיש כזה, לקחת מתכנת מחברה מסוימת, ולהציג רק את הפתרון של החברה לבעיה ספציפית, כשיש עוד חלופות(חברות אחרות)הוא אינו נכון לאתר. האתר חייב להיות נטול באייאס(דעות קדומות) או תוכן שיווקי סמוי. כי יש המון חלופות ופתרונות להמון בעיות. וזה גורם לחוסר אמון. רוצים להציג תוכן עמוק ומקצועי. או שתעשו את זה באופן חכם יותר או שלכל פתרון טכנולוגי שאתם מציגים, תציגו את החברות המתחרות כדי שיהיה איזון מצד אחד ולא ניסיון לשדל לרכוש שירות או מוצר בינוניים. לעומת זאת. הכתבה מרתקת וניתוח הנתונים מעניין, אלכסנדר, מוצע לשלוח את המחקר לחקר הימי באילת. זה יתן להם… Read more »
סטארטאפיסט
Guest

ניחא אקווריום של צקלידים אבל העיצוב של המיכל חלש ביותר. תשקיעו בUI לפני שקופצים לML.

אני
Guest

רספברי פיי הוא מחשב חזק!

יונתן
Guest

אין כמו האקאתונים ואין כמו Anodot.

שרון
Guest

האם יש קשר בין הנתונים הנ"ל לזמנים גאות ושפל בים ?

אמיר
Guest

יכולת גם לאמן מודל חיצוני ו"רק" להריץ אותו בRP…

wpDiscuz

תגיות לכתבה: