# Segmentasi Gambar

Model segmentasi citra memisahkan area yang sesuai dengan berbagai area kepentingan dalam sebuah citra. Model-model ini bekerja dengan cara memberikan label pada setiap piksel. Terdapat beberapa jenis segmentasi: segmentasi semantik, segmentasi instans, dan segmentasi panoptik.

Dalam panduan ini, kami akan:

1. [Lihat berbagai jenis segmentasi](#types-of-segmentation).
2. [Mempunyai contoh fine-tuning end-to-end untuk segmentasi semantik](#fine-tuning-a-model-for-segmentation).

Sebelum memulai, pastikan Anda telah menginstal semua pustaka yang diperlukan:

```py
# uncomment to install the necessary libraries
!pip install -q datasets transformers evaluate accelerate trackio
```

Kami menyarankan Anda untuk masuk ke akun Hugging Face Anda agar dapat mengunggah dan membagikan model Anda dengan komunitas. Saat diminta, masukkan token Anda untuk masuk:

```py
>>> from huggingface_hub import notebook_login

>>> notebook_login()
```

## Jenis-jenis Segmentasi

Segmentasi semantik memberikan label atau kelas pada setiap piksel dalam sebuah gambar. Mari kita lihat keluaran dari model segmentasi semantik. Model ini akan memberikan kelas yang sama untuk setiap instans objek yang ditemukan dalam gambar, misalnya, semua kucing akan diberi label "cat" alih-alih "cat-1", "cat-2". Kita dapat menggunakan pipeline segmentasi gambar dari transformers untuk melakukan inferensi model segmentasi semantik dengan cepat. Mari kita lihat gambar contohnya.

```python
from transformers import pipeline
from PIL import Image
import requests

url = "https://huggingface.co/datasets/huggingface/documentation-images/resolve/main/transformers/tasks/segmentation_input.jpg"
image = Image.open(requests.get(url, stream=True).raw)
image
```

     

Kami akan menggunakan [nvidia/segformer-b1-finetuned-cityscapes-1024-1024](https://huggingface.co/nvidia/segformer-b1-finetuned-cityscapes-1024-1024).

```python
semantic_segmentation = pipeline("image-segmentation", "nvidia/segformer-b1-finetuned-cityscapes-1024-1024")
results = semantic_segmentation(image)
results
```

Output dari pipeline segmentasi mencakup mask untuk setiap kelas yang diprediksi.

```bash
[{'score': None,
  'label': 'road',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': None,
  'label': 'sidewalk',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': None,
  'label': 'building',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': None,
  'label': 'wall',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': None,
  'label': 'pole',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': None,
  'label': 'traffic sign',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': None,
  'label': 'vegetation',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': None,
  'label': 'terrain',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': None,
  'label': 'sky',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': None,
  'label': 'car',
  'mask': <PIL.Image.Image image mode=L size=612x415>}]
```

Jika kita melihat mask untuk kelas mobil, kita dapat melihat bahwa setiap mobil diklasifikasikan dengan mask yang sama.

```python
results[-1]["mask"]
```

     

Dalam segmentasi instance, tujuannya bukan untuk mengklasifikasikan setiap piksel, melainkan untuk memprediksi mask untuk **setiap instance dari sebuah objek** dalam gambar tertentu. Cara kerjanya sangat mirip dengan deteksi objek, di mana terdapat bounding box untuk setiap instance, namun di sini digunakan segmentation mask sebagai gantinya. Kita akan menggunakan [facebook/mask2former-swin-large-cityscapes-instance](https://huggingface.co/facebook/mask2former-swin-large-cityscapes-instance) untuk ini.

```python
instance_segmentation = pipeline("image-segmentation", "facebook/mask2former-swin-large-cityscapes-instance")
results = instance_segmentation(image)
results
```

Seperti yang dapat Anda lihat di bawah, terdapat beberapa mobil yang diklasifikasikan, dan tidak ada klasifikasi untuk piksel selain piksel yang merupakan bagian dari instans mobil dan orang.

```bash
[{'score': 0.999944,
  'label': 'car',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': 0.999945,
  'label': 'car',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': 0.999652,
  'label': 'car',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': 0.903529,
  'label': 'person',
  'mask': <PIL.Image.Image image mode=L size=612x415>}]
```

Melihat salah satu masker mobil di bawah ini.

```python
results[2]["mask"]
```

     

Segmentasi panoptik menggabungkan segmentasi semantik dan segmentasi instans, di mana setiap piksel diklasifikasikan ke dalam sebuah kelas dan sebuah instans dari kelas tersebut, dengan adanya beberapa mask untuk setiap instans dari suatu kelas. Kita dapat menggunakan [facebook/mask2former-swin-large-cityscapes-panoptic](https://huggingface.co/facebook/mask2former-swin-large-cityscapes-panoptic) untuk ini.

```python
panoptic_segmentation = pipeline("image-segmentation", "facebook/mask2former-swin-large-cityscapes-panoptic")
results = panoptic_segmentation(image)
results
```

Seperti yang dapat Anda lihat di bawah, kita memiliki lebih banyak kelas. Nantinya kita akan mengilustrasikan bahwa setiap piksel diklasifikasikan ke salah satu dari kelas tersebut.

```bash
[{'score': 0.999981,
  'label': 'car',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': 0.999958,
  'label': 'car',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': 0.99997,
  'label': 'vegetation',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': 0.999575,
  'label': 'pole',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': 0.999958,
  'label': 'building',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': 0.999634,
  'label': 'road',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': 0.996092,
  'label': 'sidewalk',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': 0.999221,
  'label': 'car',
  'mask': <PIL.Image.Image image mode=L size=612x415>},
 {'score': 0.99987,
  'label': 'sky',
  'mask': <PIL.Image.Image image mode=L size=612x415>}]
```

Mari kita lakukan perbandingan berdampingan untuk semua jenis segmentasi.

     

Melihat berbagai jenis segmentasi, mari kita mendalami penyesuaian halus (fine-tuning) model untuk segmentasi semantik.

Aplikasi dunia nyata yang umum dari segmentasi semantik meliputi pelatihan mobil otonom untuk mengidentifikasi pejalan kaki dan informasi lalu lintas penting, mengidentifikasi sel dan kelainan pada citra medis, serta memantau perubahan lingkungan dari citra satelit.

## Menyesuaikan Model untuk Segmentasi

Kita akan:

1. Lakukan finetune [SegFormer](../model_doc/segformer#segformer) pada dataset [SceneParse150](https://huggingface.co/datasets/merve/scene_parse_150).
2. Gunakan model yang telah Anda fine-tune untuk inferensi.

Untuk melihat semua arsitektur dan checkpoint yang kompatibel dengan tugas ini, kami menyarankan untuk memeriksa [halaman tugas](https://huggingface.co/tasks/image-segmentation)

### Muat dataset SceneParse150

Mulai dengan memuat subset yang lebih kecil dari dataset SceneParse150 dari pustaka 🤗 Datasets. Hal ini akan memberi Anda kesempatan untuk bereksperimen dan memastikan semuanya berfungsi sebelum menghabiskan lebih banyak waktu untuk pelatihan pada dataset lengkap.

```py
>>> from datasets import load_dataset

>>> ds = load_dataset("merve/scene_parse_150", split="train[:50]")
```

Pisahkan split `train` dari dataset menjadi set train dan test dengan metode [train_test_split](https://huggingface.co/docs/datasets/main/en/package_reference/main_classes#datasets.Dataset.train_test_split):

```py
>>> ds = ds.train_test_split(test_size=0.2)
>>> train_ds = ds["train"]
>>> test_ds = ds["test"]
```

Lalu, lihatlah sebuah contoh:

```py
>>> train_ds[0]
{'image': <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=512x683 at 0x7F9B0C201F90>,
 'annotation': <PIL.PngImagePlugin.PngImageFile image mode=L size=512x683 at 0x7F9B0C201DD0>,
 'scene_category': 368}

# view the image
>>> train_ds[0]["image"]
```

- `image`: gambar PIL dari adegan tersebut.
- `annotation`: gambar PIL dari peta segmentasi, yang juga merupakan target model.
- `scene_category`: id kategori yang menggambarkan adegan gambar seperti "kitchen" atau "office". Dalam panduan ini, Anda hanya membutuhkan `image` dan `annotation`, yang keduanya merupakan gambar PIL.

Anda juga perlu membuat kamus yang memetakan id label ke kelas label, yang akan berguna saat Anda mengatur model nanti. Unduh pemetaan dari Hub dan buat kamus `id2label` dan `label2id`:

```py
>>> import json
>>> from pathlib import Path
>>> from huggingface_hub import hf_hub_download

>>> repo_id = "huggingface/label-files"
>>> filename = "ade20k-id2label.json"
>>> id2label = json.loads(Path(hf_hub_download(repo_id, filename, repo_type="dataset")).read_text())
>>> id2label = {int(k): v for k, v in id2label.items()}
>>> label2id = {v: k for k, v in id2label.items()}
>>> num_labels = len(id2label)
```

### Pra-pemrosesan

Langkah selanjutnya adalah memuat pemroses gambar SegFormer untuk menyiapkan gambar dan anotasi bagi model. Beberapa dataset, seperti yang ini, menggunakan indeks nol sebagai kelas latar belakang. Namun, kelas latar belakang sebenarnya tidak termasuk dalam 150 kelas, sehingga Anda perlu mengatur `do_reduce_labels=True` untuk mengurangi satu dari semua label. Indeks nol diganti dengan `255` sehingga diabaikan oleh fungsi kerugian SegFormer:

```py
>>> from transformers import AutoImageProcessor

>>> checkpoint = "nvidia/mit-b0"
>>> image_processor = AutoImageProcessor.from_pretrained(checkpoint, do_reduce_labels=True)
```

Umumnya, beberapa augmentasi data diterapkan pada dataset gambar untuk membuat model lebih tahan terhadap overfitting. Dalam panduan ini, Anda akan menggunakan fungsi [`ColorJitter`](https://pytorch.org/vision/stable/generated/torchvision.transforms.ColorJitter.html) dari [torchvision](https://pytorch.org/vision/stable/index.html) untuk mengubah properti warna gambar secara acak, tetapi Anda juga dapat menggunakan pustaka gambar apa pun yang Anda sukai.

```py
>>> from torchvision.transforms import ColorJitter

>>> jitter = ColorJitter(brightness=0.25, contrast=0.25, saturation=0.25, hue=0.1)
```

Sekarang buat dua fungsi pra-pemrosesan untuk menyiapkan gambar dan anotasi bagi model. Fungsi-fungsi ini mengonversi gambar menjadi `pixel_values` dan anotasi menjadi `labels`. Untuk set pelatihan, `jitter` diterapkan sebelum memberikan gambar ke image processor. Untuk set pengujian, image processor memotong dan menormalisasi `images`, serta hanya memotong `labels` karena tidak ada augmentasi data yang diterapkan selama pengujian.

```py
>>> def train_transforms(example_batch):
...     images = [jitter(x) for x in example_batch["image"]]
...     labels = [x for x in example_batch["annotation"]]
...     inputs = image_processor(images, labels)
...     return inputs

>>> def val_transforms(example_batch):
...     images = [x for x in example_batch["image"]]
...     labels = [x for x in example_batch["annotation"]]
...     inputs = image_processor(images, labels)
...     return inputs
```

Untuk menerapkan `jitter` ke seluruh dataset, gunakan fungsi [set_transform](https://huggingface.co/docs/datasets/main/en/package_reference/main_classes#datasets.Dataset.set_transform) dari 🤗 Datasets. Transformasi diterapkan secara langsung (on the fly) sehingga lebih cepat dan menghemat ruang disk:

```py
>>> train_ds.set_transform(train_transforms)
>>> test_ds.set_transform(val_transforms)
```

### Evaluasi

Termasuk metrik selama pelatihan sering kali membantu untuk mengevaluasi kinerja model Anda. Anda dapat dengan cepat memuat metode evaluasi dengan pustaka 🤗 [Evaluate](https://huggingface.co/docs/evaluate/index). Untuk tugas ini, muat metrik [mean Intersection over Union](https://huggingface.co/spaces/evaluate-metric/accuracy) (IoU) (lihat [quick tour](https://huggingface.co/docs/evaluate/a_quick_tour) 🤗 Evaluate untuk mempelajari lebih lanjut tentang cara memuat dan menghitung metrik):

```py
>>> import evaluate

>>> metric = evaluate.load("mean_iou")
```

Lalu buat fungsi untuk [menghitung](https://huggingface.co/docs/evaluate/main/en/package_reference/main_classes#evaluate.EvaluationModule.compute) metrik. Prediksi Anda perlu dikonversi menjadi logits terlebih dahulu, lalu di-reshape agar sesuai dengan ukuran label sebelum Anda dapat memanggil [compute](https://huggingface.co/docs/evaluate/main/en/package_reference/main_classes#evaluate.EvaluationModule.compute):

```py
>>> import numpy as np
>>> import torch
>>> from torch import nn

>>> def compute_metrics(eval_pred):
...     with torch.no_grad():
...         logits, labels = eval_pred
...         logits_tensor = torch.from_numpy(logits)
...         logits_tensor = nn.functional.interpolate(
...             logits_tensor,
...             size=labels.shape[-2:],
...             mode="bilinear",
...             align_corners=False,
...         ).argmax(dim=1)

...         pred_labels = logits_tensor.detach().cpu().numpy()
...         metrics = metric.compute(
...             predictions=pred_labels,
...             references=labels,
...             num_labels=num_labels,
...             ignore_index=255,
...             reduce_labels=False,
...         )
...         for key, value in metrics.items():
...             if isinstance(value, np.ndarray):
...                 metrics[key] = value.tolist()
...         return metrics
```

Fungsi `compute_metrics` Anda sudah siap digunakan, dan Anda akan kembali ke fungsi ini saat menyiapkan pelatihan.

### Latih

Jika Anda belum familiar dengan finetuning model menggunakan [Trainer](/docs/transformers/main/id/main_classes/trainer#transformers.Trainer), silakan lihat tutorial dasar [di sini](../training)!

Anda siap untuk mulai melatih model Anda sekarang! Muat SegFormer dengan [AutoModelForSemanticSegmentation](/docs/transformers/main/id/model_doc/auto#transformers.AutoModelForSemanticSegmentation), dan berikan model pemetaan antara id label dan kelas label:

```py
>>> from transformers import AutoModelForSemanticSegmentation, TrainingArguments, Trainer

>>> model = AutoModelForSemanticSegmentation.from_pretrained(checkpoint, id2label=id2label, label2id=label2id)
```

Pada titik ini, hanya tersisa tiga langkah:

1. Definisikan hiperparameter pelatihan Anda di [TrainingArguments](/docs/transformers/main/id/main_classes/trainer#transformers.TrainingArguments). Penting untuk tidak menghapus kolom yang tidak digunakan karena hal ini akan membuang kolom `image`. Tanpa kolom `image`, Anda tidak dapat membuat `pixel_values`. Atur `remove_unused_columns=False` untuk mencegah perilaku ini! Parameter wajib lainnya adalah `output_dir` yang menentukan di mana model Anda disimpan. Anda akan mendorong model ini ke Hub dengan mengatur `push_to_hub=True` (Anda perlu masuk ke Hugging Face untuk mengunggah model Anda). Di akhir setiap epoch, [Trainer](/docs/transformers/main/id/main_classes/trainer#transformers.Trainer) akan mengevaluasi metrik IoU dan menyimpan checkpoint pelatihan.
2. Lewatkan argumen pelatihan ke [Trainer](/docs/transformers/main/id/main_classes/trainer#transformers.Trainer) bersama dengan model, dataset, tokenizer, data collator, dan fungsi `compute_metrics`.
3. Panggil [train()](/docs/transformers/main/id/main_classes/trainer#transformers.Trainer.train) untuk melakukan finetuning pada model Anda.

```py
>>> training_args = TrainingArguments(
...     output_dir="segformer-b0-scene-parse-150",
...     learning_rate=6e-5,
...     num_train_epochs=50,
...     per_device_train_batch_size=2,
...     per_device_eval_batch_size=2,
...     save_total_limit=3,
...     eval_strategy="steps",
...     save_strategy="steps",
...     save_steps=20,
...     eval_steps=20,
...     logging_steps=1,
...     report_to="trackio",
...     run_name="scene-parse-150",
...     eval_accumulation_steps=5,
...     remove_unused_columns=False,
...     push_to_hub=True,
... )

>>> trainer = Trainer(
...     model=model,
...     args=training_args,
...     train_dataset=train_ds,
...     eval_dataset=test_ds,
...     compute_metrics=compute_metrics,
... )

>>> trainer.train()
```

Setelah pelatihan selesai, bagikan model Anda ke Hub dengan metode [push_to_hub()](/docs/transformers/main/id/main_classes/trainer#transformers.Trainer.push_to_hub) agar semua orang dapat menggunakan model Anda:

```py
>>> trainer.push_to_hub()
```

### Inferensi

Bagus, sekarang setelah Anda melakukan penyesuaian halus pada model, Anda dapat menggunakannya untuk inferensi!

Muat ulang dataset dan muat gambar untuk inferensi.

```py
>>> from datasets import load_dataset

>>> ds = load_dataset("merve/scene_parse_150", split="train[:50]")
>>> ds = ds.train_test_split(test_size=0.2)
>>> test_ds = ds["test"]
>>> image = ds["test"][0]["image"]
>>> image
```

    

Sekarang kita akan melihat cara melakukan inferensi tanpa pipeline. Proses gambar dengan image processor dan letakkan `pixel_values` di GPU:

```py
>>> from accelerate import Accelerator
>>> device = Accelerator().device
>>> encoding = image_processor(image, return_tensors="pt")
>>> pixel_values = encoding.pixel_values.to(device)
```

Lewatkan input Anda ke model dan kembalikan `logits`:

```py
>>> outputs = model(pixel_values=pixel_values)
>>> logits = outputs.logits.cpu()
```

Selanjutnya, skala ulang logits ke ukuran gambar asli:

```py
>>> upsampled_logits = nn.functional.interpolate(
...     logits,
...     size=image.size[::-1],
...     mode="bilinear",
...     align_corners=False,
... )

>>> pred_seg = upsampled_logits.argmax(dim=1)[0]
```

Untuk memvisualisasikan hasilnya, muat [palet warna dataset](https://github.com/tensorflow/models/blob/3f1ca33afe3c1631b733ea7e40c294273b9e406d/research/deeplab/utils/get_dataset_colormap.py#L51) sebagai `ade_palette()` yang memetakan setiap kelas ke nilai RGB-nya.

```py
def ade_palette():
  return np.asarray([
      [0, 0, 0],
      [120, 120, 120],
      [180, 120, 120],
      [6, 230, 230],
      [80, 50, 50],
      [4, 200, 3],
      [120, 120, 80],
      [140, 140, 140],
      [204, 5, 255],
      [230, 230, 230],
      [4, 250, 7],
      [224, 5, 255],
      [235, 255, 7],
      [150, 5, 61],
      [120, 120, 70],
      [8, 255, 51],
      [255, 6, 82],
      [143, 255, 140],
      [204, 255, 4],
      [255, 51, 7],
      [204, 70, 3],
      [0, 102, 200],
      [61, 230, 250],
      [255, 6, 51],
      [11, 102, 255],
      [255, 7, 71],
      [255, 9, 224],
      [9, 7, 230],
      [220, 220, 220],
      [255, 9, 92],
      [112, 9, 255],
      [8, 255, 214],
      [7, 255, 224],
      [255, 184, 6],
      [10, 255, 71],
      [255, 41, 10],
      [7, 255, 255],
      [224, 255, 8],
      [102, 8, 255],
      [255, 61, 6],
      [255, 194, 7],
      [255, 122, 8],
      [0, 255, 20],
      [255, 8, 41],
      [255, 5, 153],
      [6, 51, 255],
      [235, 12, 255],
      [160, 150, 20],
      [0, 163, 255],
      [140, 140, 140],
      [250, 10, 15],
      [20, 255, 0],
      [31, 255, 0],
      [255, 31, 0],
      [255, 224, 0],
      [153, 255, 0],
      [0, 0, 255],
      [255, 71, 0],
      [0, 235, 255],
      [0, 173, 255],
      [31, 0, 255],
      [11, 200, 200],
      [255, 82, 0],
      [0, 255, 245],
      [0, 61, 255],
      [0, 255, 112],
      [0, 255, 133],
      [255, 0, 0],
      [255, 163, 0],
      [255, 102, 0],
      [194, 255, 0],
      [0, 143, 255],
      [51, 255, 0],
      [0, 82, 255],
      [0, 255, 41],
      [0, 255, 173],
      [10, 0, 255],
      [173, 255, 0],
      [0, 255, 153],
      [255, 92, 0],
      [255, 0, 255],
      [255, 0, 245],
      [255, 0, 102],
      [255, 173, 0],
      [255, 0, 20],
      [255, 184, 184],
      [0, 31, 255],
      [0, 255, 61],
      [0, 71, 255],
      [255, 0, 204],
      [0, 255, 194],
      [0, 255, 82],
      [0, 10, 255],
      [0, 112, 255],
      [51, 0, 255],
      [0, 194, 255],
      [0, 122, 255],
      [0, 255, 163],
      [255, 153, 0],
      [0, 255, 10],
      [255, 112, 0],
      [143, 255, 0],
      [82, 0, 255],
      [163, 255, 0],
      [255, 235, 0],
      [8, 184, 170],
      [133, 0, 255],
      [0, 255, 92],
      [184, 0, 255],
      [255, 0, 31],
      [0, 184, 255],
      [0, 214, 255],
      [255, 0, 112],
      [92, 255, 0],
      [0, 224, 255],
      [112, 224, 255],
      [70, 184, 160],
      [163, 0, 255],
      [153, 0, 255],
      [71, 255, 0],
      [255, 0, 163],
      [255, 204, 0],
      [255, 0, 143],
      [0, 255, 235],
      [133, 255, 0],
      [255, 0, 235],
      [245, 0, 255],
      [255, 0, 122],
      [255, 245, 0],
      [10, 190, 212],
      [214, 255, 0],
      [0, 204, 255],
      [20, 0, 255],
      [255, 255, 0],
      [0, 153, 255],
      [0, 41, 255],
      [0, 255, 204],
      [41, 0, 255],
      [41, 255, 0],
      [173, 0, 255],
      [0, 245, 255],
      [71, 0, 255],
      [122, 0, 255],
      [0, 255, 184],
      [0, 92, 255],
      [184, 255, 0],
      [0, 133, 255],
      [255, 214, 0],
      [25, 194, 194],
      [102, 255, 0],
      [92, 0, 255],
  ])
```

Lalu, Anda dapat menggabungkan dan memplot gambar serta peta segmentasi yang diprediksi:

```py
>>> import matplotlib.pyplot as plt
>>> import numpy as np

>>> color_seg = np.zeros((pred_seg.shape[0], pred_seg.shape[1], 3), dtype=np.uint8)
>>> palette = np.array(ade_palette())
>>> for label, color in enumerate(palette):
...     color_seg[pred_seg == label, :] = color
>>> color_seg = color_seg[..., ::-1]  # convert to BGR

>>> img = np.array(image) * 0.5 + color_seg * 0.5  # plot the image with the segmentation map
>>> img = img.astype(np.uint8)

>>> plt.figure(figsize=(15, 10))
>>> plt.imshow(img)
>>> plt.show()
```

    

