Format Dataset pada Deep Learning ada banyak sekali seperti Pascal VOC, COCO, YOLO, dan Trimap. Semuanya mempunyai kelebihan masing-masing dan mempunyai tujuan khusus. Untuk kasus semantic dan instance segmentation, saya biasanya menggunakan Trimap dan COLO. Sedangkan objek detection menggunakan Pascal VOC dan YOLO. Kalian bisa menggunakan tools annotation seperti LabelImg dan CVAT, roboflow.. Saya sudah pernah mencoba semuanya untuk keperluan khusus
Pascal VOC
Contents
Pascal VOC adalah salah satu format anotasi yang digunakan secara luas dalam computer vision, terutama untuk tugas deteksi objek. Format ini pertama kali diperkenalkan oleh Pascal Visual Object Classes (VOC) Challenge, sebuah kompetisi yang dirancang untuk mengevaluasi model dalam tugas-tugas seperti deteksi objek, segmentasi gambar, dan klasifikasi.
Dalam deteksi objek, format Pascal VOC menyimpan informasi tentang lokasi objek dalam gambar melalui anotasi bounding box serta kategori objek. Format ini menggunakan file XML untuk menyimpan informasi anotasi.
Struktur File Pascal VOC
Setiap file XML Pascal VOC biasanya memiliki struktur dasar sebagai berikut:
<annotation> <folder>nama_folder</folder> <filename>nama_gambar.jpg</filename> <path>path/ke/nama_gambar.jpg</path> <source> <database>Unknown</database> </source> <size> <width>640</width> <height>480</height> <depth>3</depth> </size> <segmented>0</segmented> <object> <name>kategori_objek</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>50</xmin> <ymin>50</ymin> <xmax>400</xmax> <ymax>300</ymax> </bndbox> </object> </annotation>
Penjelasan Elemen-Elemen Utama:
<folder>
: Nama folder tempat gambar disimpan.<filename>
: Nama file gambar.<path>
: Path lengkap ke file gambar.<size>
: Ukuran gambar, termasuk lebar (width
), tinggi (height
), dan jumlah kanal warna (depth
), yang biasanya bernilai 3 untuk gambar RGB.<object>
: Elemen ini berisi informasi tentang setiap objek yang terdeteksi dalam gambar. Jika ada beberapa objek, elemen<object>
ini akan diulang untuk setiap objek.<name>
: Nama atau kelas objek (misalnya, “dog”, “cat”).<pose>
: Pose objek (misalnya, “Left”, “Right”). Biasanya diabaikan atau dibiarkan sebagai “Unspecified”.<truncated>
: Indikator apakah objek terpotong oleh tepi gambar (nilai 0 atau 1).<difficult>
: Indikator kesulitan mendeteksi objek ini (nilai 0 atau 1).<bndbox>
: Koordinat bounding box yang mengelilingi objek.<xmin>
dan<ymin>
adalah koordinat sudut kiri atas bounding box.<xmax>
dan<ymax>
adalah koordinat sudut kanan bawah bounding box.
Contoh Kasus Pascal VOC
Misalkan Anda memiliki gambar berukuran 640×480 piksel yang berisi seekor anjing yang terdeteksi dalam gambar. Berikut adalah contoh anotasi Pascal VOC untuk objek tersebut:
<annotation> <folder>images</folder> <filename>dog.jpg</filename> <path>/home/user/images/dog.jpg</path> <source> <database>Unknown</database> </source> <size> <width>640</width> <height>480</height> <depth>3</depth> </size> <segmented>0</segmented> <object> <name>dog</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <bndbox> <xmin>120</xmin> <ymin>100</ymin> <xmax>500</xmax> <ymax>400</ymax> </bndbox> </object> </annotation>
Pada contoh di atas:
- Gambar tersebut berada dalam folder
images
dan bernamadog.jpg
. - Ukuran gambar adalah 640×480 piksel dengan kedalaman 3 kanal (RGB).
- Objek yang terdeteksi adalah seekor anjing (
dog
) dengan bounding box dari koordinat (120, 100) untuk sudut kiri atas hingga (500, 400) untuk sudut kanan bawah.
Kegunaan Pascal VOC dalam Deteksi Objek
Format Pascal VOC sering digunakan untuk:
- Pelabelan data: Anotasi gambar secara manual atau otomatis.
- Evaluasi model: Format ini digunakan untuk membandingkan prediksi model dengan anotasi ground truth.
- Interoperabilitas: Pascal VOC digunakan oleh berbagai framework deep learning, sehingga memudahkan pertukaran data anotasi antara berbagai alat dan model.
Mari kita coba dengan gambar berikut
dengan file xml nya yaitu
<annotation> <folder></folder> <filename>000090623_jpg.rf.f0956cd698e13eeb4614b8bbf89df3de.jpg</filename> <path>000090623_jpg.rf.f0956cd698e13eeb4614b8bbf89df3de.jpg</path> <source> <database>roboflow.ai</database> </source> <size> <width>416</width> <height>416</height> <depth>3</depth> </size> <segmented>0</segmented> <object> <name>1</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <occluded>0</occluded> <bndbox> <xmin>154</xmin> <xmax>173</xmax> <ymin>116</ymin> <ymax>139</ymax> </bndbox> </object> <object> <name>0</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <occluded>0</occluded> <bndbox> <xmin>174</xmin> <xmax>195</xmax> <ymin>116</ymin> <ymax>139</ymax> </bndbox> </object> <object> <name>9</name> <pose>Unspecified</pose> <truncated>0</truncated> <difficult>0</difficult> <occluded>0</occluded> <bndbox> <xmin>209</xmin> <xmax>230</xmax> <ymin>124</ymin> <ymax>148</ymax> </bndbox> </object> </annotation>
kita baca dengan kode berikut
from xml.etree import ElementTree as et import cv2 import numpy as np from matplotlib import pyplot as plt image = cv2.imread('000090623_jpg.rf.f0956cd698e13eeb4614b8bbf89df3de.jpg',1) annot_file_path = '000090623_jpg.rf.f0956cd698e13eeb4614b8bbf89df3de.xml' boxes = [] labels = [] tree = et.parse(annot_file_path) root = tree.getroot() # box coordinates for xml files are extracted and corrected for image size given for member in root.findall('object'): # map the current object name to `classes` list to get... # ... the label index and append to `labels` list labels.append(int(member.find('name').text)) # xmin = left corner x-coordinates xmin = int(member.find('bndbox').find('xmin').text) # xmax = right corner x-coordinates xmax = int(member.find('bndbox').find('xmax').text) # ymin = left corner y-coordinates ymin = int(member.find('bndbox').find('ymin').text) # ymax = right corner y-coordinates ymax = int(member.find('bndbox').find('ymax').text) boxes.append([xmin, ymin, xmax, ymax]) for j, box in enumerate(boxes): class_name = str(labels[j]) color = [255,255,1] cv2.rectangle(image, (int(box[0]), int(box[1])), (int(box[2]), int(box[3])), color, 1) cv2.putText(image, class_name, (int(box[0]), int(box[1]-5)), cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 1, lineType=cv2.LINE_AA) plt.figure(figsize=(16,8)) plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)) plt.show()
hasilnya
Penjelasan Format COCO
COCO (Common Objects in Context) adalah salah satu format anotasi yang paling populer dalam computer vision, terutama untuk tugas-tugas seperti deteksi objek, segmentasi instance, segmentasi panoptic, dan captioning gambar. Format COCO dikembangkan sebagai bagian dari COCO dataset, yang terkenal karena menyediakan data yang kaya dan beragam untuk melatih model deep learning.
Format COCO menggunakan file JSON untuk menyimpan anotasi, yang mencakup informasi mengenai gambar, kategori objek, anotasi bounding box, segmentasi, dan lainnya. File JSON ini sangat terstruktur dan fleksibel, memungkinkan penyimpanan berbagai jenis informasi dalam satu file.
Struktur File COCO
Struktur file COCO JSON terdiri dari beberapa bagian utama:
info
: Berisi informasi umum tentang dataset, seperti deskripsi, versi, tahun, dan URL.licenses
: Informasi tentang lisensi yang berlaku untuk dataset.images
: Daftar gambar yang ada dalam dataset, masing-masing dengan ID unik, file name, dimensi gambar, dan URL (jika tersedia).annotations
: Daftar anotasi untuk setiap objek dalam gambar. Setiap anotasi berisi ID unik, ID gambar terkait, ID kategori, koordinat bounding box, data segmentasi (jika ada), dan informasi lainnya.categories
: Daftar kategori objek yang ada dalam dataset, masing-masing dengan ID unik dan nama.
Contoh File COCO JSON
Berikut adalah contoh sederhana dari file JSON dalam format COCO:
{ "info": { "description": "Example Dataset", "version": "1.0", "year": 2023, "contributor": "Dataset Creator", "date_created": "2023-08-17" }, "licenses": [ { "id": 1, "name": "Creative Commons Attribution", "url": "http://creativecommons.org/licenses/by/4.0/" } ], "images": [ { "id": 1, "width": 640, "height": 480, "file_name": "image1.jpg", "license": 1, "date_captured": "2023-08-17" } ], "annotations": [ { "id": 1, "image_id": 1, "category_id": 1, "bbox": [120, 100, 380, 300], "area": 114000, "iscrowd": 0, "segmentation": [[120, 100, 500, 100, 500, 400, 120, 400]] } ], "categories": [ { "id": 1, "name": "dog", "supercategory": "animal" } ] }
Penjelasan Elemen-Elemen Utama
info
: Berisi metadata tentang dataset seperti deskripsi, versi, tahun, kontributor, dan tanggal pembuatan dataset.licenses
: Berisi informasi lisensi yang berlaku untuk gambar dalam dataset, seperti nama lisensi dan URL yang mengarah ke detail lisensi tersebut.images
: Berisi daftar gambar dalam dataset. Setiap entri gambar mencakup:id
: ID unik untuk setiap gambar.width
danheight
: Dimensi gambar.file_name
: Nama file gambar.license
: ID lisensi yang berlaku untuk gambar tersebut.date_captured
: Tanggal kapan gambar tersebut diambil.
annotations
: Berisi daftar anotasi untuk setiap objek dalam gambar. Setiap entri anotasi mencakup:id
: ID unik untuk setiap anotasi.image_id
: ID gambar yang terkait dengan anotasi ini.category_id
: ID kategori objek (misalnya, “dog”).bbox
: Koordinat bounding box dalam format [xmin, ymin, width, height].area
: Luas dari bounding box.iscrowd
: Indikator apakah objek ini bagian dari kelompok yang sulit diidentifikasi secara individual (misalnya, kerumunan orang).segmentation
: Informasi segmentasi untuk objek, berupa daftar koordinat yang membentuk poligon (bila tugas segmentasi dilakukan).
categories
: Berisi daftar kategori objek yang ada dalam dataset. Setiap entri kategori mencakup:id
: ID unik untuk kategori tersebut.name
: Nama kategori (misalnya, “dog”).supercategory
: Kategori umum yang mencakup kategori ini (misalnya, “animal”).
Kegunaan Format COCO
Format COCO sangat fleksibel dan mendukung berbagai jenis anotasi, membuatnya populer di kalangan peneliti dan praktisi yang bekerja dengan tugas-tugas computer vision seperti:
- Deteksi Objek: Menyediakan anotasi bounding box yang mencakup lokasi objek dalam gambar.
- Segmentasi Instance: Menyediakan data segmentasi yang memungkinkan model untuk mengenali setiap piksel objek.
- Segmentasi Panoptic: Mendukung tugas segmentasi panoptic di mana setiap piksel dalam gambar diberi label kategori.
- Captioning Gambar: Dapat diadaptasi untuk tugas captioning, di mana setiap gambar diberi deskripsi teks.
Mari kita gunakan dataset berikut ini https://www.kaggle.com/datasets/sovitrath/microcontroller-instance-segmentation-json-format#
Saya akan membuat dataset dari pytorch dengan contoh kasus Mask RCNN. Berikut class Dataset yang akan kita gunakan
import torch import torch.nn as nn import torchvision import torchvision.transforms as transforms import os import numpy as np import cv2 from pycocotools.coco import COCO from PIL import Image from matplotlib import pyplot as plt from torch.utils.data import Dataset, DataLoader from PIL import Image, ImageFont, ImageDraw class Datasetku(Dataset): def __init__(self, root, annotation, transforms=None): self.root = root self.transforms = transforms self.coco = COCO(annotation) self.ids = list(sorted(self.coco.imgs.keys())) def __getitem__(self, index): coco = self.coco img_id = self.ids[index] ann_ids = coco.getAnnIds(imgIds=img_id) coco_annotation = coco.loadAnns(ann_ids) path = coco.loadImgs(img_id)[0]['file_name'] # pakai opencv saja # img = cv2.imread(os.path.join(self.root, path)) # img = img/255.0 # agar sama dengan img = Image.open(os.path.join(self.root, path)) # Bounding boxes for objects # yang perlu kalian ketahui bahwa # coco format, bbox = [xmin, ymin, width, height] # pytorch menggunakan format [xmin, ymin, xmax, ymax] num_objs = len(coco_annotation) boxes = [] areas = [] labels = torch.ones((num_objs,), dtype=torch.int64) for i in range(num_objs): # untuk BBOX xmin = coco_annotation[i]['bbox'][0] ymin = coco_annotation[i]['bbox'][1] xmax = xmin + coco_annotation[i]['bbox'][2] ymax = ymin + coco_annotation[i]['bbox'][3] # format dibawah ini jika akan digunakan untuk mask RCNN boxes.append([xmin, ymin, xmax, ymax]) # width = coco_annotation[i]['bbox'][2] # height = coco_annotation[i]['bbox'][3] # format dibawah ini untuk augmentation saja pada albumentation # boxes.append([xmin, ymin, width, height]) # untuk labels/category label = coco_annotation[i]['category_id'] labels[i] = label # untuk area areas.append(coco_annotation[i]['area']) boxes = torch.as_tensor(boxes, dtype=torch.float32) areas = torch.as_tensor(areas, dtype=torch.float32) img_id = torch.tensor([img_id]) iscrowd = torch.zeros((num_objs,), dtype=torch.int64) # mask target masks = [coco.annToMask(ann) for ann in coco_annotation] masks = torch.as_tensor(masks, dtype=torch.float32) # Annotation is in dictionary format records = {} records["boxes"] = boxes records["labels"] = labels records["image_id"] = img_id records["area"] = areas records["iscrowd"] = iscrowd records["masks"] = masks if self.transforms is not None: img = self.transforms(img) return img, records def __len__(self): return len(self.ids) folder_root = 'train2017' annotation = 'annotations/instances_train2017.json' image_transform = torchvision.transforms.Compose( [transforms.ToTensor(), # transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) dataset = Datasetku(folder_root, annotation,transforms = image_transform) kategori = dataset.coco.cats
Kemudian kita buat visualisasinya (untuk file fontnya kalian downloa dulu saja Arial.ttf)
fontsize = 24 font = ImageFont.truetype("Arial.ttf", fontsize) k = 75 inputs,targets = dataset.__getitem__(k) img = transforms.ToPILImage()(inputs) draw = ImageDraw.Draw(img) for index,bb in enumerate(targets['boxes']): kelas = category[targets['labels'][index].item()]['name'] draw.rectangle(((bb[0],bb[1]), (bb[2],bb[3]))) draw.text((bb[0], bb[1]), # Coordinates kelas, # Text (255, 255, 0),font # Color ) blank = torch.zeros([600,800]) for b in targets['masks']: blank += b plt.figure(figsize=(16,8)) plt.subplot(1,2,1),plt.imshow(img),plt.title('Bbox') plt.subplot(1,2,2),plt.imshow(blank.detach().numpy()),plt.title('Masking') plt.show()
atau juga bisa menggunakan tools pycocotools
import matplotlib.pyplot as plt import numpy as np import skimage.io as io import numpy as np from pycocotools.coco import COCO from pycocotools.cocoeval import COCOeval annFile = 'annotations/instances_train2017.json' coco = COCO(annFile) folder_root = 'train2017' index = 75 img = coco.loadImgs(index)[0] print(img['file_name']) annIds = coco.getAnnIds(index, iscrowd=False) anns = coco.loadAnns(annIds) # tampilkan gambar image = io.imread(root+img['file_name']) plt.imshow(image) plt.axis('off') # jangan lupa annotasinya annIds = coco.getAnnIds(imgIds=img['id'], iscrowd=False) anns = coco.loadAnns(annIds) coco.showAnns(anns, draw_bbox=True) plt.show()
Penjelasan Format YOLO
YOLO (You Only Look Once) adalah salah satu algoritma deteksi objek yang paling populer dan efisien. YOLO bekerja dengan cara mengubah masalah deteksi objek menjadi masalah regresi tunggal, di mana jaringan saraf langsung memprediksi bounding box dan kelas objek dalam satu langkah. Format anotasi YOLO adalah salah satu komponen penting dari algoritma ini, digunakan untuk memberikan informasi mengenai posisi dan kelas objek dalam gambar.
Format YOLO sangat sederhana dan ringan, menggunakan file teks (.txt) untuk menyimpan informasi anotasi. Setiap gambar memiliki satu file anotasi dengan nama yang sama tetapi dengan ekstensi .txt
. File ini berisi satu baris untuk setiap objek yang ada dalam gambar.
Struktur Anotasi YOLO
Setiap baris dalam file anotasi YOLO terdiri dari lima elemen yang dipisahkan oleh spasi:
<class_id> <x_center> <y_center> <width> <height>
<class_id>
: ID dari kelas objek. ID ini biasanya dimulai dari 0 dan sesuai dengan urutan kelas yang didefinisikan dalam file kelas (misalnya,0
untuk “dog”,1
untuk “cat”, dll.).<x_center>
: Koordinat x dari titik tengah bounding box, dinyatakan dalam skala relatif terhadap lebar gambar (nilai antara 0 dan 1).<y_center>
: Koordinat y dari titik tengah bounding box, dinyatakan dalam skala relatif terhadap tinggi gambar (nilai antara 0 dan 1).<width>
: Lebar bounding box, dinyatakan dalam skala relatif terhadap lebar gambar (nilai antara 0 dan 1).<height>
: Tinggi bounding box, dinyatakan dalam skala relatif terhadap tinggi gambar (nilai antara 0 dan 1).
Contoh File Anotasi YOLO
Misalkan kita memiliki gambar berukuran 640×480 piksel yang mengandung seekor anjing, dengan bounding box yang mencakup sebagian besar gambar. Berikut adalah contoh anotasi dalam format YOLO:
0 0.5 0.5 0.625 0.625
Penjelasan:
0
: Merupakanclass_id
untuk objek tersebut. Jika “dog” adalah kelas pertama dalam daftar kelas, makaclass_id
untuk “dog” adalah 0.0.5 0.5
: Koordinat titik tengah bounding box (di tengah gambar) dalam skala relatif. Karena titik tengahnya berada di tengah gambar, maka x_center dan y_center adalah 0.5.0.625 0.625
: Lebar dan tinggi bounding box, yang dalam hal ini menutupi 62.5% dari lebar dan tinggi gambar.
Jika gambar tersebut memiliki lebih dari satu objek, maka setiap objek akan memiliki baris tersendiri dalam file anotasi. Misalnya, jika gambar juga mengandung seekor kucing:
0 0.5 0.5 0.625 0.625 1 0.3 0.4 0.2 0.3
Kelebihan Format YOLO
- Kesederhanaan: Format YOLO sangat sederhana dan mudah diimplementasikan. File teks yang dihasilkan ringan dan mudah dibaca.
- Efisiensi: Anotasi dalam format YOLO dioptimalkan untuk digunakan dalam model YOLO, yang dikenal cepat dan efisien dalam mendeteksi objek.
- Fleksibilitas: Format ini dapat digunakan dengan berbagai macam jenis objek dan ukuran gambar, selama semua koordinat dan dimensi dinyatakan dalam skala relatif.
Sedang dicari contoh dataset nya
Penjelasan Format Trimap
Trimap adalah format anotasi yang digunakan dalam tugas segmentasi gambar, terutama dalam konteks image matting. Image matting adalah proses pemisahan objek latar depan dari latar belakang dalam sebuah gambar, yang sering digunakan dalam pengeditan gambar, produksi film, dan aplikasi augmented reality. Trimap membantu dalam mengidentifikasi dengan tepat bagian-bagian dari gambar yang termasuk ke dalam latar depan, latar belakang, atau area yang belum ditentukan (ambiguous).
Struktur dan Penggunaan Trimap
Trimap adalah gambar anotasi yang memiliki tiga kategori utama:
- Latar Depan (Foreground): Area ini secara pasti ditentukan sebagai bagian dari objek yang ingin dipisahkan atau diekstraksi dari gambar. Biasanya diberi nilai 255 atau warna putih.
- Latar Belakang (Background): Area ini secara pasti ditentukan sebagai bagian dari latar belakang gambar, yang tidak termasuk objek utama. Biasanya diberi nilai 0 atau warna hitam.
- Area Ambigu (Unknown/Transition Area): Area ini adalah bagian dari gambar yang belum pasti atau ambigu, di mana algoritma matting harus memutuskan apakah area tersebut termasuk dalam latar depan atau latar belakang. Biasanya diberi nilai 128 atau warna abu-abu.
Contoh Penggunaan Trimap
Misalkan kita memiliki sebuah gambar di mana kita ingin mengekstraksi objek orang dari latar belakangnya. Trimap untuk gambar tersebut akan terlihat seperti ini:
- Latar Depan (Putih, 255): Bagian gambar yang pasti merupakan bagian dari orang tersebut (misalnya, wajah, pakaian).
- Latar Belakang (Hitam, 0): Bagian gambar yang pasti merupakan latar belakang (misalnya, langit, tanah).
- Area Ambigu (Abu-abu, 128): Bagian di sekitar tepi orang, di mana mungkin terdapat campuran latar depan dan latar belakang (misalnya, rambut yang tipis atau tepi pakaian).
Cara Membuat Trimap
Trimap bisa dibuat secara manual atau otomatis:
- Manual: Dengan menggunakan perangkat lunak pengeditan gambar seperti Adobe Photoshop atau GIMP, Anda bisa melukis pada gambar dengan menggunakan tiga warna (putih, hitam, abu-abu) untuk menandai area foreground, background, dan area yang ambigu.
- Otomatis: Algoritma atau perangkat lunak khusus dapat menghasilkan trimap dari sebuah gambar atau dari anotasi lain seperti mask. Dalam beberapa metode, dilasi (dilation) dan erosi (erosion) diterapkan pada mask objek untuk memperluas atau mengurangi area foreground dan background sehingga area ambigu dapat terbentuk secara otomatis.
Perhatikan gambar berikut (mungkin gambar dibawah ini tidak nampak di browser karena pakai format *.tiff 16 bit)
Gambar dibawah ini juga tidak akan tampak di browser, karena format tiff 16 bit
Pada gambar mask/target berisi nilai pixel sehingga tidak akan nampak, mari kita perjelas dengan kode berikut
import numpy as np import cv2 from matplotlib import pyplot as plt image = cv2.imread('/Users/user/Desktop/agumentasi Albumentation/Trimap/images/0bda515e370294ed94efd36bd53782288acacb040c171df2ed97fd691fc9d8fe.tif',cv2.IMREAD_UNCHANGED) mask = cv2.imread('/Users/user/Desktop/agumentasi Albumentation/Trimap/masks/0bda515e370294ed94efd36bd53782288acacb040c171df2ed97fd691fc9d8fe.tif',cv2.IMREAD_UNCHANGED) def coloring(a): b = np.zeros([a.shape[0],a.shape[1],3]) for k in range(1,int(a.max())): color = np.uint8(np.random.randint(0, 255, 3)).tolist() b[a==k] = color return np.uint8(b) plt.figure(figsize=(16,8)) plt.subplot(1,3,1),plt.imshow(image,cmap='gray'),plt.title('image') plt.subplot(1,3,2),plt.imshow(mask,cmap='gray'),plt.title('mask') plt.subplot(1,3,3),plt.imshow(coloring(mask)),plt.title('trimap') plt.show()
Hasilnya yaitu kita buat coloring untuk memvisualisasikan mask sebagai target instance segmentation
Format trimap banyak digunakan untuk instance segmentation terutama untuk yang sejenis dan nempel satu sama lain.