PyTorch图像分割模型——segmentation_models_pytorch库的使用

本文介绍了如何使用segmentation_models_pytorch库在PyTorch中训练UNet++模型进行图像分割。该库提供高级API,支持多种模型架构和预训练编码器。作者详细展示了训练过程,包括环境配置、数据集准备、模型创建、图像增强、损失函数、优化器和训练循环。此外,还展示了模型测试和实际应用,验证了模型在车辆检测上的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、概要

segmentation_models_pytorch是一个基于PyTorch的图像分割神经网络

这个新集合由俄罗斯的程序员小哥Pavel Yakubovskiy一手打造,对于图像分割而言简直就是神器般的存在。
github地址:https://github.com/qubvel/segmentation_models.pytorch

该库的主要功能有:

  1. 高级API(只需两行即可创建神经网络);
  2. 用于二分类和多类分割的9种模型架构(包括传奇的Unet)(Unet、Unet++、MAnet、Linknet、FPN、PSPNet、PAN、DeepLabV3、DeepLabV3+);
  3. 每种架构有113种可用的编码器;
  4. 所有编码器均具有预训练的权重,以实现更快更好的收敛。

这篇文章我主要介绍UNet++模型的训练和检测,UNet在图像分割中已经足够传奇,可以利用底层的特征(同分辨率级联)改善上采样的信息不足,对训练所要求的数据集并不是特别大,而且准确率也相当的高,UNet++又在UNet的基础上增加了剪枝的操作配合深监督,整合不同层次的特征以提升精度,且减少了图像分割所用的时间,只是在内存的要求上相应的增加了些。关于UNet和UNet++具体的解读可参考这两篇文章:
UNET详解和UNET++介绍(零基础)
[论文解读]UNet++解读 + 它是如何对UNet改进 + 作者的研究态度和方式

话不多说,我们开始基于segmentation_models_pytorch库进行UNet++模型训练。

二、环境配置

首先我们需创建一个虚拟环境,我这里采用的是python3.7版本。

conda create -n segmentation python==3.7

创建好后进入segmentation虚拟环境,并安装我们这里要用的图像分割神器segmentation-models-pytorch。

pip install segmentation-models-pytorch

安装segmentation-models-pytorch会一同安装上torch和torchvision,但是这时要注意了,这里安装进去的是CPU版的而且是最新版的pytorch,如果你确实打算用cpu来做的话那后面的也可以忽略,但是做目标检测和图像分割不用GPU简直没有灵魂啊,而且也为了方便我们同目标检测的神经网络结合,所以我们在segmentation-models-pytorch安装好后要先卸载掉torch和torchvision,然后再安装相应的cuda版本的torch和torchvision。我电脑采用的是cuda11.0,所以首先下载后对应cuda11.0的torch和torchvision,并进行安装。我这里采用的是下载好的离线安装包。

pip install torch-1.7.1+cu110-cp37-cp37m-win_amd64.whl
pip install torchvision-0.8.2+cu110-cp37-cp37m-win_amd64.whl

安装好后虚拟环境中的pytorch如下图所示。
在这里插入图片描述
同时,我们还需安装以下库:

pip install albumentations
pip install matplotlib
pip install imageio
pip install opencv-python

安装好后,虚拟环境中所含的库如下图所示。
在这里插入图片描述
此时,我们的前期工作就准备好了,接下来开始图像分割模型的训练和测试。

三、segmentation_models_pytorch库之UNet++模型训练

3.1 UNet++训练

首先我们看一下segmentation_models_pytorch库是怎么使用他所包含的9种模型的。

由于该库是基于PyTorch框架构建的,因此创建的细分模型只是一个PyTorch nn.Module,可以轻松地创建它。

import segmentation_models_pytorch as smp

model = smp.UnetPlusPlus(
    encoder_name="resnet34",        # 选择解码器, 例如 mobilenet_v2 或 efficientnet-b7
    encoder_weights="imagenet",     # 使用预先训练的权重imagenet进行解码器初始化
    in_channels=1,                  # 模型输入通道(1个用于灰度图像,3个用于RGB等)
    classes=3,                      # 模型输出通道(数据集所分的类别总数)
)

如果要使用UNet、FPN等模型,只要改成model = smp.Unet()或model = smp.FPN()即可。

所有模型均具有预训练的编码器,因此必须按照权重预训练的相同方法准备数据。

from segmentation_models_pytorch.encoders import get_preprocessing_fn

preprocess_input = get_preprocessing_fn('resnet18', pretrained='imagenet')

授人以鱼不如授人以渔,放出了9种模型还不算,俄罗斯大神还贴心地提供了如何使用CamVid数据集进行训练的示例(详情可见segmentation_models_pytorch在GitHub中的examples/cars segmentation (camvid).ipynb)。

CamVid数据集是计算机视觉领域常用的一个数据集,拥有汽车、建筑、人行道、云、树等12种不同的类别,通常用来进行街景分割。方便起见,我们从GitHub上拿来一套已经标注好的图像分割的数据集来进行训练和测试,下载地址:CamVid数据集

这里尤其要注意的是我们训练所用的数据集,不管是原图还是含有标注信息的图像,都必须是png格式,因为png图像可以做到无损压缩,能在保证最不失真的情况下尽可能压缩图像文件的大小。我们从CamVid数据集中所下载的数据也都是png格式的。

segmentation包含9种用于二分类和多类分割的模型架构,这里我们只采用UNet++,并使用了se_resnext50_32x4d这个预训练骨干模型。

训练UNet++模型的代码如下所示:

import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'

import numpy as np
import cv2
import matplotlib.pyplot as plt
import albumentations as albu
import torch
import segmentation_models_pytorch as smp
from torch.utils.data import DataLoader
from torch.utils.data import Dataset as BaseDataset


# ---------------------------------------------------------------
### 加载数据

class Dataset(BaseDataset):
    """CamVid数据集。进行图像读取,图像增强增强和图像预处理.

    Args:
        images_dir (str): 图像文件夹所在路径
        masks_dir (str): 图像分割的标签图像所在路径
        class_values (list): 用于图像分割的所有类别数
        augmentation (albumentations.Compose): 数据传输管道
        preprocessing (albumentations.Compose): 数据预处理
    """
	# CamVid数据集中用于图像分割的所有标签类别
    CLASSES = ['sky', 'building', 'pole', 'road', 'pavement',
               'tree', 'signsymbol', 'fence', 'car',
               'pedestrian', 'bicyclist', 'unlabelled']

    def __init__(
            self,
            images_dir,
            masks_dir,
            classes=None,
            augmentation=None,
            preprocessing=None,
    ):
        self.ids = os.listdir(images_dir)
        self.images_fps = [os.path.join(images_dir, image_id) for image_id in self.ids]
        self.masks_fps = [os.path.join(masks_dir, image_id) for image_id in self.ids]

        # convert str names to class values on masks
        self.class_values = [self.CLASSES.index(cls.lower()) for cls in classes]

        self.augmentation = augmentation
        self.preprocessing = preprocessing

    def __getitem__(self, i):

        # read data
        image = cv2.imread(self.images_fps[i])
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        mask = cv2.imread(self.masks_fps[i], 0)

        # 从标签中提取特定的类别 (e.g. cars)
        masks = [(mask == v) for v in self.class_values]
        mask = np.stack(masks, axis=-1).astype('float')

        # 图像增强应用
        if self.augmentation:
            sample = self.augmentation(image=image, mask=mask)
            image, mask = sample['image'], sample['mask']

        # 图像预处理应用
        if self.preprocessing:
            sample = self.preprocessing(image=image, mask=mask)
            image, mask = sample['image'], sample['mask']

        return image, mask

    def __len__(self):
        return len(self.ids)

# ---------------------------------------------------------------
### 图像增强

def get_training_augmentation():
    train_transform = [

        albu.HorizontalFlip(p=0.5),

        albu.ShiftScaleRotate(scale_limit=0.5, rotate_limit=0, shift_limit=0.1, p=1, border_mode=0),

        albu.PadIfNeeded(min_height=320, min_width=320, always_apply=True, border_mode=0),
        albu.RandomCrop(height=320, width=320, always_apply=True),

        albu.IAAAdditiveGaussianNoise(p=0.2),
        albu.IAAPerspective(p=0.5),

        albu.OneOf(
            [
                albu.CLAHE(p=1),
                albu.RandomBrightness(p=1),
                albu.RandomGamma(p=1),
            ],
            p=0.9,
        ),

        albu.OneOf(
            [
                albu.IAASharpen(p=1),
                albu.Blur(blur_limit=3, p=1),
                albu.MotionBlur(blur_limit=3, p=1),
            ],
            p=0.9,
        ),

        albu.OneOf(
            [
                albu.RandomContrast(p=1),
                albu.HueSaturationValue(p=1),
            ],
            p=0.9,
        ),
    ]
    return albu.Compose(train_transform)


def get_validation_augmentation():
    """调整图像使得图片的分辨率长宽能被32整除"""
    test_transform = [
        albu.PadIfNeeded(384, 480)
    ]
    return albu.Compose(test_transform)


def to_tensor(x, **kwargs):
    return x.transpose(2, 0, 1).astype('float32')


def get_preprocessing(preprocessing_fn):
    """进行图像预处理操作

    Args:
        preprocessing_fn (callbale): 数据规范化的函数
            (针对每种预训练的神经网络)
    Return:
        transform: albumentations.Compose
    """

    _transform = [
        albu.Lambda(image=preprocessing_fn),
        albu.Lambda(image=to_tensor, mask=to_tensor),
    ]
    return albu.Compose(_transform)


#$# 创建模型并训练
# ---------------------------------------------------------------
if __name__ == '__main__':
	
	# 数据集所在的目录
    DATA_DIR = './data/CamVid/'

    # 如果目录下不存在CamVid数据集,则克隆下载
    if not os.path.exists(DATA_DIR):
        print('Loading data...')
        os.system('git clone https://github.com/alexgkendall/SegNet-Tutorial ./data')
        print('Done!')

    # 训练集
    x_train_dir = os.path.join(DATA_DIR, 'train')
    y_train_dir = os.path.join(DATA_DIR, 'trainannot')

    # 验证集
    x_valid_dir = os.path.join(DATA_DIR, 'val')
    y_valid_dir = os.path.join(DATA_DIR, 'valannot')

    ENCODER = 'se_resnext50_32x4d'
    ENCODER_WEIGHTS = 'imagenet'
    CLASSES = ['car']
    ACTIVATION = 'sigmoid' # could be None for logits or 'softmax2d' for multiclass segmentation
    DEVICE = 'cuda'

    # 用预训练编码器建立分割模型
    # 使用FPN模型
    # model = smp.FPN(
    #     encoder_name=ENCODER,
    #     encoder_weights=ENCODER_WEIGHTS,
    #     classes=len(CLASSES),
    #     activation=ACTIVATION,
    # )
    # 使用unet++模型
    model = smp.UnetPlusPlus(
        encoder_name=ENCODER,
        encoder_weights=ENCODER_WEIGHTS,
        classes=len(CLASSES),
        activation=ACTIVATION,
    )

    preprocessing_fn = smp.encoders.get_preprocessing_fn(ENCODER, ENCODER_WEIGHTS)
	
	# 加载训练数据集
    train_dataset = Dataset(
        x_train_dir,
        y_train_dir,
        augmentation=get_training_augmentation(),
        preprocessing=get_preprocessing(preprocessing_fn),
        classes=CLASSES,
    )

	# 加载验证数据集
    valid_dataset = Dataset(
        x_valid_dir,
        y_valid_dir,
        augmentation=get_validation_augmentation(),
        preprocessing=get_preprocessing(preprocessing_fn),
        classes=CLASSES,
    )

	# 需根据显卡的性能进行设置,batch_size为每次迭代中一次训练的图片数,num_workers为训练时的工作进程数,如果显卡不太行或者显存空间不够,将batch_size调低并将num_workers调为0
    train_loader = DataLoader(train_dataset, batch_size=2, shuffle=True, num_workers=0)
    valid_loader = DataLoader(valid_dataset, batch_size=1, shuffle=False, num_workers=0)

    loss = smp.utils.losses.DiceLoss()
    metrics = [
        smp.utils.metrics.IoU(threshold=0.5),
    ]

    optimizer = torch.optim.Adam([
        dict(params=model.parameters(), lr=0.0001),
    ])

    # 创建一个简单的循环,用于迭代数据样本
    train_epoch = smp.utils.train.TrainEpoch(
        model,
        loss=loss,
        metrics=metrics,
        optimizer=optimizer,
        device=DEVICE,
        verbose=True,
    )

    valid_epoch = smp.utils.train.ValidEpoch(
        model,
        loss=loss,
        metrics=metrics,
        device=DEVICE,
        verbose=True,
    )

    # 进行40轮次迭代的模型训练
    max_score = 0

    for i in range(0, 40):

        print('\nEpoch: {}'.format(i))
        train_logs = train_epoch.run(train_loader)
        valid_logs = valid_epoch.run(valid_loader)
		
		# 每次迭代保存下训练最好的模型
        if max_score < valid_logs['iou_score']:
            max_score = valid_logs['iou_score']
            torch.save(model, './best_model.pth')
            print('Model saved!')

        if i == 25:
            optimizer.param_groups[0]['lr'] = 1e-5
            print('Decrease decoder learning rate to 1e-5!')

这里我们只训练 ‘car’ 的类别进行图像分割,设置好数据集后开始训练,训练场景如图所示。
在这里插入图片描述

因为数据集量并不大,40轮次的训练很快就结束了,此时在文件夹中出现一个 best_model.pth 的文件,即我们迭代40轮次训练后得到的最好的模型。

3.2 UNet++测试

训练好后我们开始测试UNet++所训练的最好的那个模型,测试代码如下:

import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'

import numpy as np
import cv2
import matplotlib.pyplot as plt
import albumentations as albu
import torch
import segmentation_models_pytorch as smp
from torch.utils.data import Dataset as BaseDataset


# ---------------------------------------------------------------
### 加载数据

class Dataset(BaseDataset):
    """CamVid数据集。进行图像读取,图像增强增强和图像预处理.

    Args:
        images_dir (str): 图像文件夹所在路径
        masks_dir (str): 图像分割的标签图像所在路径
        class_values (list): 用于图像分割的所有类别数
        augmentation (albumentations.Compose): 数据传输管道
        preprocessing (albumentations.Compose): 数据预处理
    """
    # CamVid数据集中用于图像分割的所有标签类别
    CLASSES = ['sky', 'building', 'pole', 'road', 'pavement',
               'tree', 'signsymbol', 'fence', 'car',
               'pedestrian', 'bicyclist', 'unlabelled']

    def __init__(
            self,
            images_dir,
            masks_dir,
            classes=None,
            augmentation=None,
            preprocessing=None,
    ):
        self.ids = os.listdir(images_dir)
        self.images_fps = [os.path.join(images_dir, image_id) for image_id in self.ids]
        self.masks_fps = [os.path.join(masks_dir, image_id) for image_id in self.ids]

        # convert str names to class values on masks
        self.class_values = [self.CLASSES.index(cls.lower()) for cls in classes]

        self.augmentation = augmentation
        self.preprocessing = preprocessing

    def __getitem__(self, i):

        # read data
        image = cv2.imread(self.images_fps[i])
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        mask = cv2.imread(self.masks_fps[i], 0)

        # 从标签中提取特定的类别 (e.g. cars)
        masks = [(mask == v) for v in self.class_values]
        mask = np.stack(masks, axis=-1).astype('float')

        # 图像增强应用
        if self.augmentation:
            sample = self.augmentation(image=image, mask=mask)
            image, mask = sample['image'], sample['mask']

        # 图像预处理应用
        if self.preprocessing:
            sample = self.preprocessing(image=image, mask=mask)
            image, mask = sample['image'], sample['mask']

        return image, mask

    def __len__(self):
        return len(self.ids)


# ---------------------------------------------------------------
### 图像增强

def get_validation_augmentation():
    """调整图像使得图片的分辨率长宽能被32整除"""
    test_transform = [
        albu.PadIfNeeded(384, 480)
    ]
    return albu.Compose(test_transform)


def to_tensor(x, **kwargs):
    return x.transpose(2, 0, 1).astype('float32')


def get_preprocessing(preprocessing_fn):
    """进行图像预处理操作

    Args:
        preprocessing_fn (callbale): 数据规范化的函数
            (针对每种预训练的神经网络)
    Return:
        transform: albumentations.Compose
    """

    _transform = [
        albu.Lambda(image=preprocessing_fn),
        albu.Lambda(image=to_tensor, mask=to_tensor),
    ]
    return albu.Compose(_transform)


# 图像分割结果的可视化展示
def visualize(**images):
    """PLot images in one row."""
    n = len(images)
    plt.figure(figsize=(16, 5))
    for i, (name, image) in enumerate(images.items()):
        plt.subplot(1, n, i + 1)
        plt.xticks([])
        plt.yticks([])
        plt.title(' '.join(name.split('_')).title())
        plt.imshow(image)
    plt.show()


# ---------------------------------------------------------------
if __name__ == '__main__':

    DATA_DIR = './data/CamVid/'

    # 测试集
    x_test_dir = os.path.join(DATA_DIR, 'test')
    y_test_dir = os.path.join(DATA_DIR, 'testannot')

    ENCODER = 'se_resnext50_32x4d'
    ENCODER_WEIGHTS = 'imagenet'
    CLASSES = ['car']
    ACTIVATION = 'sigmoid' # could be None for logits or 'softmax2d' for multiclass segmentation
    DEVICE = 'cuda'

    preprocessing_fn = smp.encoders.get_preprocessing_fn(ENCODER, ENCODER_WEIGHTS)
    # ---------------------------------------------------------------
    #$# 测试训练出来的最佳模型

    # 加载最佳模型
    best_model = torch.load('./best_model.pth')

    # 创建测试数据集
    test_dataset = Dataset(
        x_test_dir,
        y_test_dir,
        augmentation=get_validation_augmentation(),
        preprocessing=get_preprocessing(preprocessing_fn),
        classes=CLASSES,
    )

    # ---------------------------------------------------------------
    #$# 图像分割结果可视化展示
    # 对没有进行图像处理转化的测试集进行图像可视化展示
    test_dataset_vis = Dataset(
        x_test_dir, y_test_dir,
        classes=CLASSES,
    )
	# 从测试集中随机挑选3张图片进行测试
    for i in range(3):
        n = np.random.choice(len(test_dataset))

        image_vis = test_dataset_vis[n][0].astype('uint8')
        image, gt_mask = test_dataset[n]

        gt_mask = gt_mask.squeeze()

        x_tensor = torch.from_numpy(image).to(DEVICE).unsqueeze(0)
        pr_mask = best_model.predict(x_tensor)
        pr_mask = (pr_mask.squeeze().cpu().numpy().round())

        visualize(
            image=image_vis,
            ground_truth_mask=gt_mask,
            predicted_mask=pr_mask
        )

这里我们也只针对 ‘car’ 的类别进行图像分割测试,运行代码后测试场景如图所示。左边为原图,中间为标注的图像分割场景,右边为测试的图像分歌结果,可以看出测试的结果和标注的图像分割场景还是很相似的,说明训练结果还不错。
在这里插入图片描述

在这里插入图片描述

3.3 UNet++图像分割检测

通过测试后,我们可以使用我们训练好后UNet++模型,进行图像分割的实际操作。检测代码如下:

import os
os.environ['CUDA_VISIBLE_DEVICES'] = '0'

import numpy as np
import cv2
import matplotlib.pyplot as plt
import albumentations as albu
import torch
import segmentation_models_pytorch as smp
from torch.utils.data import Dataset as BaseDataset
import imageio


# ---------------------------------------------------------------
### Dataloader

class Dataset(BaseDataset):
    """CamVid数据集。进行图像读取,图像增强增强和图像预处理.

    Args:
        images_dir (str): 图像文件夹所在路径
        masks_dir (str): 图像分割的标签图像所在路径
        class_values (list): 用于图像分割的所有类别数
        augmentation (albumentations.Compose): 数据传输管道
        preprocessing (albumentations.Compose): 数据预处理
    """
    # CamVid数据集中用于图像分割的所有标签类别
    CLASSES = ['sky', 'building', 'pole', 'road', 'pavement',
               'tree', 'signsymbol', 'fence', 'car',
               'pedestrian', 'bicyclist', 'unlabelled']

    def __init__(
            self,
            images_dir,
            # masks_dir,
            classes=None,
            augmentation=None,
            preprocessing=None,
    ):
        self.ids = os.listdir(images_dir)
        self.images_fps = [os.path.join(images_dir, image_id) for image_id in self.ids]

        # convert str names to class values on masks
        self.class_values = [self.CLASSES.index(cls.lower()) for cls in classes]

        self.augmentation = augmentation
        self.preprocessing = preprocessing

    def __getitem__(self, i):

        # read data
        image = cv2.imread(self.images_fps[i])
        image = cv2.resize(image, (480, 384))   # 改变图片分辨率
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)

        # 图像增强应用
        if self.augmentation:
            sample = self.augmentation(image=image)
            image = sample['image']

        # 图像预处理应用
        if self.preprocessing:
            sample = self.preprocessing(image=image)
            image = sample['image']

        return image

    def __len__(self):
        return len(self.ids)

# ---------------------------------------------------------------

def get_validation_augmentation():
    """调整图像使得图片的分辨率长宽能被32整除"""
    test_transform = [
        albu.PadIfNeeded(384, 480)
    ]
    return albu.Compose(test_transform)


def to_tensor(x, **kwargs):
    return x.transpose(2, 0, 1).astype('float32')


def get_preprocessing(preprocessing_fn):
    """进行图像预处理操作

    Args:
        preprocessing_fn (callbale): 数据规范化的函数
            (针对每种预训练的神经网络)
    Return:
        transform: albumentations.Compose
    """

    _transform = [
        albu.Lambda(image=preprocessing_fn),
        albu.Lambda(image=to_tensor),
    ]
    return albu.Compose(_transform)


# 图像分割结果的可视化展示
def visualize(**images):
    """PLot images in one row."""
    n = len(images)
    plt.figure(figsize=(16, 5))
    for i, (name, image) in enumerate(images.items()):
        plt.subplot(1, n, i + 1)
        plt.xticks([])
        plt.yticks([])
        plt.title(' '.join(name.split('_')).title())
        plt.imshow(image)
    plt.show()


# ---------------------------------------------------------------
if __name__ == '__main__':

    DATA_DIR = './data/CamVid/'

    x_test_dir = os.path.join(DATA_DIR, 'abc')

    img_test = cv2.imread('data/CamVid/abc/car_test.jpg')
    height = img_test.shape[0]
    weight = img_test.shape[1]

    ENCODER = 'se_resnext50_32x4d'
    ENCODER_WEIGHTS = 'imagenet'
    CLASSES = ['car']
    ACTIVATION = 'sigmoid' # could be None for logits or 'softmax2d' for multiclass segmentation
    DEVICE = 'cuda'

    # 按照权重预训练的相同方法准备数据
    preprocessing_fn = smp.encoders.get_preprocessing_fn(ENCODER, ENCODER_WEIGHTS)

    # 加载最佳模型
    best_model = torch.load('./best_model.pth')

    # 创建检测数据集
    predict_dataset = Dataset(
        x_test_dir,
        augmentation=get_validation_augmentation(),
        preprocessing=get_preprocessing(preprocessing_fn),
        classes=CLASSES,
    )

    # 对检测图像进行图像分割并进行图像可视化展示
    predict_dataset_vis = Dataset(
        x_test_dir,
        classes=CLASSES,
    )

    for i in range(len(predict_dataset)):
        # 原始图像image_vis
        image_vis = predict_dataset_vis[i].astype('uint8')
        image = predict_dataset[i]

        # 通过图像分割得到的0-1图像pr_mask
        x_tensor = torch.from_numpy(image).to(DEVICE).unsqueeze(0)
        pr_mask = best_model.predict(x_tensor)
        pr_mask = (pr_mask.squeeze().cpu().numpy().round())
        print(pr_mask.shape)

        # 恢复图片原来的分辨率
        image_vis = cv2.resize(image_vis, (weight, height))
        pr_mask = cv2.resize(pr_mask, (weight, height))
        # 保存图像分割后的黑白结果图像
        imageio.imwrite('car_test_out.png', pr_mask)
        # 原始图像和图像分割结果的可视化展示
        visualize(
            image=image_vis,
            predicted_mask=pr_mask
        )

这里我采用了一张大桥上车辆的图片进行图像分割检测,检测结果如图所示:
在这里插入图片描述
这里我们可以看出只检测出了两辆车,说明我们更换检测场景后,检测的结果并不是很令人满意,但整体思路是没有问题的。如需应用在实际场景下,还需针对实际场景的数据集进行相应的训练。

好了,到底为止,使用segmentation_models_pytorch库进行UNet++图像分割模型训练的使用方法就到此结束,是不是很easy,那还不赶快去GitHub给这位俄罗斯大神点个星!

<think>好的,用户现在想了解如何在Miniconda的虚拟环境下安装`segmentation-models-pytorch`这个包。我需要仔细思考他的需求,可能存在的疑问以及如何一步步指导他完成安装。 首先,用户可能已经知道一些基本的conda命令,但不确定具体步骤。他可能是在使用conda创建的环境中进行开发,需要确保包安装在正确的环境中。可能的问题包括如何激活虚拟环境,如何正确使用pip安装,以及可能遇到的依赖问题。 我需要分步骤解释整个过程。首先,确保conda已经安装,这应该是用户已经具备的条件。然后,创建并激活虚拟环境,这样安装的包才会被隔离在该环境中。接下来,使用pip安装指定的包,这里需要提醒用户注意虚拟环境是否激活,避免安装到全局环境中。 另外,用户提到的包`segmentation-models-pytorch`可能依赖PyTorch,而PyTorch通常建议通过conda安装以获得更好的兼容性,尤其是在不同平台上。因此,可能需要建议用户先安装PyTorch,再安装这个包。但用户的问题直接是关于用pip安装的,所以需要明确说明是否需要先安装PyTorch,或者pip是否会自动处理依赖。 可能用户没有意识到,直接使用pip安装可能会缺少一些系统依赖,比如在某些情况下需要安装CUDA或cuDNN。但大部分时候,PyTorch的pip版本会包含必要的二进制文件。不过,用户如果遇到问题,可能需要进一步指导,比如安装正确版本的PyTorch。 另外,用户可能是在Windows、Linux还是MacOS下操作?不同系统下conda的使用略有不同,但基本命令是相同的。所以不需要特别区分,除非用户遇到特定系统的问题。 还要考虑到用户可能希望验证安装是否成功,所以需要建议如何通过Python命令行导入包来测试。 总结回答的步骤应该是: 1. 创建conda虚拟环境(如果尚未创建)。 2. 激活环境。 3. 使用pip安装包。 4. 验证安装。 同时,需要提醒用户注意点,比如环境激活的重要性,依赖项的处理,以及可能的PyTorch安装建议。另外,如果用户遇到权限问题,可能需要使用`--user`选项或者以管理员权限运行命令,但conda环境通常不需要。 最后,保持回答简洁明了,避免技术术语过多,让用户能够轻松跟随步骤操作。</think>以下是使用 Miniconda 虚拟环境直接安装 `segmentation-models-pytorch` 的详细步骤: --- ### **1. 创建并激活虚拟环境** - **新建环境**(可选,如果已有环境可跳过): ```bash conda create -n myenv python=3.8 # 创建一个名为 `myenv` 的虚拟环境,Python版本建议3.6+ ``` - **激活环境**: ```bash conda activate myenv # Windows/Linux/macOS 通用 ``` --- ### **2. 安装 PyTorch(推荐先通过 Conda 安装)** `segmentation-models-pytorch` 依赖 PyTorch,建议先安装与你的 CUDA 版本匹配的 PyTorch: ```bash conda install pytorch torchvision torchaudio cudatoolkit=11.3 -c pytorch # 根据你的 CUDA 版本调整参数 ``` - 如果没有 GPU,使用 CPU 版本: ```bash conda install pytorch torchvision torchaudio cpuonly -c pytorch ``` --- ### **3. 使用 pip 安装 segmentation-models-pytorch** 在激活的虚拟环境中直接运行: ```bash pip install segmentation-models-pytorch ``` --- ### **4. 验证安装** 在 Python 中导入包,检查是否报错: ```python import segmentation_models_pytorch as smp print(smp.__version__) # 输出版本号(如 0.3.0) ``` --- ### **常见问题** 1. **依赖冲突**: - 如果报错 `Could not build wheels for XXX`,尝试更新 pip: ```bash pip install --upgrade pip ``` - 安装依赖(如 OpenCV): ```bash conda install opencv # 或 pip install opencv-python ``` 2. **PyTorch 版本不匹配**: - 卸载冲突版本后重新安装: ```bash pip uninstall torch torchvision conda install pytorch torchvision ... # 根据官方命令安装 ``` --- ### **总结** - 通过 Conda 管理虚拟环境和 PyTorch 依赖,避免版本冲突。 - 使用 `pip` 在激活的虚拟环境中直接安装目标包。 - 如果安装失败,优先检查 PyTorch 和 CUDA 版本是否匹配。 遇到具体问题可补充说明,我会进一步协助! 🚀
评论 30
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值