那么,实例分割有什么用呢,最直观的应用便是抠图了,我们将语义分割的预测代码修改一下,就可以实现抠图了,步骤如下:
- 调用语义分割模型,获取结果
result
- 拆分
result
,因为result中含有目标检测的box
、类别等诸多信息,我们只需要得到masks
即可 - 将
masks
循环遍历,在这里我们可以对选择扣出哪些目标,如人或是车辆(通过读取box
中的cls
可以知道其类别编号,通过读取result
中的names
属性可以对应类别与编号 - 利用感兴趣区域来分割出相应目标,其余部分设置为黑色,当然也可以设置为透明
import cv2
import numpy as np
from ultralytics import YOLO
if __name__ == "__main__":
model = YOLO("yolov8n-seg.pt")
img = cv2.imread("1.jpg")
img=cv2.resize(img,(640,640))
result = model(img)
result=result[0]
names = result.names
boxes = result.boxes.data.tolist()
masks = result.masks
image=np.zeros_like(img)
for i, mask in enumerate(masks):
mask = masks.data[i].cpu().numpy().astype(np.bool_)
image[mask]=img[mask]
cv2.imwrite("predict.jpg", image)
print("save done")
抠图效果如下:
下面的代码是只抠出人物,并且背景透明。
关于图像透明,需要注意的几点:
- 在图形图像学中,透明通道也称
Alpha
通道,代表数字图像中像素点的透明信息。白色的Alpha
像素用以定义不透明的彩色像素,而黑色的Alpha
定以透明像素,黑白之间的灰阶则是彩色图片中的半透明部分。 - 只有
png
和gif
格式能保存透明信息,像BMP
、JPG
格式的图片是不能保存透明信息的。
import cv2
import numpy as np
from ultralytics import YOLO
if __name__ == "__main__":
model = YOLO("yolov8n-seg.pt")
img = cv2.imread("3.jpg")
img=cv2.resize(img,(640,640))
result = model(img)
result=result[0]
names = result.names
cls=result.boxes.cls
boxes = result.boxes.data.tolist()
masks = result.masks
masked_image_rgba=cv2.cvtColor(img,cv2.COLOR_BGR2BGRA)#添加alpha通道
mask_save = np.zeros((640,640)).astype(np.bool_)
for i, mask in enumerate(masks):
if cls[i]==0:
mask=masks.data[i].cpu().numpy().astype(np.bool_)
mask_save=mask_save|mask
else:
continue
masked_image_rgba[~mask_save] = (0,0,0,0) # 将非掩码区域设置为透明
cv2.imwrite("predict.jpg", masked_image_rgba)
print("save done")