Segmentation
- 모델명: yolov8?-seg (n, s, m, ...)
Segmentation 추론결과 조회
- segmentation 추론 결과는 Masks를 이용해 분할된 mask 정보와 Boxes를 이용해 추론한 bounding box의 결과를 조회한다.
- ultralytics.yolo.engine.results.Masks
- Segmentation 의 결과 type
- Results.masks 로 조회한다.
- 주요 속성, 메소드
- xy : mask의 bounding 좌표(경계선 좌표)를 물체별로 list에 담아서 반환한다.
- Object의 외곽선을 그리는 좌표들을 반환
- 개별 object 의 좌표들은 [point개수, x좌표-y좌표] shape의 ndarray로 구성된다.
- xyn: xy의 결과를 이미지 크기 대비 비율로 normalize한 결과. - ultralytics.yolo.engine.results.Boxes
- Results.boxes로 조회
- 주요 속성
- shape: 결과 shape. (찾은 물체개수, 6)
- boxes
- 6: 좌상단 x, 좌상단 y, 우하단 x, 우하단 y, confidence score, label
- xyxy
- bounding box의 좌상단 x, 좌상단 y, 우하단 x, 우하단 y 좌표 반환
- xyxyn
- xyxy를 이미지 대비 비율로 반환
- xywh
- bounding box의 center x, center y, 너비, 높이 를 반환
- xywhn
- xywh를 이미지 대비 비율로 반환
- cls: 찾은 물체의 label
- conf: cls에 대한 confidence score (그 물체일 확률)
- boxes
- x, y, x, y, conf, cls tensor를 반환
import
from ultralytics import YOLO
import cv2
import matplotlib.pyplot as plt
import numpy as np
seg 진행할 사진 파일 경로 지정
- model 지정(yolov8m-seg.pt)
- 결과 저장
file_path = "02_test_image_seg/beatles.jpg"
model = YOLO("models/yolov8m-seg.pt")
result_list = model(file_path, save=True, save_txt=True)
파일 경로 리스트형식으로 지정
- verbose=False -> 로그 출력 X
- conf=0.5 확률 0.5이상의 object만 출력
model = YOLO("models/yolov8m-seg.pt")
file_path2 = ["02_test_image_seg/beatles.jpg", "02_test_image_seg/bus.jpg"]
result_list2 = model(file_path2, save=True, save_txt=True, conf=0.5, verbose=False)
print(type(result_list2), len(result_list2), type(result_list2[0])) # len(result_list2) -> 사진이 몇장인지
이미지 출력 함수 정의
def imshow(img):
cv2.imshow("frame", img)
cv2.waitKey()
cv2.destroyAllWindows()
출력 결과 이미지 확인
# 출력 결과 이미지 확인
result = result_list[0]
imshow(result.plot()) # BGR 모드
bbox
# Bounding Box 정보
boxes = result.boxes
# print(type(boxes))
# bbox의 위치정보
print(len(boxes)) # 찾은 object 개수
print(boxes.xyxy.shape) # bbox의 좌상단 우하단 x, y 좌표
print(boxes.xyxyn.shape) # bbox의 좌상단 우하단 x, y 좌표 이미지크기 대비 비율
# [15:찾은 object개수, 4:좌표]
print(boxes.xywh.shape) # bbox의 center x, y좌표, bbox의 width, height 크기
print(boxes.xywhn.shape) # bbox의 center x, y좌표, bbox의 width, height 크기 이미지크기 대비 비율
## bbox 내의 object 분류
print(boxes.cls) # object calss index
print(boxes.conf) # object들의 확률
object들의 값 확인
result.names.items()
찾아낸 object들의 값 확인
idx2class = np.array([value for key, value in result.names.items()])
idx2class[boxes.cls.to('cpu').numpy().astype('int')]
segmentation
# segmentation
masks = result.masks
print(type(masks))
print(len(masks)) # 추론한 대상이 몇 개인지
print(type(masks.xy), len(masks.xy)) # 찾은 object의 point 좌표들을 리스트로 리턴.
print(type(masks.xy[0]), masks.xy[0].shape) # [0]: 첫번째 object. (374:점개수, 2:좌표)
print(type(masks.xy[-1]), masks.xy[-1].shape)
첫번째 대상(처음으로 검출된)의 좌표점을 시각화
# 첫번째 대상의 좌표점을 시각화
obj = np.zeros(result.orig_shape, dtype='uint8')
idx = masks.xy[0].astype('int')
y_idx, x_idx = idx[:, 0], idx[:, 1]
obj[x_idx, y_idx] = 255
plt.imshow(obj, cmap='gray')
plt.show()
# Masks, Boxes, Keypoints ==> Iterable ==> for in 에서 사용할 수 있는 반복가능 객체
# 여러 object를 찾은 결과 Masks를 for in 으로 조회하면 개별 object의 결과를 가진 Masks가 반환.
len(masks.xy)
for xy in masks.xy:
print(xy.shape)
# masks: 찾은 모든 object
# mask: 개별 object
for mask in masks:
print(type(mask), len(mask.xy), mask.xy[0].shape)
# boxes: 전체 찾은 object들, box: 개별 object
for box in boxes:
print(type(box), box.xyxy.shape, box.cls.shape, box.conf.shape)
bus.jpg 물체의 경계를 찾기.(segment)
# bus.jpg 물체의 경계를 찾기.(segment)
import cv2
from ultralytics import YOLO
# 모델 생성
model = YOLO("models/yolov8m-seg.pt")
# 추론
result = model("02_test_image_seg/bus.jpg")[0]
# 원본 이미지 크기
shape = result.orig_shape
# print(shape) # height, width
# 추론 결과를 그릴 원소가 모두 0이고 원본이미지와 같은 크기의 배열
arr = np.zeros(shape, dtype="uint8")
object_mask = np.zeros(shape, dtype="uint8") # 찾은 사람들의 pixcel을 표시하는 마스크. (사람들만 추출하기 위해 사용.)
background_mask = np.full(shape, fill_value=255, dtype='uint8') # 배경 마스크
# 추론 결과
masks = result.masks # segmentation 결과
boxes = result.boxes # detection 결과
for mask, box in zip(masks, boxes): # mask: 개별 Object
if box.cls.item() == 0: # 찾은 object가 person이라면
xy = mask.xy[0].astype('int') # mask.xy: list. 1개 object결과이므로 length=1
# 찾은 point들 연결
cv2.polylines(arr, [xy], isClosed=True, color=(255,255,255), thickness=2) # isClosed=True -> 끝점도 연결(default=False)
# object mask 생성
cv2.fillPoly(object_mask, # 그릴 대상
[xy], # 다각형의 꼭지점들
255 # 다각형 안쪽을 채울 값
)
cv2.fillPoly(background_mask, [xy], 0)
imshow(cv2.resize(background_mask, (0,0), fx=0.5, fy=0.5))
찾은 instance만 따내기
# 찾은 instance만 따내기
person_img = cv2.bitwise_and(result.orig_img, result.orig_img, mask=object_mask)
imshow(cv2.resize(person_img, (0,0), fx=0.5, fy=0.5))
background_img를 blur
- 배경을 흐리게
# 배경 아웃포커싱
background_img = cv2.bitwise_and(result.orig_img, result.orig_img, mask=background_mask)
# imshow(cv2.resize(background_img, (0,0), fx=0.5, fy=0.5))
# background_img를 blur
blur_background_img = cv2.GaussianBlur(background_img, ksize=(0,0), sigmaX=5)
# imshow(cv2.resize(blur_background_img, (0,0), fx=0.5, fy=0.5))
# 최종결과
result_img = np.where(background_mask[..., np.newaxis]!=0, blur_background_img, result.orig_img)
imshow(cv2.resize(result_img, (0,0), fx=0.5, fy=0.5))
bitwise_and
# bitwise_and(img1, img2 [, mask]) -> img2과 img2의 공통부분만 추출, 다른 부분은 0을 반환, mask=> 추출할 영역
# img1과 img2의 shape은 같아야 한다.
a = np.array([1, 2, 3, 100, 500])
b = np.array([100, 2, 300, 1, 500])
m = np.array([0, 255, 0, 0, 0], dtype='uint8') # mask: 이진마스크 - (0과 255 두 개 값으로 구성.) 결과는 255가 있는 index의 결과만 사용한다.
cv2.bitwise_and(a, b, mask=m)
'Data_Analysis_Track_33 > Python' 카테고리의 다른 글
| Python_Computer_vision_04(yolov8_pose) (0) | 2023.11.10 |
|---|---|
| Python_Computer_vision_02(yolov8_customdataset_train 실습) (0) | 2023.11.08 |
| Python_Computer_vision_01(yolov8_object_detection) (0) | 2023.11.08 |
| Python_Deeplearning_pytorch_12(DCGan_실습) (1) | 2023.11.03 |
| Python_Deeplearning_pytorch_11(LSTM을 활용한 주가예측) (1) | 2023.11.03 |