세그멘테이션 객체 분리
Segment Task를 수행한 후, 추론 결과에서 분리된 객체를 추출하는 것이 유용할 때가 있습니다. 이 가이드는 Ultralytics Predict Mode를 사용하여 이를 수행하는 일반적인 방법을 제공합니다.
Watch: How to Remove Background and Isolate Objects with Ultralytics YOLO Segmentation & OpenCV in Python 🚀
레시피 따라하기
-
필수 라이브러리 설치에 대한 빠른 가이드는 Ultralytics Quickstart Installation 섹션을 참조하십시오.
-
모델을 로드하고 소스에서
predict()메서드를 실행합니다.from ultralytics import YOLO # Load a model model = YOLO("yolo26n-seg.pt") # Run inference results = model.predict()
소스를 지정하지 않으면 라이브러리의 예제 이미지가 사용됩니다:
'ultralytics/assets/bus.jpg'
'ultralytics/assets/zidane.jpg'이는 predict() 메서드를 사용하여 빠르게 테스트할 때 유용합니다.
세그멘테이션 모델에 대한 추가 정보는 Segment Task 페이지를 방문하십시오. predict() 메서드에 대해 자세히 알아보려면 문서의 Predict Mode 섹션을 참조하십시오.
***
이제 결과와 윤곽선을 반복합니다. 이미지를 파일로 저장하려는 워크플로우의 경우, 소스 이미지 base-name과 탐지 class-label을 나중에 사용하기 위해 검색합니다(선택 사항).
```{ .py .annotate }
from pathlib import Path
import numpy as np
# (2) Iterate detection results (helpful for multiple images)
for r in results:
img = np.copy(r.orig_img)
img_name = Path(r.path).stem # source image base-name
# Iterate each object contour (multiple detections)
for ci, c in enumerate(r):
# (1) Get detection class name
label = c.names[c.boxes.cls.tolist().pop()]
```
1. To learn more about working with detection results, see [Boxes Section for Predict Mode](../modes/predict.md#boxes).
2. To learn more about `predict()` results see [Working with Results for Predict Mode](../modes/predict.md#working-with-results)For-Loop(반복문)
단일 이미지는 첫 번째 루프를 한 번만 반복합니다. 탐지가 단 하나인 단일 이미지는 각 루프를 단 한 번만 반복합니다.
-
소스 이미지에서 이진 마스크를 생성하는 것부터 시작한 다음, 마스크에 채워진 윤곽선을 그립니다. 이렇게 하면 이미지의 다른 부분으로부터 객체를 분리할 수 있습니다.
bus.jpg에서 탐지된person클래스 객체 중 하나에 대한 예시가 오른쪽에 나와 있습니다.{ width="240", align="right" }
import cv2 # Create binary mask b_mask = np.zeros(img.shape[:2], np.uint8) # (1) Extract contour result contour = c.masks.xy.pop() # (2) Changing the type contour = contour.astype(np.int32) # (3) Reshaping contour = contour.reshape(-1, 1, 2) # Draw contour onto mask _ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)-
c.masks.xy에 대한 자세한 내용은 Masks Section from Predict Mode를 참조하십시오. -
Here the values are cast into
np.int32for compatibility withdrawContours()function from OpenCV. -
OpenCV
drawContours()함수는 윤곽선의 형태가[N, 1, 2]가 될 것으로 기대합니다. 자세한 내용은 아래 섹션을 펼쳐보십시오.
Expand to understand what is happening when defining the
contourvariable.- `c.masks.xy` :: Provides the coordinates of the mask contour points in the format `(x, y)`. For more details, refer to the [Masks Section from Predict Mode](../modes/predict.md#masks). - `.pop()` :: As `masks.xy` is a list containing a single element, this element is extracted using the `pop()` method. - `.astype(np.int32)` :: Using `masks.xy` will return with a data type of `float32`, but this won't be compatible with the OpenCV `drawContours()` function, so this will change the data type to `int32` for compatibility. - `.reshape(-1, 1, 2)` :: Reformats the data into the required shape of `[N, 1, 2]` where `N` is the number of contour points, with each point represented by a single entry `1`, and the entry is composed of `2` values. The `-1` denotes that the number of values along this dimension is flexible.
Expand for an explanation of the
drawContours()configuration.- Encapsulating the `contour` variable within square brackets, `[contour]`, was found to effectively generate the desired contour mask during testing. - The value `-1` specified for the `drawContours()` parameter instructs the function to draw all contours present in the image. - The `tuple` `(255, 255, 255)` represents the color white, which is the desired color for drawing the contour in this binary mask. - The addition of `cv2.FILLED` will color all pixels enclosed by the contour boundary the same, in this case, all enclosed pixels will be white. - See [OpenCV Documentation on `drawContours()`](https://docs.opencv.org/4.8.0/d6/d6e/group__imgproc__draw.html#ga746c0625f1781f1ffc9056259103edbc) for more information.
-
-
다음으로, 이 시점부터 이미지를 처리하는 두 가지 옵션과 각각에 대한 후속 옵션이 있습니다.
객체 분리 옵션
# Create 3-channel mask
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
# Isolate object with binary mask
isolated = cv2.bitwise_and(mask3ch, img)어떻게 작동하나요?
-
먼저, 이진 마스크를 단일 채널 이미지에서 3채널 이미지로 변환합니다. 이 변환은 마스크와 원본 이미지를 결합하는 후속 단계를 위해 필요합니다. 블렌딩 작업과 호환되려면 두 이미지의 채널 수가 동일해야 합니다.
-
원본 이미지와 3채널 이진 마스크는 OpenCV 함수
bitwise_and()를 사용하여 병합됩니다. 이 연산은 두 이미지에서 0보다 큰(> 0)픽셀 값만 유지합니다. 마스크 픽셀은 윤곽 영역 내에서만 0보다 크기 때문에(> 0), 원본 이미지에서 남은 픽셀은 윤곽선과 겹치는 픽셀들입니다.
검은색 픽셀로 분리: 하위 옵션
전체 크기 이미지
전체 크기 이미지를 유지하는 경우 추가 단계가 필요하지 않습니다.
객체 잘라내기(Crop) 이미지
이미지를 객체 영역만 포함하도록 잘라내려면 추가 단계가 필요합니다.
{ align="right" }
# (1) Bounding box coordinates
x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
# Crop image to object region
iso_crop = isolated[y1:y2, x1:x2]- bounding box 결과에 대한 자세한 내용은 Boxes Section from Predict Mode를 참조하십시오.
이 코드는 어떤 기능을 하나요?
-
c.boxes.xyxy.cpu().numpy()호출은xyxy형식의 NumPy 배열로 경계 상자를 가져오며, 여기서xmin,ymin,xmax,ymax는 경계 상자 사각형의 좌표를 나타냅니다. 자세한 내용은 Boxes Section from Predict Mode를 참조하십시오. -
squeeze()연산은 NumPy 배열에서 불필요한 차원을 제거하여 예상되는 형태를 갖도록 합니다. -
.astype(np.int32)를 사용하여 좌표 값을 변환하면 상자 좌표 데이터 타입이float32에서int32로 변경되어 인덱스 슬라이싱을 사용한 이미지 잘라내기와 호환됩니다. -
마지막으로, 경계 상자 영역은 인덱스 슬라이싱을 사용하여 이미지에서 잘라냅니다. 경계는 탐지 경계 상자의
[ymin:ymax, xmin:xmax]좌표로 정의됩니다.
배경을 **포함**하여 잘라낸 객체를 원하면 어떻게 하나요?
This is a built-in feature for the Ultralytics library. See the save_crop argument for Predict Mode Inference Arguments for details.
- 다음에 무엇을 할지는 전적으로 개발자의 몫입니다. 가능한 다음 단계 중 하나인 기본 예시(향후 사용을 위해 이미지를 파일로 저장)가 표시되어 있습니다.
- 참고: 이 단계는 선택 사항이며 특정 사용 사례에 필요하지 않은 경우 건너뛸 수 있습니다.
최종 단계 예시
# Save isolated object to file
_ = cv2.imwrite(f"{img_name}_{label}-{ci}.png", iso_crop)- 이 예시에서
img_name은 소스 이미지 파일의 기본 이름이고,label은 탐지된 클래스 이름이며,ci는 object detection의 인덱스입니다(동일한 클래스 이름의 인스턴스가 여러 개인 경우).
전체 예시 코드
여기서는 이전 섹션의 모든 단계를 하나의 코드 블록으로 결합했습니다. 반복 사용을 위해서는 for-루프에 포함된 명령의 일부 또는 전부를 수행하는 함수를 정의하는 것이 최적이지만, 이는 사용자에게 맡기는 연습 과제입니다.
from pathlib import Path
import cv2
import numpy as np
from ultralytics import YOLO
m = YOLO("yolo26n-seg.pt") # (4)!
res = m.predict(source="path/to/image.jpg") # (3)!
# Iterate detection results (5)
for r in res:
img = np.copy(r.orig_img)
img_name = Path(r.path).stem
# Iterate each object contour (6)
for ci, c in enumerate(r):
label = c.names[c.boxes.cls.tolist().pop()]
b_mask = np.zeros(img.shape[:2], np.uint8)
# Create contour mask (1)
contour = c.masks.xy.pop().astype(np.int32).reshape(-1, 1, 2)
_ = cv2.drawContours(b_mask, [contour], -1, (255, 255, 255), cv2.FILLED)
# Choose one:
# OPTION-1: Isolate object with black background
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR)
isolated = cv2.bitwise_and(mask3ch, img)
# OPTION-2: Isolate object with transparent background (when saved as PNG)
isolated = np.dstack([img, b_mask])
# OPTIONAL: detection crop (from either OPT1 or OPT2)
x1, y1, x2, y2 = c.boxes.xyxy.cpu().numpy().squeeze().astype(np.int32)
iso_crop = isolated[y1:y2, x1:x2]
# Add your custom post-processing here (2)contour를 채우는 라인은 위에서 여러 줄로 나뉘었던 것이 여기서는 한 줄로 결합되었습니다.- {==여기에 무엇을 넣을지는 사용자에게 달렸습니다!==}
- 추가 정보는 Predict Mode를 참조하십시오.
- 더 자세한 정보는 Segment Task를 참조하십시오.
- Working with Results에 대해 더 알아보십시오.
- Segmentation Mask Results에 대해 더 알아보십시오.
FAQ
세그멘테이션 작업을 위해 Ultralytics YOLO26을 사용하여 객체를 어떻게 분리하나요?
Ultralytics YOLO26을 사용하여 객체를 분리하려면 다음 단계를 따르십시오:
-
모델 로드 및 추론 실행:
from ultralytics import YOLO model = YOLO("yolo26n-seg.pt") results = model.predict(source="path/to/your/image.jpg") -
이진 마스크 생성 및 윤곽선 그리기:
import cv2 import numpy as np 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)
더 자세한 정보는 Predict Mode 가이드와 Segment Task를 참조하십시오.
세그멘테이션 후 분리된 객체를 저장하는 데 사용할 수 있는 옵션은 무엇인가요?
Ultralytics YOLO26은 분리된 객체를 저장하기 위한 두 가지 주요 옵션을 제공합니다:
-
검은색 배경 포함:
mask3ch = cv2.cvtColor(b_mask, cv2.COLOR_GRAY2BGR) isolated = cv2.bitwise_and(mask3ch, img) -
투명 배경 포함:
isolated = np.dstack([img, b_mask])
자세한 내용은 Predict Mode 섹션을 방문하십시오.
Ultralytics YOLO26을 사용하여 분리된 객체를 경계 상자로 잘라내려면 어떻게 해야 하나요?
분리된 객체를 경계 상자로 잘라내려면:
-
경계 상자 좌표 검색:
x1, y1, x2, y2 = results[0].boxes.xyxy[0].cpu().numpy().astype(np.int32) -
분리된 이미지 잘라내기:
iso_crop = isolated[y1:y2, x1:x2]
경계 상자 결과에 대해 더 자세히 알아보려면 Predict Mode 문서를 참조하십시오.
세그멘테이션 작업에서 객체 분리를 위해 Ultralytics YOLO26을 사용해야 하는 이유는 무엇인가요?
Ultralytics YOLO26은 다음을 제공합니다:
- 고속 실시간 객체 탐지 및 세그멘테이션.
- 정밀한 객체 분리를 위한 정확한 경계 상자 및 마스크 생성.
- 효율적인 개발을 위한 포괄적인 문서 및 사용하기 쉬운 API.
Segment Task 문서에서 YOLO 사용의 이점을 살펴보십시오.
Ultralytics YOLO26을 사용하여 배경을 포함하여 분리된 객체를 저장할 수 있나요?
Yes, this is a built-in feature in Ultralytics YOLO26. Use the save_crop argument in the predict() method. For example:
results = model.predict(source="path/to/your/image.jpg", save_crop=True)save_crop 인자에 대해 자세히 읽으려면 Predict Mode Inference Arguments 섹션을 참조하십시오.