Transformers documentation
Segmentasi Gambar
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:
Sebelum memulai, pastikan Anda telah menginstal semua pustaka yang diperlukan:
# uncomment to install the necessary libraries
!pip install -q datasets transformers evaluate accelerate trackioKami 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:
>>> from huggingface_hub import notebook_login
>>> notebook_login()Jenis-jenis Segmentasi
Semantic segmentation memberikan label atau kelas pada setiap piksel dalam sebuah gambar. Mari kita lihat keluaran dari model semantic segmentation. 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 semantic segmentation dengan cepat. Mari kita lihat gambar contohnya.
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.
semantic_segmentation = pipeline("image-segmentation", "nvidia/segformer-b1-finetuned-cityscapes-1024-1024")
results = semantic_segmentation(image)
resultsOutput dari pipeline segmentasi mencakup mask untuk setiap kelas yang diprediksi.
[{'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.
results[-1]["mask"]
Pada 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 untuk ini.
instance_segmentation = pipeline("image-segmentation", "facebook/mask2former-swin-large-cityscapes-instance")
results = instance_segmentation(image)
resultsSeperti yang dapat Anda lihat di bawah, terdapat beberapa mobil yang diklasifikasikan, dan tidak ada klasifikasi untuk piksel selain piksel yang termasuk dalam instans mobil dan orang.
[{'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.
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 untuk ini.
panoptic_segmentation = pipeline("image-segmentation", "facebook/mask2former-swin-large-cityscapes-panoptic")
results = panoptic_segmentation(image)
resultsSeperti 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.
[{'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 proses 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:
- Lakukan finetune SegFormer pada dataset SceneParse150.
- 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
Muat dataset SceneParse150
Mulai dengan memuat subset kecil dari dataset SceneParse150 dari pustaka 🤗 Datasets. Hal ini memberi Anda kesempatan untuk bereksperimen dan memastikan semuanya berfungsi dengan baik sebelum menghabiskan lebih banyak waktu untuk pelatihan pada dataset lengkap.
>>> from datasets import load_dataset
>>> ds = load_dataset("merve/scene_parse_150", split="train[:50]")Bagi split train dari dataset menjadi set train dan test dengan metode train_test_split:
>>> ds = ds.train_test_split(test_size=0.2)
>>> train_ds = ds["train"]
>>> test_ds = ds["test"]Lalu, lihatlah sebuah contoh:
>>> 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 membutuhkanimagedanannotation, yang keduanya berupa gambar PIL.
Anda juga perlu membuat kamus yang memetakan id label ke kelas label, yang akan berguna saat Anda menyiapkan model nanti. Unduh pemetaan dari Hub dan buat kamus id2label dan label2id:
>>> 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 image processor 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 loss SegFormer:
>>> 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 dari torchvision untuk mengubah properti warna gambar secara acak, tetapi Anda juga dapat menggunakan pustaka gambar apa pun yang Anda inginkan.
>>> 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.
>>> 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 inputsUntuk menerapkan jitter ke seluruh dataset, gunakan fungsi set_transform dari 🤗 Datasets. Transformasi diterapkan secara langsung (on the fly) sehingga lebih cepat dan menghemat ruang disk:
>>> train_ds.set_transform(train_transforms)
>>> test_ds.set_transform(val_transforms)Evaluasi
Menambahkan metrik selama pelatihan sering kali membantu untuk mengevaluasi kinerja model Anda. Anda dapat dengan cepat memuat metode evaluasi dengan pustaka 🤗 Evaluate. Untuk tugas ini, muat metrik mean Intersection over Union (IoU) (lihat quick tour 🤗 Evaluate untuk mempelajari lebih lanjut tentang cara memuat dan menghitung metrik):
>>> import evaluate
>>> metric = evaluate.load("mean_iou")Lalu buat fungsi untuk menghitung metrik. Prediksi Anda perlu dikonversi terlebih dahulu menjadi logits, lalu dibentuk ulang agar sesuai dengan ukuran label sebelum Anda dapat memanggil compute:
>>> 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 metricsFungsi 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, silakan lihat tutorial dasar di sini!
Anda siap untuk mulai melatih model Anda sekarang! Muat SegFormer dengan AutoModelForSemanticSegmentation, dan berikan model pemetaan antara id label dan kelas label:
>>> from transformers import AutoModelForSemanticSegmentation, TrainingArguments, Trainer
>>> model = AutoModelForSemanticSegmentation.from_pretrained(checkpoint, id2label=id2label, label2id=label2id)Pada titik ini, hanya tersisa tiga langkah:
- Definisikan hiperparameter pelatihan Anda di TrainingArguments. Penting untuk tidak menghapus kolom yang tidak terpakai karena hal ini akan membuang kolom
image. Tanpa kolomimage, Anda tidak dapat membuatpixel_values. Aturremove_unused_columns=Falseuntuk mencegah perilaku ini! Parameter wajib lainnya adalahoutput_diryang menentukan di mana model Anda disimpan. Anda akan mendorong model ini ke Hub dengan mengaturpush_to_hub=True(Anda harus masuk ke Hugging Face untuk mengunggah model Anda). Di akhir setiap epoch, Trainer akan mengevaluasi metrik IoU dan menyimpan checkpoint pelatihan. - Lewatkan argumen pelatihan ke Trainer bersama dengan model, dataset, tokenizer, data collator, dan fungsi
compute_metrics. - Panggil train() untuk melakukan finetuning pada model Anda.
>>> 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() agar semua orang dapat menggunakan model Anda:
>>> trainer.push_to_hub()Inferensi
Bagus, sekarang setelah Anda melakukan finetuning pada model, Anda dapat menggunakannya untuk inferensi!
Muat ulang dataset dan muat gambar untuk inferensi.
>>> 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:
>>> 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:
>>> outputs = model(pixel_values=pixel_values)
>>> logits = outputs.logits.cpu()Selanjutnya, skala ulang logits ke ukuran gambar asli:
>>> 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 sebagai ade_palette() yang memetakan setiap kelas ke nilai RGB-nya.
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:
>>> 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()