Link to this sectionCách cô lập các đối tượng phân đoạn với Ultralytics YOLO#
Instance segmentation tạo ra một mask chính xác từng pixel cho mọi đối tượng được phát hiện, nghĩa là bạn có thể tách từng đối tượng ra khỏi ảnh một cách riêng biệt. Hướng dẫn này chỉ cho bạn cách biến kết quả phân đoạn của Ultralytics YOLO thành các đối tượng riêng lẻ bằng cách sử dụng Predict Mode và OpenCV, với tùy chọn nền đen hoặc nền trong suốt để lưu dưới dạng PNG.
Watch: How to Remove Background and Isolate Objects with Ultralytics YOLO Segmentation & OpenCV in Python 🚀
Link to this sectionTại sao cần cô lập đối tượng phân đoạn?#
Việc tách từng đối tượng ra khỏi ảnh mở ra nhiều quy trình xử lý tiếp theo:
- Xóa nền cho ảnh sản phẩm, danh mục hoặc chỉnh sửa sáng tạo.
- Cắt theo đối tượng để xây dựng tập dữ liệu phân loại từ các phát hiện của bạn.
- Xử lý tập trung giúp các bước sau như OCR, phân tích màu sắc hoặc đo lường chỉ nhìn thấy đối tượng, thay vì khung cảnh xung quanh.
- Xuất file PNG trong suốt để ghép các đối tượng lên nền mới.
Công thức này hoạt động với bất kỳ model phân đoạn Ultralytics YOLO nào và gồm bốn giai đoạn: chạy inference → trích xuất từng đường bao → cô lập đối tượng → lưu kết quả.
Link to this sectionChạy Segmentation Inference#
Cài đặt các thư viện cần thiết, sau đó tải model phân đoạn (hậu tố -seg, cần thiết để tạo mask) và chạy dự đoán trên ảnh nguồn của bạn:
from ultralytics import YOLO
# Load a segmentation model
model = YOLO("yolo26n-seg.pt")
# Run inference on a source
results = model.predict(source="path/to/image.jpg")Nếu bạn gọi model.predict() mà không có source, Ultralytics sẽ quay về sử dụng các ảnh mẫu đi kèm với gói cài đặt (bus.jpg và zidane.jpg), rất tiện lợi để kiểm tra nhanh quy trình.
Link to this sectionTrích xuất đường bao đối tượng#
Mỗi mục trong results tương ứng với một ảnh, và việc duyệt qua một result sẽ trả về từng phát hiện một. Với mỗi phát hiện, hãy sao chép ảnh gốc, đọc nhãn lớp và vẽ đường bao của mask đối tượng lên một mask nhị phân trống. Vùng màu trắng của mask này đánh dấu chính xác những pixel nào thuộc về đối tượng.
Các đoạn mã trong phần này và phần tiếp theo chạy bên trong vòng lặp phát hiện bên dưới; kịch bản hoàn chỉnh, có thể sao chép nằm trong Full Example.
{ width="240", align="right" }
from pathlib import Path
import cv2
import numpy as np
for r in results:
img = np.copy(r.orig_img)
img_name = Path(r.path).stem # source image base-name
# Iterate each detected object in the image
for ci, c in enumerate(r):
label = c.names[c.boxes.cls.tolist().pop()] # class name
# Build a binary mask and draw the object contour onto it
b_mask = np.zeros(img.shape[:2], np.uint8)
contour = c.masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)c.masks.xy[0]trả về đường bao mask dưới dạng tọa độ điểm(x, y)cho đối tượng trong kết quả phát hiện đơn lẻ này..astype(np.int32)chuyển đổi các điểm từfloat32, định dạng mà hàmdrawContours()của OpenCV không hỗ trợ..reshape(-1, 1, 2)định hình lại các điểm thành cấu trúc[N, 1, 2]màdrawContours()mong đợi, vớiNlà số lượng điểm đường bao.
Việc truyền [contour] với chỉ số -1 sẽ vẽ tất cả các điểm của đường bao được cung cấp, và cv2.FILLED tô màu trắng cho mọi pixel được bao quanh.
Link to this sectionCô lập đối tượng#
Với mask nhị phân đã sẵn sàng, hãy kết hợp nó với ảnh gốc. Có hai kiểu phổ biến, tùy thuộc vào nền bạn muốn:
Chuyển đổi mask thành ba kênh và chỉ giữ lại các pixel trùng với đối tượng. Mọi thứ bên ngoài đường bao sẽ trở thành màu đen:
# Isolate object with a black background
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img)Để chỉ giữ lại vùng của đối tượng thay vì toàn bộ ảnh, hãy cắt nó theo BBox của phát hiện:
# Bounding box coordinates
x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
# Crop the isolated image to the object region
iso_crop = isolated[y1:y2, x1:x2]Tính năng này đã có sẵn. Hãy truyền save_crop=True vào predict() và Ultralytics sẽ tự động lưu các ảnh cắt theo BBox, không cần dùng mask.
Link to this sectionLưu kết quả (tùy chọn)#
Việc bạn làm gì với từng đối tượng đã cô lập là tùy thuộc vào bạn. Một bước tiếp theo phổ biến là ghi nó vào ổ đĩa để sử dụng sau:
# Save the isolated object to file
cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated)Tại đây img_name là phần tên gốc của ảnh, label là tên lớp và ci là chỉ số phát hiện, do đó nhiều instance của cùng một lớp sẽ có tên file duy nhất. Hãy đổi isolated thành iso_crop nếu bạn đã áp dụng tùy chọn cắt bên trên.
Link to this sectionVí dụ đầy đủ#
Kịch bản dưới đây kết hợp mọi bước thành một khối có thể chạy được. Mặc định nó sử dụng nền đen; hãy chuyển dòng được đánh dấu thành np.dstack([img, b_mask]) để có file PNG trong suốt:
from pathlib import Path
import cv2
import numpy as np
from ultralytics import YOLO
model = YOLO("yolo26n-seg.pt")
results = model.predict(source="path/to/image.jpg")
for r in results:
img = np.copy(r.orig_img)
img_name = Path(r.path).stem
for ci, c in enumerate(r):
label = c.names[c.boxes.cls.tolist().pop()]
# Build a binary mask from the object contour
b_mask = np.zeros(img.shape[:2], np.uint8)
contour = c.masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
# Isolate the object (black background)
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img) # transparent PNG: isolated = np.dstack([img, b_mask])
# Save or add your custom post-processing here
cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated)
# Optional: crop to the bounding box before saving
# x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
# cv2.imwrite(f"{img_name}_{label}-{ci}.png", isolated[y1:y2, x1:x2])Để sử dụng nhiều lần, hãy gói phần thân vòng lặp trong một hàm để bạn có thể gọi nó trên nhiều ảnh.
Link to this sectionKết luận#
Giờ bạn đã có công thức hoàn chỉnh để cô lập các đối tượng phân đoạn bằng Ultralytics YOLO: chạy inference, tạo mask nhị phân từ từng đường bao, sau đó trích xuất đối tượng trên nền đen hoặc trong suốt và tùy chọn cắt nó theo BBox. Khám phá tài liệu đầy đủ về Segment Task và Predict Mode để điều chỉnh quy trình cho các lớp của riêng bạn.
Link to this sectionCâu hỏi thường gặp#
Link to this sectionLàm thế nào để cô lập các đối tượng bằng Ultralytics YOLO cho các tác vụ phân đoạn?#
Tải một model phân đoạn, chạy inference, tạo mask nhị phân từ đường bao của mỗi phát hiện và kết hợp nó với ảnh gốc:
import cv2
import numpy as np
from ultralytics import YOLO
model = YOLO("yolo26n-seg.pt")
results = model.predict(source="path/to/your/image.jpg")
img = np.copy(results[0].orig_img)
b_mask = np.zeros(img.shape[:2], np.uint8)
contour = results[0].masks.xy[0].astype(np.int32).reshape(-1, 1, 2)
cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img)Xem Full Example để biết vòng lặp theo từng phát hiện đầy đủ.
Link to this sectionCó những tùy chọn nào để lưu các đối tượng đã cô lập sau khi phân đoạn?#
Có hai kiểu chính. Đối với nền đen, hãy chuyển đổi mask thành ba kênh và sử dụng cv2.bitwise_and(). Đối với nền trong suốt (khi lưu dưới dạng PNG), hãy xếp chồng mask làm kênh thứ tư alpha với np.dstack([img, b_mask]). Cả hai đều được hiển thị trong phần Isolate the Object.
Link to this sectionLàm thế nào để cắt các đối tượng đã cô lập theo BBox của chúng?#
Đọc tọa độ BBox từ kết quả phát hiện và cắt ảnh đã cô lập:
x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32)
iso_crop = isolated[y1:y2, x1:x2]Tìm hiểu thêm về kết quả BBox trong tài liệu Predict Mode.
Link to this sectionTại sao tôi nên sử dụng Ultralytics YOLO để cô lập đối tượng trong các tác vụ phân đoạn?#
Ultralytics YOLO cung cấp khả năng phân đoạn instance thời gian thực, nhanh chóng với việc tạo mask và BBox chính xác, cộng với Python API đơn giản giúp chuyển đổi kết quả inference thành các đối tượng riêng biệt chỉ với vài dòng mã OpenCV.
Link to this sectionTôi có thể lưu các đối tượng đã cô lập bao gồm cả nền bằng Ultralytics YOLO không?#
Có. Sử dụng đối số save_crop trong predict() để lưu các ảnh cắt BBox với nền gốc của chúng:
results = model.predict(source="path/to/your/image.jpg", save_crop=True)Đọc thêm trong phần Predict Mode Inference Arguments.