Object Detection dengan PyTorch Detectron 2 dan Colab

Pada tutorial ini kita akan coba membuat object detection model dengan custom dataset kita sendiri menggunakan PyTorch Detectron 2.

Facebook Detectron 2 adalah salah satu python framework yang dapat digunakan untuk kasus object detection. Detectron dikembangkan oleh Facebook dengan menggunakan basis PyTorch sebagai deep learning frameworknya. Bagi yang belum tahu tentang PyTorch, bisa cek website resminya atau kunjungi tutorial kami sebelumnya di sini.

Framework lain untuk deteksi objek yang cukup populer adalah Tensorflow object-detection API (TFOD) yang dikembangkan oleh Google. Keduanya hampir memiliki fitur utama yang sama, salah satunya mereka menyediakan Model Zoo, di mana kita bisa mulai proses training menggunakan model yang sudah ada (pretrained model).

Detectron 2 Tutorial

Pada tutorial ini kita akan menggunakan Google Colab. Contoh code yang akan dibahas pada artikel ini tersedia di sini.

Detectron 2 Logo
  1. Dataset
  2. Instalasi
  3. Menyiapkan DatasetCatalog
  4. Training Model
  5. Save and Load Model

1. Dataset

Dataset yang akan kita gunakan sama dengan dataset dari tutorial sebelumnya. Kita akan mendeteksi pada suatu citra apakah ada kangguru atau rakun. Penjelasan detail format data dan bagaimana memprosesnya dapat dilihat pada artikel sebelumnya. Tapi, karena artikel sebelumnya digunakan untuk object detection dengan Tensorflow sedangkan kita di sini akan menggunakan PyTorch Detectron, maka kita tidak perlu memproses data sampai membuat file tfrecord, cukup sampai bagian membuat file csv.

Dataset latihan dapat didownload melalui github dengan menuliskan perintah berikut di google colab. Detail dataset dapat dibaca di file Readme:

! git clone https://github.com/rianrajagede/object-detection.git

2. Instalasi Detectron 2

Sebelum menginstall detectron kita perlu menginstall PyTorch, pyyaml, dan pycocotools dengan versi yang sesuai. Di Google Colab PyTorch sudah otomatis terinstall, kita cukup menginstall 2 package sisanya melalui Google Colab:

! pip install pyyaml==5.1 pycocotools==2.0.1

Kita juga perlu memperhatikan versi PyTorch yang tersedia dan versi Cuda. Hal ini bisa dilakukan dengan menjalankan perintah berikut di Colab:

import torch
print(torch.__version__)

Pada saat tutorial ini ditulis, output dari perintah di atas adalah 1.6.0+cu101 yang artinya terinstall PyTorch versi 1.6.0 dengan Cuda versi 10.1. Selanjutnya kita cukup install Detectron berdasarkan versi yang sesuai, petunjukknya dapat dibaca di link berikut.

! python -m pip install detectron2==0.2.1 -f https://dl.fbaipublicfiles.com/detectron2/wheels/cu101/torch1.6/index.html

3. Menyiapkan DatasetCatalog

Detectron menyimpan dataset pada sebuah object bernama DatasetCatalog. Sebelum memulai training, kita perlu mengconvert dataset kita yang awalnya berbentuk XML ke DatasetCatalog.

DatasetCatalog adalah sebuah list of dictionary dengan setiap elemennya berformat sebagai berikut:

{'annotations':
    [{'bbox': [LIST KOORDINAT BOUNDING BOX 1],
       'bbox_mode': <FORMAT BOUNDING BOX 1>,
       'category_id': LABEL INDEX OBJECT 1},
     {'bbox': [LIST KOORDINAT BOUNDING BOX 2],
       'bbox_mode': <FORMAT BOUNDING BOX 2>,
       'category_id': LABEL INDEX OBJECT 2},
       .... ],
 'file_name': 'PATH KE FILE JPG',
 'height': TINGGI GAMBAR,
 'width': LEBAR GAMBAR,
 'image_id': ID GAMBAR,
}

Code yang diperlukan untuk mengconvert dari CSV dataset kita sebagai berikut (penjelasan dalam bentuk komentar):

# Buat dictionary berisikan nama label dan indexnya
labelmap = {
    "kangaroo" : 0,
    "raccoon" : 1
}

# Buat fungsi get_dicts() untuk mengconvert XML ke DatasetCatalog.
# Parameter settype digunakan untuk membedakan file dataset,
# Karena data test dan data train diperlakukan sama, maka saya
# memilih untuk menggunakan satu fungsi untuk memproses dua 
# DatasetCatalog, yaitu untuk train dan untuk test
def get_dicts(settype):
    if settype=="test":
        csvpath = main_path+"/test_labels.csv"
    else:
        csvpath = main_path+"/train_labels.csv"

    df = pd.read_csv(csvpath).values # load dataset

    dataset_dicts = []
    done = []
    for idx in range(len(df)):
        record = {}
        filename = df[idx, 0]
        record["image_id"] = idx
        record["file_name"] =  main_path+"/"+settype+"/"+filename
        record["width"] = df[idx, 1]
        record["height"] = df[idx, 2]

        if filename in done: # untuk menghindari duplikat
            continue
        done.append(filename)

        objs = []
        for row in df[df[:,0]==filename]: # simpan semua objek
            objs.append({
                    "bbox": [ row[4], row[5], row[6], row[7]],
                    "bbox_mode": BoxMode.XYXY_ABS,
                    "category_id": labelmap[row[3]],
            })
        record["annotations"] = objs
        dataset_dicts.append(record)

    return dataset_dicts

Selanjutnya kita cukup menggunanakan perintah berikut untuk membuat DatasetCatalog dengan nama rk_train dan rk_test. Sekaligus kita juga membuat MetadataCatalog untuk menyimpan informasi objeknya.

DatasetCatalog.register("rk_train", lambda t="train":get_dicts(t))
DatasetCatalog.register("rk_test", lambda t="test":get_dicts(t))
MetadataCatalog.get("rk_train").set(thing_classes=["kangaroo", "raccoon"])
MetadataCatalog.get("rk_test").set(thing_classes=["kangaroo", "raccoon"])

4. Training Model

Dengan menggunakan pretrained model, yang perlu kita lakukan adalah mendownload model dari Model Zoo lalu melakukan sedikit config atau pengaturan. Detail penjelasan pengaturan ini dapat dilihat di dokumentasi resmi Detectron 2.

from detectron2.engine import DefaultTrainer
from detectron2.config import get_cfg

cfg = get_cfg()
pre_mod = "COCO-Detection/faster_rcnn_X_101_32x8d_FPN_3x.yaml"

# pilih dan download model
cfg.merge_from_file(model_zoo.get_config_file(pre_mod))
cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(pre_mod)

# atur data train dan test
cfg.DATASETS.TRAIN = ("rk_train",)
cfg.DATASETS.TEST = ()

# atur pelatihan
cfg.DATALOADER.NUM_WORKERS = 2
cfg.SOLVER.IMS_PER_BATCH = 2
cfg.SOLVER.BASE_LR = 0.005  # learning rate
cfg.SOLVER.MAX_ITER = 100  # banyak iterasi
cfg.MODEL.ROI_HEADS.BATCH_SIZE_PER_IMAGE = 48
cfg.MODEL.ROI_HEADS.NUM_CLASSES = 2

Setelah pengaturan di atas, proses training cukup menjalankan perintah berikut:

# membuat direktori output pelatihan
os.makedirs(cfg.OUTPUT_DIR, exist_ok=True)

trainer = DefaultTrainer(cfg) 
 # resume=False artinya pelatihan baru bukan melanjutkan
trainer.resume_or_load(resume=False)
trainer.train()

Hasil dari proses pelatihan ini akan muncul di folder output. Model akhir bernama model_final.pth

Tampilan proses pelatihan

5. Load Model

Kita bisa gunakan model akhir tersebut untuk mendeteksi citra dengan langkah berikut. Pertama-tama kita load terlebih dahulu model dan beri sedikit pengaturan treshold.

cfg.MODEL.WEIGHTS = os.path.join("output/", "model_final.pth")
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.8  
predictor = DefaultPredictor(cfg)

predictor adalah objek model kita. Untuk melakukan deteksi kita cukup menuliskan perintah berikut:

from detectron2.utils.visualizer import ColorMode

im = cv2.imread("/content/TestImage.png") # load image
outputs = predictor(im) # predict
v = Visualizer(im[:, :, ::-1], metadata=metadata, scale=0.8) # visualisasi
out = v.draw_instance_predictions(outputs["instances"].to("cpu"))
cv2_imshow(out.get_image()[:, :, ::-1])

Variabel outputs yang dihasilkan menyimpan data-data seperti koordinat bounding box, score, dan class object pada gambar sehingga mudah diolah. Untuk visualisasi kita bisa memanfaatkan fungsi Visualizer bawaan Detectron yang dapat langsung menampilkan gambar disertai bounding boxnya seperti di bawah ini:

Sekian tutorialnya, semoga bermanfaat! kode yang kami bahas di artikel ini tersedia di sini.

About the author

Rian Adam

Lecturer at Universitas Islam Indonesia; Machine Learning Enthusiast

View all posts

Leave a Reply