सामग्री पर जाएं

वॉल्यूम, पॉइंट क्लाउड और वीडियो पर मॉडल प्रशिक्षित करें

पेंट किए गए CT मास्क पर 3D U-Net फ़िट करें, लिडार क्यूबॉइड पर अपना OpenPCDet डिटेक्टर चलाएँ, और वीडियो ट्रैकर प्रशिक्षित करें, हर एक का स्कोर होल्ड-आउट आइटम पर।

v2.14.0 में नया

यह ट्यूटोरियल Potato अध्ययन के अपने एनोटेशन से 3D और गतिशील डेटा पर तीन मॉडल प्रशिक्षित करता है। volume-unet एक 3D U-Net प्रशिक्षित करता है जो CT और MR वॉल्यूम को सेगमेंट करता है, external-3d वह लिडार डिटेक्टर चलाता है जिसे आप खुद बनाते और चलाते हैं, और video-track एक वीडियो ऑब्जेक्ट ट्रैकर प्रशिक्षित करता है। यह पेज उन टीमों के लिए है जो पहले से Potato में वॉल्यूम, पॉइंट क्लाउड या वीडियो एनोटेट करती हैं और चाहती हैं कि बाकी पर प्री-लेबल एक मॉडल लगाए। हर ट्रेनर के लिए पेज बताता है कि प्रशिक्षण डेटा कौन-सी स्कीम बनाती है, potato validate पास करने वाला config कैसा है, रन क्या करता है, होल्ड-आउट स्कोर क्या है, और भविष्यवाणियाँ एनोटेटरों तक कैसे पहुँचती हैं। पहले मॉडल का ट्यूटोरियल बिना GPU वाले टेक्स्ट क्लासिफ़ायर के साथ Training पेज के चरण दिखाता है, और यह ट्यूटोरियल उसी वॉकथ्रू को पहले से पढ़ा मानता है।

ट्रेनर सारांश

तीनों ट्रेनर हर रन में एक स्कीम फ़िट करते हैं, मॉडल को रन के होल्ड-आउट val और test आइटम पर स्कोर करते हैं, और भविष्यवाणियों को प्री-लेबल के रूप में राइट-बैक करते हैं जिन्हें एनोटेटर संपादित करते हैं। व्यवहार में volume-unet और external-3d के पीछे के डिटेक्टरों को GPU चाहिए, इसलिए इन दोनों ट्रेनरों के config रन को ssh से GPU सर्वर पर भेजते हैं, जैसा रिमोट प्रशिक्षण ट्यूटोरियल सेट करता है।

ट्रेनरस्कीमआइटमप्रशिक्षण मशीन पर इंस्टॉलमुख्य स्कोर
volume-unetvolume_annotation (पेंट किए गए मास्क)NIfTI वॉल्यूम, DICOM श्रृंखलाpip install "potato-annotation[train-vision,volumes]"; व्यवहार में GPUmean_dice
external-3dspatial_annotation (क्यूबॉइड)पॉइंट क्लाउडआपका अपना डिटेक्टर (OpenPCDet, MMDetection3D)map_3d_50
video-tracktracking या combined मोड में video_annotationवीडियोpip install "potato-annotation[train-vision]" opencv-pythonidf1

हर ट्रेनर मीडिया को डिस्क की फ़ाइलों से पढ़ता है। मीडिया पाथ को टास्क डायरेक्टरी या media_directory के भीतर इशारा करना चाहिए, और जिन आइटम का मीडिया http(s) URL है वे प्रशिक्षण और भविष्यवाणी से बाहर रखे जाते हैं।

volume-unet से CT और MR वॉल्यूम सेगमेंट करें

volume-unet वे मास्क सीखता है जो एनोटेटर volume_annotation स्कीम में पेंट करते हैं, और उन वॉल्यूम पर मास्क पेंट करता है जिन्हें अभी किसी ने सेगमेंट नहीं किया। स्कीम NIfTI फ़ाइल या DICOM श्रृंखला को तीन जुड़े व्यू (एक्सियल, कोरोनल और सैजिटल) में दिखाती है, और एनोटेटर हर लेबल को ब्रश से या पॉलिगॉन बंद करके पेंट करते हैं। source_field जिस आइटम फ़ील्ड का नाम देता है, उसमें media_directory के सापेक्ष .nii या .nii.gz फ़ाइल होती है, या वह डायरेक्टरी जिसमें एक DICOM श्रृंखला हो। स्लाइस पर खींचे गए बॉक्स का कोई मास्क नहीं होता, इसलिए केवल बॉक्स वाला उत्तर प्रशिक्षण लक्ष्य नहीं है। Potato शोध सॉफ़्टवेयर है जिसकी कोई चिकित्सीय या नियामक मंज़ूरी नहीं है, और यहाँ प्रशिक्षित मॉडल ऐसे मास्क सुझाता है जिन्हें एनोटेटर सुधारते हैं।

नीचे का config तिल्ली और यकृत को सेगमेंट करता है, GPU सर्वर पर प्रशिक्षित होता है, और train स्प्लिट के बाहर के हर वॉल्यूम को प्री-लेबल करता है:

yaml
annotation_task_name: "Spleen segmentation"
task_dir: .
media_directory: media
data_files:
  - data/scans.jsonl
item_properties:
  id_key: id
  text_key: volume
output_annotation_dir: annotation_output
user_config:
  allow_all_users: true
 
annotation_schemes:
  - annotation_type: volume_annotation
    name: organs
    description: "Paint the spleen and the liver on every slice where each organ appears."
    source_field: volume
    labels:
      - {name: Spleen, color: "#e6553a", key_value: "1"}
      - {name: Liver, color: "#3a8ee6", key_value: "2"}
    tools: [brush, eraser, polygon]
    default_window: Soft tissue
 
model_training:
  enabled: true
  backend: gpu-server
  backends:
    gpu-server:
      type: ssh
      host: gpu.example.edu
      python: /opt/conda/bin/python3
      gpus: auto
      min_free_gpu_mb: 8000
  trainer_params:
    volume-unet:
      patch: 96
  writeback:
    schemas: [organs]
    min_confidence: 0.6
    include_unlabeled: true

डेटा की हर पंक्ति एक वॉल्यूम का नाम देती है:

json
{"id": "case_001", "volume": "case_001.nii.gz"}
{"id": "case_002", "volume": "case_002_ct"}

patch मान उस घनाकार पैच की भुजा तय करता है जिस पर नेटवर्क प्रशिक्षित होता है, और डिफ़ॉल्ट तीन स्तरों पर वह 4 का गुणज होना चाहिए (2 की घात levels घटा 1)। 96 वोक्सेल का पैच नेटवर्क को हर वोक्सेल के आसपास डिफ़ॉल्ट 64 से अधिक संदर्भ देता है और अधिक GPU मेमोरी माँगता है। min_free_gpu_mb: 8000 के साथ Potato रन केवल उस GPU पर शुरू करता है जिसकी कम से कम 8,000 MB मेमोरी खाली हो। Potato हर पेंट किए गए लेबल के मास्क के भीतर मॉडल की औसत प्रायिकता लेता है और उन औसतों में सबसे कम को वॉल्यूम का विश्वास बताता है। min_confidence: 0.6 के साथ, जिस वॉल्यूम में कोई एक अंग 0.6 से कम औसत प्रायिकता पर पेंट हुआ हो, उसे प्री-लेबल नहीं मिलता।

volume-unet रन के प्रशिक्षण चरण

रन हर एनोटेट किए गए वॉल्यूम को उसी वोक्सेल क्रम में पढ़ता है जिसमें विजेट पेंट करता है, और मास्क को प्रति वोक्सेल एक लेबल में बदल देता है। जहाँ दो लेबल ओवरलैप करते हैं, वहाँ बंडल के लेबल क्रम में बाद वाला लेबल जीतता है, जैसा NIfTI निर्यात करता है। तीव्रताओं को हर वॉल्यूम के 0.5 और 99.5 परसेंटाइल पर क्लिप करके मानकीकृत किया जाता है। नेटवर्क सादे torch में 3D U-Net है (तीन स्तर, इंस्टेंस नॉर्म), जो प्रति एपॉक 100 यादृच्छिक पैच पर क्रॉस-एंट्रॉपी और सॉफ़्ट Dice के साथ प्रशिक्षित होता है। आधे पैच पेंट किए गए वोक्सेल पर केंद्रित होते हैं, इसलिए छोटी संरचनाएँ प्रशिक्षण में दिखती हैं। हर एपॉक के बाद रन val वॉल्यूम पर औसत Dice स्कोर करता है और सबसे अच्छा एपॉक रखता है, और बेहतर स्कोर के बिना 10 एपॉक बीतने पर रन रुक जाता है। भविष्यवाणी में पैच पूरे वॉल्यूम पर आधे-पैच ओवरलैप के साथ सरकता है और प्रायिकताओं का औसत लिया जाता है।

train स्प्लिट में कम से कम तीन एनोटेट किए गए वॉल्यूम चाहिए (min_instances)। जिस वॉल्यूम का पेंट किया गया आकार फ़ाइल के आकार से अलग हो, वह रन लॉग में चेतावनी के साथ बाहर रखा जाता है, और जिस वॉल्यूम की फ़ाइल गायब हो वह भी। एक वॉल्यूम पर कई पाठकों के होने पर रन उस एक पाठक के मास्क पर प्रशिक्षित होता है जिसे aggregation समाधानित करता है, क्योंकि एग्रीगेटर पूरे उत्तरों की तुलना करते हैं। कई पाठकों और STAPLE के साथ CT वॉल्यूम सेगमेंट करें पाठकों की सहमति और Potato के बाहर बने सर्वसम्मति मास्क को समझाता है।

वॉल्यूम के लिए होल्ड-आउट स्कोर

Potato हर होल्ड-आउट वॉल्यूम पर हर लेबल का Dice गुणांक (dice_<label>) निकालता है और हर वॉल्यूम और लेबल पर औसत को mean_dice के रूप में रिपोर्ट करता है। जो लेबल किसी ऐसे वॉल्यूम से मॉडल ने छोड़ दिया जिसमें वह लेबल है, उसका स्कोर 0 है। ट्रेनर val पर सबसे अच्छा एपॉक चुनता है, इसलिए Runs तालिका मुख्य स्कोर test से लेती है (test_mean_dice)। प्रति-लेबल स्कोर की पूरी सूची रन पेज पर है।

स्लाइस व्यू पर मास्क प्री-लेबल

भविष्यवाणी किए गए मास्क विजेट के अपने रूप में, हर लेबल और एक्सियल स्लाइस के हिसाब से, prefilled_from: model चिह्नित होकर लौटते हैं, और एनोटेटर के वॉल्यूम खोलने पर स्लाइस व्यू पर दिखते हैं। एनोटेटर मास्क को ब्रश और इरेज़र से सुधारता है, और सुधारे गए मास्क उस एनोटेटर के उत्तर के रूप में सहेजे जाते हैं। रन के train स्प्लिट के आइटम को कभी प्री-लेबल नहीं मिलता। include_unlabeled के बिना रन केवल अपने val और test वॉल्यूम पर भविष्यवाणी करता है।

external-3d से 3D क्यूबॉइड पहचानें

external-3d एनोटेट किए गए स्कैन को उस 3D डिटेक्टर को सौंपता है जिसे आप प्रशिक्षण होस्ट पर इंस्टॉल करते हैं, आपके train और predict कमांड चलाता है, और भविष्यवाणी किए गए बॉक्स को क्यूबॉइड के रूप में वापस पढ़ता है। Potato कोई पॉइंट-क्लाउड डिटेक्टर साथ नहीं देता। जिन दो डिटेक्टरों के लिए ट्रेनर बना है, OpenPCDet और MMDetection3D, उन्हें GPU होस्ट पर कंपाइल किए गए CUDA ऑपरेटर चाहिए। Potato की ओर से ट्रेनर को केवल numpy चाहिए।

प्रशिक्षण डेटा cuboid_3d टूल वाली spatial_annotation स्कीम से आता है। एनोटेटर PCD, PLY, LAS या KITTI .bin स्कैन पर उन्मुख बॉक्स रखते हैं, जो स्कैन के अपने फ़्रेम में मीटर में सहेजे जाते हैं (देखें 3D पॉइंट क्लाउड और क्यूबॉइड)। लक्ष्य केवल क्यूबॉइड हैं, इसलिए उसी स्कीम के पॉइंट, पॉलीलाइन और पॉइंट सेगमेंट अनदेखे रहते हैं। हर आइटम एक स्कैन है, और ट्रैक आईडी वाले फ़्रेमों का क्रम प्रशिक्षण लक्ष्य नहीं है।

डिटेक्टर के लिए लिखा गया डेटासेट फ़ोल्डर

train कमांड चलने से पहले Potato स्कैन को {dataset} में लिखता है, जो रन के फ़ोल्डर के भीतर dataset नाम का फ़ोल्डर है, OpenPCDet के कस्टम डेटासेट लेआउट में:

  • points/<id>.npy में एक स्कैन x y z intensity की float32 पंक्तियों के रूप में होता है, और फ़ाइल में तीव्रता न हो तो तीव्रता 0 होती है।
  • labels/<id>.txt में train और val स्कैन के लिए हर क्यूबॉइड की एक पंक्ति होती है, x y z dx dy dz heading label के रूप में। हेडिंग +z के गिर्द रेडियन में घुमाव है, और पिच और रोल नहीं रखे जाते। लेबल नाम में स्पेस अंडरस्कोर बन जाता है।
  • ImageSets/train.txt, val.txt और predict.txt स्कैन आईडी सूचीबद्ध करते हैं। predict.txt में val और test स्कैन होते हैं, और writeback.include_unlabeled चालू होने पर बिना लेबल वाले स्कैन भी।

हर <id> आइटम आईडी के SHA-1 के पहले 16 हेक्स वर्ण है, क्योंकि आइटम आईडी में ऐसे वर्ण हो सकते हैं जो फ़ाइल नाम में नहीं चलते। test स्कैन के लेबल फ़ोल्डर में कभी नहीं लिखे जाते। Potato जियोरेफ़रेंस्ड स्कैन को स्कैन के मूल बिंदु के सापेक्ष लिखता है, क्योंकि जियोरेफ़रेंस्ड निर्देशांक float32 के लिए बहुत बड़े होते हैं, और भविष्यवाणी किए गए बॉक्स को उसी ऑफ़सेट से वापस खिसकाता है।

डिटेक्टर से वापस पढ़ी जाने वाली भविष्यवाणी फ़ाइलें

predict कमांड हर स्कैन के लिए एक फ़ाइल {predictions}/<id>.txt में लिखता है, हर पंक्ति में एक बॉक्स, x y z dx dy dz heading label score के रूप में। स्कोर वैकल्पिक है। जो पंक्ति पार्स न हो, जिसमें nan या inf हो, जो स्कीम में अनुपस्थित लेबल का नाम दे, या जो बिना आकार के बॉक्स का वर्णन करे, उसे Potato छोड़ देता है, और रन लॉग छोड़ी गई पंक्तियाँ गिनता है। शेष बॉक्स source: model चिह्नित cuboid_3d ऑब्जेक्ट के रूप में लौटते हैं, और हर बॉक्स का स्कोर उस बॉक्स का विश्वास बन जाता है। Potato स्कैन का विश्वास उस स्कैन के सबसे कम बॉक्स स्कोर के बराबर रखता है, और min_confidence उसी मान पर लागू होता है।

train और predict कमांड

दोनों कमांड ट्रेनर पैरामीटर के रूप में सेट होते हैं। Potato हर कमांड को शेल की तरह शब्दों में बाँटता है, {dataset}, {workdir} (रन का फ़ोल्डर) और {predictions} को संबंधित पाथ से बदलता है, और कमांड को शेल के बिना रन के फ़ोल्डर में चलाता है। कमांड के अन्य ब्रेस जैसे लिखे हैं वैसे रहते हैं। पाइप, && और $VARIABLES प्रोग्राम तक शाब्दिक शब्दों के रूप में पहुँचते हैं, इसलिए बहु-चरण काम स्क्रिप्ट में होना चाहिए। पॉइंट-क्लाउड अध्ययन के config में यह ब्लॉक जोड़ें:

yaml
model_training:
  enabled: true
  backend: gpu-server
  backends:
    gpu-server:
      type: ssh
      host: gpu.example.edu
      python: /opt/conda/envs/pcdet/bin/python
      gpus: auto
  trainer_params:
    external-3d:
      train_command: "/opt/pcdet-jobs/train.sh {dataset} {workdir}"
      predict_command: "/opt/conda/envs/pcdet/bin/python /opt/pcdet-jobs/predict.py {dataset} {workdir} {predictions}"
      timeout_s: 43200
  writeback:
    schemas: [objects]
    min_confidence: 0.3
    include_unlabeled: true

पाथ प्रशिक्षण होस्ट पर हैं, जहाँ रन का फ़ोल्डर भी रहता है। timeout_s हर कमांड की सीमा तय करता है, और यहाँ 12 घंटे डिफ़ॉल्ट 24 की जगह लेते हैं। जो train कमांड शून्येतर कोड से बाहर निकले वह रन को विफल कर देता है, और रन की त्रुटि कमांड के आउटपुट की अंतिम पंक्तियाँ दिखाती है।

train.sh आपकी अपनी स्क्रिप्ट है। OpenPCDet के लिए स्क्रिप्ट OpenPCDet के कस्टम डेटासेट config को {dataset} की ओर इंगित करती है, python -m pcdet.datasets.custom.custom_dataset create_custom_infos <dataset config> से info फ़ाइलें बनाती है, OpenPCDet की प्रशिक्षण स्क्रिप्ट चलाती है, और चेकपॉइंट {workdir} के नीचे सहेजती है। डिटेक्टर के config के क्लास नाम labels/ में जैसे लिखे हैं वैसे ही लेबल नामों से मेल खाने चाहिए। MMDetection3D की कस्टम डेटासेट गाइड पॉइंट क्लाउड केवल .bin फ़ाइलों के रूप में पढ़ती है, इसलिए MMDetection3D के लिए स्क्रिप्ट पहले हर points/<id>.npy को .bin फ़ाइल के रूप में लिखती है। प्रशिक्षण छोड़ने के लिए train_command खाली रखें, और तब predict_command वह मॉडल चलाता है जिसे आपने कहीं और प्रशिक्षित किया।

predict.py predict.txt की आईडी पढ़ती है, हर स्कैन पर डिटेक्टर चलाती है, और बॉक्स लिखती है। load_model और detect फ़ंक्शन आपके अपने कोड हैं जो आपके प्रशिक्षित डिटेक्टर को लपेटते हैं:

python
"""predict.py DATASET WORKDIR PREDICTIONS: one line per box, one file per scan."""
import os
import sys
 
import numpy as np
 
from my_detector import load_model, detect  # your code around OpenPCDet or MMDetection3D
 
dataset, workdir, out = sys.argv[1:4]
model = load_model(os.path.join(workdir, "output"))  # where train.sh saved the checkpoint
os.makedirs(out, exist_ok=True)
 
with open(os.path.join(dataset, "ImageSets", "predict.txt")) as fh:
    scan_ids = fh.read().split()
 
for scan_id in scan_ids:
    points = np.load(os.path.join(dataset, "points", scan_id + ".npy"))  # float32, (N, 4)
    with open(os.path.join(out, scan_id + ".txt"), "w") as fh:
        for x, y, z, dx, dy, dz, heading, label, score in detect(model, points):
            fh.write(f"{x} {y} {z} {dx} {dy} {dz} {heading} {label} {score}\n")

train_command के बिना predict कमांड ही पूरा रन है, और शून्येतर कोड से निकलने वाला predict कमांड रन को विफल करता है। जो predict कमांड 0 से निकलता है पर किसी स्कैन के लिए <id>.txt नहीं लिखता, या केवल ऐसी पंक्तियाँ लिखता है जिन्हें Potato छोड़ देता है, वह भी विफल गिना जाता है, क्योंकि उस आउटपुट पर स्कोर किया गया रन ऐसे मॉडल जैसा दिखेगा जिसे कुछ मिला ही नहीं। खाली फ़ाइल का मतलब है ऐसा स्कैन जिसमें कोई वस्तु नहीं है। train कमांड के बाद विफल होने वाला predict कमांड रन को विफल नहीं करता। रन चेतावनी "Prediction pass failed after 0 prediction(s)" और कमांड की अंतिम पंक्तियों के साथ पूरा होता है, और रन में न भविष्यवाणियाँ होती हैं न होल्ड-आउट स्कोर। जब पूरा हुआ रन "not scored" दिखाए, तब उस चेतावनी के लिए रन लॉग जाँचें।

क्यूबॉइड के लिए होल्ड-आउट स्कोर

Potato हर लेबल का 3D औसत परिशुद्धता 0.5 के आयतनी IoU पर निकालता है (ap_3d_50_<label>)। IoU किसी भी घुमाव पर उन्मुख क्यूबॉइड के लिए सटीक है। Potato IoU 0.25 और 0.5 पर लेबलों का औसत भी रिपोर्ट करता है, और 0.5 पर परिशुद्धता, रिकॉल और F1 भी। मुख्य स्कोर map_3d_50 है। train_command होने पर Runs तालिका मुख्य स्कोर पहले test से लेती है, क्योंकि train कमांड को {dataset} में val लेबल सौंपे जाते हैं और वह उन्हीं लेबलों पर चेकपॉइंट चुन सकता है। train_command के बिना मॉडल ने अध्ययन के val आइटम कभी नहीं देखे, और मुख्य स्कोर val से आता है।

पॉइंट-क्लाउड व्यूअर में क्यूबॉइड प्री-लेबल

भविष्यवाणी किए गए क्यूबॉइड पॉइंट-क्लाउड व्यूअर में संपादन योग्य बॉक्स के रूप में दिखते हैं, और संपादित बॉक्स एनोटेटर के उत्तर के रूप में सहेजा जाता है। व्यूअर के बनाने से पहले Potato हर भविष्यवाणी किए गए ऑब्जेक्ट की जाँच करता है, और उस ऑब्जेक्ट को छोड़ देता है जिसकी ज्यामिति पार्स न हो, जिस क्यूबॉइड का कोई आकार न हो, और जिसका लेबल स्कीम में न हो। 3D पॉइंट क्लाउड कैसे एनोटेट करें एनोटेशन पक्ष और 3D बॉक्स पर सहमति समझाती है।

video-track से वीडियो में ऑब्जेक्ट ट्रैक करें

video-track उन ट्रैक से सीखता है जो एनोटेटर tracking या combined मोड में video_annotation स्कीम में खींचते हैं, और उन वीडियो पर ट्रैक की भविष्यवाणी करता है जिन्हें किसी ने ट्रैक नहीं किया। ट्रैक एक लेबल और हर कीफ़्रेम पर एक बॉक्स है, और विजेट कीफ़्रेम के बीच बॉक्स को इंटरपोलेट करता है। दूसरे मोड की video_annotation स्कीम ट्रैक की जगह सेगमेंट सहेजती है, और उस स्कीम के लिए video-track नहीं दिया जाता।

yaml
annotation_task_name: "Pedestrian tracking"
task_dir: .
media_directory: media
data_files:
  - data/clips.jsonl
item_properties:
  id_key: id
  text_key: video
output_annotation_dir: annotation_output
user_config:
  allow_all_users: true
 
annotation_schemes:
  - annotation_type: video_annotation
    name: tracks
    description: "Track every pedestrian and cyclist with a box at each keyframe."
    source_field: video
    mode: tracking
    video_fps: 25
    labels:
      - {name: pedestrian, color: "#FF6B6B"}
      - {name: cyclist, color: "#45B7D1"}
    tracking_options:
      interpolation: linear
      auto_advance_frames: 5
    frame_stepping: true
 
model_training:
  enabled: true
  trainer_params:
    video-track:
      frame_fps: 2
      predict_fps: 5
      max_age: 4
  writeback:
    schemas: [tracks]
    include_unlabeled: true

डेटा की हर पंक्ति media_directory के अंतर्गत एक क्लिप का नाम देती है:

json
{"id": "clip_001", "video": "/media/clip_001.mp4"}
{"id": "clip_002", "video": "/media/clip_002.mp4"}

video_fps को क्लिप की वास्तविक फ़्रेम दर पर सेट करें। कीफ़्रेम फ़्रेम के हिसाब से गिने जाते हैं, और ट्रेनर भविष्यवाणी किए गए कीफ़्रेम को स्कीम के video_fps पर गिनता है (सेट न होने पर 30)। ट्रेनर नमूना फ़्रेम पर बॉक्स को हर ट्रैक की अपनी interpolation सेटिंग (linear, cubic Catmull-Rom या constant) से पढ़ता है। इसलिए मॉडल जिन बॉक्स से सीखता है वे उसी पथ पर चलते हैं जो एनोटेटरों ने देखा। विजेट की तरह ही, एक कीफ़्रेम वाला ट्रैक हर फ़्रेम पर टिका रहता है, और जिस ट्रैक को विजेट ने startFrame और endFrame दिए हैं वह उन्हीं दो फ़्रेम के बीच चलता है। इन दो फ़्रेम के बाहर का कीफ़्रेम फिर भी अपने ही फ़्रेम पर दिखता है। predict_fps: 5 दो के बजाय प्रति सेकंड पाँच फ़्रेम पर पहचान करता है। प्रति सेकंड पाँच फ़्रेम तेज़ चलती वस्तु को अधिक कीफ़्रेम देते हैं और डिटेक्टर के अधिक पास की कीमत लेते हैं। ट्रैक तब समाप्त होता है जब max_age से अधिक नमूना फ़्रेम बिना मेल खाती पहचान के बीत जाएँ, इसलिए प्रति सेकंड 5 फ़्रेम पर max_age: 4 ट्रैक को 0.8 सेकंड की छूटी पहचानों तक जीवित रखता है। खंभे के पीछे से गुज़रने वाला पैदल यात्री एक ही ट्रैक रखता है, यदि डिटेक्टर उसे 0.8 सेकंड के भीतर फिर पा ले। यह config Potato चलाने वाली मशीन पर (local बैकएंड) प्रशिक्षित होता है, और वॉल्यूम config का gpu-server बैकएंड video-track के लिए भी चलता है।

video-track रन में प्रशिक्षण और ट्रैक जोड़ना

रन हर एनोटेट किए गए वीडियो को शुरुआत से अंतिम कीफ़्रेम तक प्रति सेकंड frame_fps फ़्रेम पर नमूना करता है, और हर नमूना फ़्रेम को OpenCV से पढ़ता है। कैनवास पिक्सेल एनोटेटर की स्क्रीन पर निर्भर करते हैं, इसलिए ट्रेनर उस फ़्रेम पर हर ट्रैक का बॉक्स चित्र के भिन्न के रूप में पढ़ता है। जिस नमूना फ़्रेम पर कोई ट्रैक नहीं है, वह खाली दृश्य के उदाहरण के रूप में प्रशिक्षण में रहता है। रन उन फ़्रेमों पर torchvision Faster R-CNN को फ़ाइन-ट्यून करता है, उन्हीं पैरामीटर और डिफ़ॉल्ट के साथ जो torchvision-detect के हैं। डिटेक्टर torchvision के COCO वेट से शुरू होता है। हर एपॉक के बाद रन val फ़्रेम पर IoU 0.5 पर बॉक्स mAP स्कोर करता है (frame_map_50) और सबसे अच्छा एपॉक रखता है।

भविष्यवाणी हर वीडियो को predict_fps पर नमूना करती है, हर नमूना फ़्रेम पर पहचान करती है, और पहचानों को ट्रैक में जोड़ती है। हर फ़्रेम की पहचानें उसी लेबल के जीवित ट्रैक से एक-से-एक मिलाई जाती हैं, हर ट्रैक के अंतिम बॉक्स से ओवरलैप के आधार पर, और मेल के लिए कम से कम match_iou (0.3) का IoU चाहिए। कम से कम new_track_score (0.5) स्कोर वाली बिना मेल की पहचान नया ट्रैक शुरू करती है। ट्रेनर लिखने और स्कोर करने से पहले उस अनुमानित ट्रैक को हटा देता है जिसकी पहचानें min_track_keyframes से कम हैं (डिफ़ॉल्ट 2)। नहीं तो विजेट एक पहचान वाले ट्रैक को हर फ़्रेम पर टिकाए रखता। हर पहचान एक कीफ़्रेम बनती है, इसलिए विजेट मॉडल के कीफ़्रेम के बीच वैसे ही इंटरपोलेट करता है जैसे एनोटेटर के कीफ़्रेम के बीच।

train स्प्लिट में कम से कम दो एनोटेट किए गए वीडियो चाहिए (min_instances)। जिस वीडियो को OpenCV डिकोड न कर सके, वह आइटम का नाम बताने वाली चेतावनी के साथ बाहर रखा जाता है, और रन बाकी के साथ जारी रहता है।

ट्रैक के लिए होल्ड-आउट स्कोर

Potato भविष्यवाणी किए गए ट्रैक की तुलना एनोटेट किए गए ट्रैक से हर होल्ड-आउट वीडियो में प्रति सेकंड 2 पर नमूना किए फ़्रेमों पर करता है, साथ में हर एनोटेट किया गया कीफ़्रेम। स्कोर MOTA, IDF1, ID स्विच, छूटे और झूठे धनात्मक हैं, जहाँ बॉक्स IoU 0.5 पर मिला हुआ गिना जाता है। MOTA छूटे, झूठे धनात्मक और पहचान बदलाव को एनोटेट किए गए बॉक्स की संख्या के विरुद्ध गिनता है। IDF1 पूरे वीडियो में सही पहचान से मिलाए गए बॉक्स का F1 स्कोर है, और IDF1 ही मुख्य स्कोर है (idf1)। ट्रेनर val पर सबसे अच्छा एपॉक चुनता है, इसलिए Runs तालिका मुख्य स्कोर test से लेती है।

वीडियो विजेट में ट्रैक प्री-लेबल

भविष्यवाणी किए गए ट्रैक वीडियो विजेट को ऐसे ट्रैक से भरते हैं जिनके कीफ़्रेम AI आउटपुट चिह्नित होते हैं और डिटेक्टर का स्कोर लिए होते हैं। ट्रैक खींचते समय विजेट बॉक्स को अपने कैनवास पिक्सेल में बदलता है, और एनोटेटर ट्रैक को किसी भी अन्य ट्रैक की तरह सुधारता है। वीडियो का विश्वास मॉडल के कीफ़्रेम का औसत स्कोर है। combined मोड में प्री-लेबल में केवल ट्रैक होते हैं, और सेगमेंट एनोटेटर जोड़ता है। वीडियो ऑब्जेक्ट ट्रैकिंग कैसे एनोटेट करें एनोटेशन पक्ष, ओक्लूज़न और अस्थायी सहमति समझाती है।

रन शुरू करें और परिणाम जाँचें

model_training जोड़ने के बाद सर्वर रीस्टार्ट करें, /admin/training खोलें, स्कीम और ट्रेनर चुनें, और Train now पर क्लिक करें। पेज केवल वे ट्रेनर देता है जो हर स्कीम के अनुकूल हैं, और जो ट्रेनर इंस्टॉल नहीं है उसे "not installed" के रूप में, इंस्टॉल कमांड के साथ सूचीबद्ध करता है। पहले रन से पहले GPU सर्वर जाँचने के लिए यह चलाएँ:

bash
potato training check gpu-server config.yaml

जाँच रिमोट Python संस्करण, हर GPU और उसकी खाली मेमोरी, रन को मिलने वाला GPU, और वे प्रशिक्षण पैकेज बताती है जो रिमोट इंटरप्रेटर में नहीं हैं। रन API से भी शुरू हो सकता है, प्रति-रन पैरामीटर के साथ जो trainer_params को अधिलेखित करते हैं:

bash
curl -X POST -H "X-API-Key: $KEY" -H "Content-Type: application/json" \
  http://localhost:8000/admin/training/api/runs \
  -d '{"trainer": "video-track", "schemas": ["tracks"], "params": {"predict_fps": 10}}'

रन पूरा होने पर Runs तालिका होल्ड-आउट स्कोर सूचीबद्ध करती है, और स्प्लिट और मीट्रिक टूलटिप में होते हैं। प्री-लेबल एनोटेटरों को एंकर करते हैं, इसलिए नए अध्ययन में include_unlabeled तभी चालू करें जब होल्ड-आउट स्कोर मॉडल के उत्तर दिखाने का समर्थन करे। मॉडल-इन-द-लूप ट्यूटोरियल सबसे कम विश्वास वाले प्री-लेबल पहले परोसना और सुधारों पर दोबारा प्रशिक्षित करना समझाता है, और मॉडल प्रशिक्षण का कॉन्फ़िगरेशन और रूट हर कुंजी, बैकएंड और राइट-बैक की जाँचें सूचीबद्ध करता है।

आगे पढ़ें

संदर्भ

  • Bernardin, K., and Stiefelhagen, R. (2008). Evaluating Multiple Object Tracking Performance: The CLEAR MOT Metrics. EURASIP Journal on Image and Video Processing. https://doi.org/10.1155/2008/246309
  • Çiçek, Ö., Abdulkadir, A., Lienkamp, S. S., Brox, T., and Ronneberger, O. (2016). 3D U-Net: Learning Dense Volumetric Segmentation from Sparse Annotation. MICCAI 2016. https://arxiv.org/abs/1606.06650
  • Ristani, E., Solera, F., Zou, R. S., Cucchiara, R., and Tomasi, C. (2016). Performance Measures and a Data Set for Multi-Target, Multi-Camera Tracking. ECCV 2016 Workshop on Benchmarking Multi-Target Tracking. https://arxiv.org/abs/1609.01775