Instance Segmentation
Phân đoạn thể hiện
Ảnh camera giao thông có 3 chiếc xe máy đỗ sát nhau. Semantic Segmentation tô tất cả cùng màu 'xe'. Làm sao phân biệt xe #1, #2, #3 để đếm hoặc bám theo?
Hãy tưởng tượng bạn là cô giáo nhìn vào lớp học: tất cả học sinh đều mặc áo đồng phục trắng. Semantic Segmentation giống như nói "có áo trắng ở đây, đây và đây" — đúng lớp nhưng không biết ai là ai. Instance Segmentation lại đi thêm một bước: gắn tên riêng cho từng học sinh — "đây là Nam, đây là Lan, đây là Tú".
Trong thế giới AI/CV, điều này có nghĩa là mỗi đối tượng nhận được mask pixel-level riêng biệt. Không chỉ "có xe ở vùng này" mà là "xe #1 chiếm đúng 1.427 pixel này, xe #2 chiếm 1.512 pixel kia". Nhờ vậy, bạn có thể đếm, tách, theo dõi, hoặc thao tác riêng với từng đối tượng.
Nếu không có Instance Segmentation, nhiều ứng dụng thực tế sẽ "đổ vỡ": robot gắp hàng không biết lấy quả táo nào trước, xe tự lái không biết có bao nhiêu người đang băng qua, ứng dụng đếm tế bào y khoa không phân biệt được 2 tế bào đang dính nhau.
Hình minh họa
Nhấn vào từng đối tượng để highlight. Đổi chế độ để thấy khác biệt cốt lõi giữa semantic (cùng lớp = cùng màu) và instance (mỗi đối tượng 1 màu riêng).
Classification
1 nhãn cho cả ảnh
Phân loại ảnh
Object Detection
Nhiều bounding box + nhãn
Phát hiện đối tượng
Semantic Seg.
Pixel-level, cùng lớp = cùng màu
Phân đoạn ngữ nghĩa
Instance Seg.
Pixel-level, mỗi đối tượng 1 màu riêng
Phân đoạn thể hiện
xe
2
tổng 17825 px²
nguoi
2
tổng 21410 px²
Instance Segmentation = Object Detection (tìm từng đối tượng) + Semantic Segmentation (mask pixel-level). Mỗi đối tượng có bounding box + nhãn lớp + mask pixel riêng biệt — giống như điểm danh từng học sinh trong lớp bằng cách tô màu riêng!
Mask R-CNN dự đoán mask riêng cho mỗi đối tượng. Điều gì xảy ra khi 2 người đi bộ che khuất nhau (occlusion)?
Hình minh họa
Stage 1/4: Backbone + FPN
CNN (ResNet + FPN) trích xuất feature đa tỷ lệ
Khi thay RoIPool bằng RoIAlign trong Mask R-CNN, mAP mask tăng đáng kể. Lý do chính là gì?
Giải thích
Instance Segmentation kết hợp phát hiện đối tượng và phân đoạn ngữ nghĩa ở cấp pixel. Không chỉ tô màu theo danh mục, mô hình còn phân biệt từng thể hiện riêng lẻ — điều mà semantic segmentation đơn thuần không làm được.
Mask R-CNN mở rộng Faster R-CNN bằng 1 nhánh mask song song. Pipeline đầy đủ:
- Backbone + FPN: ResNet-50/101 trích xuất feature map đa tỷ lệ (P2–P6), giúp bắt vật nhỏ lẫn lớn
- RPN: Region Proposal Network đề xuất ~1000 ROI từ anchor boxes
- RoIAlign: Cắt feature map cho mỗi ROI (7×7 cho box head, 14×14 cho mask head) — không làm tròn, dùng bilinear interpolation
- 3 nhánh song song: Box regression (4 số), Classification (K+1 lớp), và Binary Mask K×28×28 — mỗi lớp 1 mask riêng
Hàm mất mát Mask R-CNN là tổng trực tiếp của 3 thành phần:
là binary cross-entropy trên mask , chỉ tính cho lớp ground-truth (class-specific mask). Chi tiết này rất quan trọng: thay vì softmax trên K kênh, Mask R-CNN dùng mask sigmoid độc lập, rồi chỉ lấy mask của lớp đúng để tính loss. Kết quả: tách biệt mask khỏi classification, tránh cạnh tranh giữa các lớp.
- RoIPool: làm tròn toạ độ hai lần (ROI → lưới feature, và bins trong ROI). Gây sai lệch vài pixel. Với bbox thì OK, nhưng mask pixel-level thì thảm.
- RoIAlign: bỏ hoàn toàn quantization. Với mỗi bin, lấy mẫu 4 điểm (hoặc 1 điểm) bằng bilinear interpolation. Cải thiện mAP mask ~10% trên COCO.
Các phương pháp instance segmentation nổi bật:
- Mask R-CNN (2017): Two-stage, phổ biến nhất, baseline mạnh cho nghiên cứu và sản phẩm. Thư viện: Detectron2, MMDetection.
- YOLACT (2019): One-stage, real-time (~30 FPS). Dùng "prototypes" toàn ảnh + coefficients per-detection, mask instance = kết hợp tuyến tính.
- SOLOv2 (2020): Phân loại vị trí grid + kích thước, bỏ anchor. Xuất mask trực tiếp, không cần box trước.
- SAM (2023): Segment Anything — foundation model zero-shot. Prompt bằng click/box/text, phân đoạn mọi đối tượng không cần fine-tune.
- SAM 2 (2024): Mở rộng SAM cho video, tracking + segmentation với memory attention giữa các frame.
- Mask2Former (2022): Kiến trúc thống nhất semantic + instance + panoptic. Transformer query-based, SOTA trên nhiều benchmark.
- Robot công nghiệp: Gắp đồ vật trên dây chuyền — cần mask chính xác từng vật để tính lực kẹp.
- Thương mại điện tử: Tự động tách nền sản phẩm trên Shopee, Tiki, Lazada.
- Y tế: Đếm và đo từng tế bào riêng biệt trong ảnh hiển vi; tách từng khối u trong MRI.
- Nông nghiệp: Đếm từng quả trên cây từ ảnh drone, ước lượng sản lượng.
- Xe tự lái: Phân biệt từng người đi bộ, từng xe — cần thiết để dự đoán quỹ đạo riêng cho từng đối tượng.
- AR/VR: Tách nền video thời gian thực để thay background (Meet, Zoom) — thường dùng mô hình nhẹ như MediaPipe SelfieSegmentation nhưng về bản chất vẫn là instance seg. với 1 lớp.
Code ví dụ 1 — Detectron2 (Facebook AI Research): Mask R-CNN production-ready chỉ vài dòng.
# pip install detectron2 (xem hướng dẫn chính thức cho CUDA version)
import cv2
import numpy as np
from detectron2 import model_zoo
from detectron2.config import get_cfg
from detectron2.engine import DefaultPredictor
from detectron2.utils.visualizer import Visualizer, ColorMode
from detectron2.data import MetadataCatalog
# 1) Cấu hình Mask R-CNN + ResNet-50-FPN đã train trên COCO
cfg = get_cfg()
cfg.merge_from_file(model_zoo.get_config_file(
"COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"
))
cfg.MODEL.ROI_HEADS.SCORE_THRESH_TEST = 0.5 # ngưỡng confidence
cfg.MODEL.WEIGHTS = model_zoo.get_checkpoint_url(
"COCO-InstanceSegmentation/mask_rcnn_R_50_FPN_3x.yaml"
)
# cfg.MODEL.DEVICE = "cpu" # bỏ comment nếu không có GPU
predictor = DefaultPredictor(cfg)
# 2) Đọc ảnh và chạy inference
image = cv2.imread("duong_pho.jpg")
outputs = predictor(image)
# 3) Các trường quan trọng trong outputs["instances"]
instances = outputs["instances"].to("cpu")
print(f"Số instance phát hiện: {len(instances)}")
print(f"Class IDs: {instances.pred_classes.tolist()}")
print(f"Scores: {instances.scores.tolist()}")
print(f"Boxes shape: {instances.pred_boxes.tensor.shape}") # (N, 4) xyxy
print(f"Masks shape: {instances.pred_masks.shape}") # (N, H, W) bool
# 4) Visualize: mỗi instance một màu riêng
metadata = MetadataCatalog.get(cfg.DATASETS.TRAIN[0])
v = Visualizer(
image[:, :, ::-1], # BGR → RGB
metadata=metadata,
scale=1.0,
instance_mode=ColorMode.IMAGE, # màu riêng cho từng instance
)
vis = v.draw_instance_predictions(instances)
cv2.imwrite("ket_qua.jpg", vis.get_image()[:, :, ::-1])
# 5) Trích xuất mask nhị phân cho instance đầu tiên
if len(instances) > 0:
mask_0 = instances.pred_masks[0].numpy() # bool array (H, W)
# Ví dụ: tính diện tích mask, lấy contour, apply vào ảnh gốc
area_px = int(mask_0.sum())
print(f"Instance #0: diện tích {area_px} pixel")
Code ví dụ 2 — SAM (Segment Anything): Zero-shot segmentation chỉ cần 1 click.
# pip install git+https://github.com/facebookresearch/segment-anything.git
import cv2
import numpy as np
from segment_anything import sam_model_registry, SamPredictor
# 1) Load SAM ViT-H (checkpoint ~2.4GB)
sam = sam_model_registry["vit_h"](checkpoint="sam_vit_h_4b8939.pth")
sam.to("cuda") # hoặc "cpu"
predictor = SamPredictor(sam)
# 2) Set image (chạy image encoder 1 lần, cache feature)
image = cv2.imread("duong_pho.jpg")
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
predictor.set_image(image_rgb)
# 3) Prompt 1: click vào tâm xe máy
input_point = np.array([[200, 300]]) # (x, y)
input_label = np.array([1]) # 1 = foreground, 0 = background
masks, scores, logits = predictor.predict(
point_coords=input_point,
point_labels=input_label,
multimask_output=True, # trả về 3 mask ứng viên
)
best_idx = int(np.argmax(scores))
best_mask = masks[best_idx] # (H, W) bool
print(f"Mask tốt nhất: score={scores[best_idx]:.3f}")
# 4) Prompt 2: bounding box (khi bạn đã có box từ model khác)
input_box = np.array([150, 200, 350, 400]) # xyxy
masks_from_box, _, _ = predictor.predict(
box=input_box,
multimask_output=False,
)
# 5) Kết hợp nhiều click (refinement)
input_point = np.array([[200, 300], [220, 310]])
input_label = np.array([1, 1]) # cả 2 là foreground
refined_masks, refined_scores, _ = predictor.predict(
point_coords=input_point,
point_labels=input_label,
multimask_output=False,
)
# 6) Automatic mask generation — phân đoạn MỌI đối tượng trong ảnh
from segment_anything import SamAutomaticMaskGenerator
mask_gen = SamAutomaticMaskGenerator(sam)
auto_masks = mask_gen.generate(image_rgb)
print(f"SAM tìm được {len(auto_masks)} mask tự động")
for i, m in enumerate(auto_masks[:5]):
print(f" #{i}: area={m['area']}, score={m['predicted_iou']:.2f}")
Chọn phương pháp nào? Quy tắc nhanh:
- Có nhãn train + cần độ chính xác cao: Mask R-CNN hoặc Mask2Former với Detectron2/MMDetection.
- Cần real-time (>20 FPS): YOLACT, YOLOv8-seg, hoặc mô hình một-stage khác.
- Không có nhãn / domain mới / zero-shot: SAM hoặc SAM 2.
- Cần cả semantic + instance (mọi pixel có nhãn): Panoptic Segmentation với Mask2Former hoặc Panoptic FPN.
Các khái niệm liên quan chặt chẽ: Semantic Segmentation, Object Detection, Panoptic Segmentation.
- Instance Segmentation = Object Detection + Semantic Segmentation: mỗi đối tượng có bounding box + nhãn + MASK PIXEL RIÊNG.
- Khác Semantic (cùng lớp = cùng màu), Instance tô MÀU RIÊNG cho từng thể hiện — phân biệt người #1, người #2 cùng lớp.
- Mask R-CNN = Faster R-CNN + nhánh mask K×28×28 song song, dùng RoIAlign thay RoIPool để giữ chính xác pixel.
- Loss = L_cls + L_box + L_mask; L_mask chỉ tính cho lớp GT (class-specific sigmoid, không cạnh tranh giữa lớp).
- YOLACT/SOLOv2 cho real-time; SAM/SAM2 zero-shot qua prompt (click, box, text); Mask2Former thống nhất semantic+instance+panoptic.
- Ứng dụng: robot gắp đồ, xe tự lái, đếm tế bào, tách nền sản phẩm e-commerce, AR/VR thay background.
Kiểm tra hiểu biết
Instance Segmentation kết hợp khả năng của hai tác vụ nào?