פילוח מופעים עם YOLOv7 ב-Python PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

פילוח מופעים עם YOLOv7 ב- Python

מבוא

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

פילוח סמנטי מסווג את כל הפיקסלים בתמונה שלהם סמנטי תווית (מכונית, מדרכה, בניין). פילוח מופעים מסווג כל הפיקסלים של כל אובייקט שזוהה בנפרד, ו Car1 הוא מובחן מ Car2.

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

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

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

במדריך הקצר הזה, נבצע פילוח מופעים ב-Python, עם YOLOv7 המתקדם.

YOLO ופילוח מופעים

YOLO (אתה מסתכל רק פעם אחת) היא מתודולוגיה, כמו גם משפחה של מודלים שנבנו לזיהוי אובייקטים. מאז היווסדה בשנת 2015, YOLOv1, YOLOv2 (YOLO9000) ו-YOLOv3 הוצעו על ידי אותם מחבר/ים - וקהילת הלמידה העמוקה המשיכה בהתקדמות בקוד פתוח בשנים הבאות.

YOLOv5 של Ultralytics הוא מאגר עצום, והיישום הראשון ברמת הייצור של YOLO ב-PyTorch, אשר זכה לשימוש משמעותי בתעשייה. היישום של PyTorch הפך אותו לנגיש יותר מאי פעם, מה שנעשה בדרך כלל ב-C++, אבל הסיבה העיקרית שהוא הפך להיות כל כך פופולרי היא בגלל ה-API הפשוט והחזק להפליא שנבנה סביבו, המאפשר לכל מי שיכול להריץ כמה שורות של Python קוד המסוגל לבנות גלאי אובייקטים.

YOLOv5 הפך למרכיב עיקרי עד כדי כך שרוב המאגרים שמטרתם לקדם את שיטת YOLO משתמשים בו כבסיס ומציעים API דומה שעבר בירושה מ-Ultralytics. YOLOR (אתה לומד רק ייצוג אחד) עשה בדיוק את זה, ו-YOLOv7 נבנה על גבי YOLOR על ידי אותם מחברים.

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

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

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

פילוח מופעים עם YOLOv7

ספרייה סטנדרטית המשמשת למשל פילוח, זיהוי אובייקטים והערכת נקודות מפתח ב-Python היא Detectron2, שנבנתה על ידי Meta AI.

הספרייה מציעה שיטות נוחות ושיעורים שונים כדי לעזור להמחיש את התוצאות בצורה יפה, אבל היישום הבסיסי לזיהוי הוא Mask R-CNN. הוכח כי YOLO מתגבר על דגמים מבוססי R-CNN בכל התחומים. מאגר YOLOv7 תואם ל-Detectron2 ותואם לכלי ה-API וכלי ההדמיה שלו, מה שמקל על הפעלת פילוח מהיר ומדויק של מופעים ללא צורך בלימוד API חדש. אתה יכול, למעשה, להחליף את עמוד השדרה של Mask R-CNN ולהחליף אותו ב-YOLOv7.

התקנת תלות - YOLOv7 ו-Detectron2

בוא נתחיל קודם כל ונתקין את התלות. אנו נשכפל את ה-Repo GitHub עבור פרויקט YOLOv7, ונתקין את הגרסה העדכנית ביותר של Detectron2 באמצעות pip:

! git clone -b mask https://github.com/WongKinYiu/yolov7.git
! pip install pyyaml==5.1
! pip install 'git+https://github.com/facebookresearch/detectron2.git'

Detectron2 דורש pyyaml גם כן. כדי להבטיח תאימות, תרצה גם לציין את הריצה torch גִרְסָה:

! pip install torch==1.10.1+cu111 torchvision==0.11.2+cu111 torchaudio==0.10.1 -f https://download.pytorch.org/whl/torch_stable.html

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

%cd yolov7
! curl -L https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7-mask.pt -o yolov7-mask.pt

עברנו לראשונה ל- yolov7 ספרייה (הספרייה שהורדת המכילה את הפרויקט) ולאחר מכן הורדת שם את קובץ המשקולות. עם זה - התלות שלנו מוגדרת! בואו לייבא את החבילות והשיעורים שבהם נשתמש:

import matplotlib.pyplot as plt
import torch
import cv2
import yaml
from torchvision import transforms
import numpy as np

from utils.datasets import letterbox
from utils.general import non_max_suppression_mask_conf

from detectron2.modeling.poolers import ROIPooler
from detectron2.structures import Boxes
from detectron2.utils.memory import retry_if_cuda_oom
from detectron2.layers import paste_masks_in_image

מסקנות לפילוח מופעים עם YOLOv7

תחילה נסתכל על התמונה שאנו מפלח:

street_img = cv2.imread('../street.png')
street_img = cv2.cvtColor(street_img, cv2.COLOR_BGR2RGB)

fig = plt.figure(figsize=(12, 6))
plt.imshow(street_img)

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

כעת נוכל להגיע לטעינת הדגם ולהכנתו להסקת מסקנות. ה hyp.scratch.mask.yaml הקובץ מכיל תצורות עבור היפרפרמטרים, אז אנחנו נטען אותו בהתחלה, נבדוק את המכשיר הפעיל (GPU או CPU), ונטען את הדגם מקובץ המשקולות שהורדנו זה עתה:

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

with open('data/hyp.scratch.mask.yaml') as f:
    hyp = yaml.load(f, Loader=yaml.FullLoader)

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

def load_model():
    model = torch.load('yolov7-mask.pt', map_location=device)['model']
    
    model.eval()

    if torch.cuda.is_available():
        
        
        model.half().to(device)
    return model

model = load_model()

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

def run_inference(url):
    image = cv2.imread(url) 
    
    image = letterbox(image, 640, stride=64, auto=True)[0] 
    
    image = transforms.ToTensor()(image) 
    
    image = image.half().to(device)
    
    image = image.unsqueeze(0) 
    output = model(image) 
    return output, image

output, image = run_inference('../street.png')

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

output.keys()

התחזיות שהדגם עשה הן גולמיות - נצטרך להעביר אותן non_max_supression(), והשתמש ב-ROIPooler מ-Detectron2.

הערה: "גיוס ROI" הוא קיצור של "אזור של איגום אינטרסים" ומשמש לחילוץ מפות תכונות קטנות עבור משימות זיהוי ופילוח של אובייקטים, באזורים שעשויים להכיל אובייקטים.

inf_out = output['test']
attn = output['attn']
bases = output['bases']
sem_output = output['sem']

bases = torch.cat([bases, sem_output], dim=1)
nb, _, height, width = image.shape
names = model.names
pooler_scale = model.pooler_scale

pooler = ROIPooler(output_size=hyp['mask_resolution'], 
                   scales=(pooler_scale,), 
                   sampling_ratio=1, 
                   pooler_type='ROIAlignV2', 
                   canonical_level=2)
                   

output, output_mask, _, _, _ = non_max_suppression_mask_conf(inf_out, 
                                                             attn, 
                                                             bases, 
                                                             pooler, 
                                                             hyp, 
                                                             conf_thres=0.25, 
                                                             iou_thres=0.65, 
                                                             merge=False, 
                                                             mask_iou=None)                 

כאן - השגנו את התחזיות עבור אובייקטים והתוויות שלהם output והמסכות שאמורות לכסות את החפצים האלה output_mask:

output[0].shape 
output_mask[0].shape 

המודל מצא 30 מופעים בתמונה, כל אחד עם תווית הקשורה אליהם. בואו ניצור קופסאות עבור המופעים שלנו בעזרת זה של Detectron2 Boxes מחלקה ועיבוי את pred_masks (המכילים מסכה בוליאנית) לסט של פיקסלים שנוכל להחיל על התמונה המקורית:

pred, pred_masks = output[0], output_mask[0]
base = bases[0]
bboxes = Boxes(pred[:, :4])

original_pred_masks = pred_masks.view(-1, 
                                      hyp['mask_resolution'], 
                                      hyp['mask_resolution'])

pred_masks = retry_if_cuda_oom(paste_masks_in_image)(original_pred_masks, 
                                                     bboxes, 
                                                     (height, width), 
                                                     threshold=0.5)
                                                     

pred_masks_np = pred_masks.detach().cpu().numpy()
pred_cls = pred[:, 5].detach().cpu().numpy()
pred_conf = pred[:, 4].detach().cpu().numpy()
nimg = image[0].permute(1, 2, 0) * 255
nimg = nimg.cpu().numpy().astype(np.uint8)
nimg = cv2.cvtColor(nimg, cv2.COLOR_RGB2BGR)
nbboxes = bboxes.tensor.detach().cpu().numpy().astype(np.int)

השמיים original_pred_masks מציין את המסכות החזויות עבור התמונה המקורית:

original_pred_masks.shape 

ולבסוף, אנחנו יכולים לשרטט את התוצאות עם:

def plot_results(original_image, pred_img, pred_masks_np, nbboxes, pred_cls, pred_conf, plot_labels=True):
  for one_mask, bbox, cls, conf in zip(pred_masks_np, nbboxes, pred_cls, pred_conf):
    if conf < 0.25:
        continue
    color = [np.random.randint(255), np.random.randint(255), np.random.randint(255)]

    pred_img = pred_img.copy()
                             
    
    pred_img[one_mask] = pred_img[one_mask] * 0.5 + np.array(color, dtype=np.uint8) * 0.5
    
    pred_img = cv2.rectangle(pred_img, (bbox[0], bbox[1]), (bbox[2], bbox[3]), color, 2)

    if plot_labels:
      label = '%s %.3f' % (names[int(cls)], conf)
      t_size = cv2.getTextSize(label, 0, fontScale=0.1, thickness=1)[0]
      c2 = bbox[0] + t_size[0], bbox[1] - t_size[1] - 3
      pred_img = cv2.rectangle(pred_img, (bbox[0], bbox[1]), c2, color, -1, cv2.LINE_AA)
      pred_img = cv2.putText(pred_img, label, (bbox[0], bbox[1] - 2), 0, 0.5, [255, 255, 255], thickness=1, lineType=cv2.LINE_AA)  

  fig, ax = plt.subplots(1, 2, figsize=(pred_img.shape[0]/10, pred_img.shape[1]/10), dpi=150)

  original_image = np.moveaxis(image.cpu().numpy().squeeze(), 0, 2).astype('float32')
  original_image = cv2.cvtColor(original_image, cv2.COLOR_RGB2BGR)
  
  ax[0].imshow(original_image)
  ax[0].axis("off")
  ax[1].imshow(pred_img)
  ax[1].axis("off")

התמונה מועתקת כך שלא נחיל טרנספורמציות על התמונה במקום, אלא על עותק. עבור כל פיקסל שתואם בין תמונת הקלט לבין המסכות החזויות, אנו מיישמים צבע עם אטימות של 0.5 ולכל אובייקט, אנו מציירים א cv2.Rectangle() שמקיף אותו מהתיבות התוחמות (bbox). אם ברצונך לתכנן תוויות, שעבורן עשויה להיות חפיפה משמעותית, יש א plot_labels דגל ב plot_results() חתימת השיטה. בואו ננסה לשרטט את התמונה שאיתה התחלנו לעבוד קודם לכן עם ובלי תוויות:

%matplotlib inline
plot_results(image, nimg, pred_masks_np, nbboxes, pred_cls, pred_conf, plot_labels=False)

פילוח מופעים עם YOLOv7 ב-Python PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

%matplotlib inline
plot_results(image, nimg, pred_masks_np, nbboxes, pred_cls, pred_conf, plot_labels=True)

פילוח מופעים עם YOLOv7 ב-Python PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

ריכזנו את שתי התמונות - התמונה המקורית והתמונה המפולחת בעלילה אחת. לרזולוציה גבוהה יותר, כוונן את dpi (נקודות לאינץ') ארגומנט ב- subplots() התקשר, ותווה רק את התמונה עם מפת הפילוח החזויה/התוויות כדי לכבוש את הדמות בשלמותה.

הולך רחוק יותר - למידה עמוקה מעשית לראייה ממוחשבת

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

פילוח מופעים עם YOLOv7 ב-Python PlatoBlockchain Data Intelligence. חיפוש אנכי. איי.

עוד קורס ראיית מחשב?

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

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

מה יש בפנים?

  • העקרונות הראשונים של חזון וכיצד ניתן ללמד מחשבים "לראות"
  • משימות ויישומים שונים של ראייה ממוחשבת
  • כלי המקצוע שיקלו עליכם את העבודה
  • מציאת, יצירה וניצול של מערכי נתונים עבור ראייה ממוחשבת
  • התיאוריה והיישום של רשתות עצביות קונבולוציונליות
  • טיפול בהסטת תחום, התרחשות משותפת והטיות אחרות במערך נתונים
  • העבר למידה וניצול זמן ההדרכה ומשאבי החישוב של אחרים לטובתך
  • בנייה והדרכה של סיווג סרטן שד חדיש
  • כיצד ליישם מנה בריאה של ספקנות על רעיונות מיינסטרים ולהבין את ההשלכות של טכניקות מאומצות באופן נרחב
  • הדמיית "מרחב הקונספט" של ConvNet באמצעות t-SNE ו-PCA
  • תיאורי מקרה של האופן שבו חברות משתמשות בטכניקות ראייה ממוחשבת כדי להשיג תוצאות טובות יותר
  • הערכת מודל נכונה, הדמיית מרחב סמוי וזיהוי תשומת הלב של המודל
  • ביצוע מחקר תחום, עיבוד מערכי נתונים משלך והקמת בדיקות מודל
  • ארכיטקטורות חדשניות, התקדמות רעיונות, מה מייחד אותם וכיצד ליישם אותם
  • KerasCV – ספריית WIP ליצירת צינורות ודגמים מתקדמים
  • כיצד לנתח ולקרוא מאמרים וליישם אותם בעצמך
  • בחירת דגמים בהתאם ליישום שלך
  • יצירת צינור למידת מכונה מקצה לקצה
  • נוף ואינטואיציה על זיהוי אובייקטים עם R-CNN מהירים יותר, RetinaNets, SSDs ו-YOLO
  • מופע ופילוח סמנטי
  • זיהוי אובייקטים בזמן אמת עם YOLOv5
  • הכשרת גלאי אובייקטים של YOLOv5
  • עבודה עם רובוטריקים באמצעות KerasNLP (ספריית WIP בעלת חוזק בתעשייה)
  • שילוב רובוטריקים עם ConvNets ליצירת כיתובים של תמונות
  • חלום עמוק
  • אופטימיזציה של מודל Deep Learning לראייה ממוחשבת

בול זמן:

עוד מ Stackabuse