win11配置Mask DINO小白踩坑记录


前情提要:需要复现Mask DINO,但是实验室没有Linux的电脑,在Windows上复现的时候遇到了 No moduld name MultiScaleDeformableAttention,然后看博客说在Windows上配置很麻烦,建议去Linux,但是虚拟机没办法用GPU,想到了三个方法:1、用WSL2来运行;2、在Windows上解决这个困难;3、装双系统。
我首先试了方法1,碰到了一开始的问题,而且也比较麻烦,所以干脆进行了2,网上一些方法写的比较简略,但是我实际运行过程中碰到了很多问题,所以记录一下。
PS:如果是已经conda create一个环境了,建议查看版本是否正确,如果是直接在项目下运行了pip install -r requirement.txt,就重头开始

参考:Mask DINO环境配置
参考:win10系统配置Mask DINO经验总结
参考:Detectron2在Windows上的三部曲——安装
[参考:panopticapi库的安装](https://blog.csdn.net/None__None/article/details/135442575)
参考:【实例分割(一)】Detectron2 数据集制作并注册数据集训练

参考:detectron2 中 demo 可视化添加置信度阈值

1 准备工作

名称版本号
cuda11.3
cudnncuda11对应最新版即可
pytorch1.10.1
torchvision0.11.2
torchaudio0.10.1

2 创建python环境和安装detectron2


conda create -n env_name python=3.9
conda activate env_name
conda install pytorch==1.10.1 torchvision==0.11.2 torchaudio==0.10.1 cudatoolkit=11.3 -c pytorch -c conda-forge
 
#安装detectron2
git clone https://github.com/facebookresearch/detectron2.git
python -m pip install -e detectron2

如果conda安装慢,记得换源
安装detectron2开始出问题了

2.1 安装前提

需要安装Visual Studio,VS的版本一定要version<=2019,之前安装的VS2022死活安不上。
并且一定要把原来的VS2022删掉,否则会报错,安装了VS2019需要配置cl.exe的环境变量,请看2.2.1

2.2 安装流程

git clone https://github.com/facebookresearch/detectron2.git

Detectron2前将fvcore安装上

pip install fvcore
python setup.py install

成功安装结果:
在这里插入图片描述

2.2.1 cl.exe的错误

至此安装完成detectron2,我一开始没有安装,所以报错'cl.exe' is not recognized as an internal or external command
这是因为VS的cl.exe这个编译器未被加入到环境变量中,可以“编辑环境变量-环境变量-系统变量-PATH“, 添加路径**“path\to\vs2019\community\vc\tools\msvc\14.13.26128\bin\hostx64\x64"** 大概是这个路径,自行去找自己的路径。(VS2022是没有这个路径的)

安装完detectron2,再继续安装mask dino一开始遇到的问题都解决了

2.2.2 SetuptoolsDeprecationWarning的错误

错误内容:
SetuptoolsDeprecationWarning: setup.py install is deprecated. !! ********************************************************************************

Please avoid running setup.py directly. Instead, use pypa/build, pypa/installer or other standards-based tools. See https://blog.ganssle.io/articles/2021/10/setup-py-deprecated.html for details.
**解决:我的原因是setuptools版本太高
首先使用以下命令查看setuptools版本信息

conda list

发现setuptools版本大于60,可能因为版本过高,算法使用的安装方式已经被弃用,选择重新安装小于60的版本,解决了此问题。

pip install setuptools==58

**

3 MaskDINO运行

#克隆maskdino库
git clone https://github.com/IDEA-Research/MaskDINO.git
cd ./MaskDINO
pip install -r requirements.txt

注意是requirements.txt,有无s
成功结果:
在这里插入图片描述
再接下来

cd maskdino/modeling/pixel_decoder/ops
python setup.py build install

(这里碰到了没有删除vs2022遇到的错,卸载了就没有报错了)
运行的时候出现了一大串类似于报错的信息,但是等待就好了
成功结果:
在这里插入图片描述

3.1 运行demo

退回到根目录 \MaskDINO-main,在根目录创建img和weight文件夹,并在img中放入测试图片,weight中放入权重:自行下载

python .\demo\demo.py --config-file .\configs\coco\instance-segmentation\maskdino_R50_bs16_50ep_3s.yaml --input .\img\1.jpg --output .\img\2.jpg --opts MODEL.WEIGHTS .\weight\maskdino_r50_50ep_300q_hid1024_3sd1_instance_maskenhanced_mask46.1ap_box51.5ap.pth

4 训练自己的数据集

4.1 panopticapi库的安装

在这里插入图片描述
不能直接用上述代码安装panopticapi库
方法:
首先克隆代码

git clone https://github.com/cocodataset/panopticapi.git

目录在项目同文件夹就行
在这里插入图片描述
终端进入conda创建的虚拟环境,并用cd panopticapi进入文件夹

python setup.py build_ext --inplace  
python setup.py build_ext install

4.2 训练自己标注的labelme数据集

前置条件:已经将数据集转换成coco格式的数据集了
没有转换,请看博客:labelme标注的json文件数据转成coco数据集格式(可处理目标框和实例分割)

条件:只用自己的笔记本电脑 8G GPU跑
在这里插入图片描述
在train_net.py文件下加入注册数据集的代码,在main函数上方添加即可

class Register:
    """用于注册自己的数据集"""
    CLASS_NAMES = ['__background__', '1']
    ROOT = r"D:\ 图片所在目录"

    def __init__(self):
        self.CLASS_NAMES = Register.CLASS_NAMES
        # 数据集路径
        self.ANN_ROOT = r"D:\ 图片所在目录\annotations"

        self.TRAIN_PATH = os.path.join(Register.ROOT, 'train')
        self.VAL_PATH = os.path.join(Register.ROOT, 'val')

        self.TRAIN_JSON = os.path.join(self.ANN_ROOT, 'annotations_train.json')
        self.VAL_JSON = os.path.join(self.ANN_ROOT, 'annotations_val.json')

        # TODO声明数据集的子集,需修改成自己的
        self.PREDEFINED_SPLITS_DATASET = {
            "coco_fish_train": (self.TRAIN_PATH, self.TRAIN_JSON),
            "coco_fish_val": (self.VAL_PATH, self.VAL_JSON),
        }

    def register_dataset(self):
        """ purpose: register all splits of datasets with PREDEFINED_SPLITS_DATASET 注册数据集(这一步就是将自定义数据集注册进Detectron2) """
        for key, (image_root, json_file) in self.PREDEFINED_SPLITS_DATASET.items():
            self.register_dataset_instances(name=key,
                                            json_file=json_file,
                                            image_root=image_root)

    @staticmethod
    def register_dataset_instances(name, json_file, image_root):
        """ purpose: register datasets to DatasetCatalog, register metadata to MetadataCatalog and set attribute 注册数据集实例,加载数据集中的对象实例 """
        DatasetCatalog.register(name, lambda: load_coco_json(json_file, image_root, name))
        MetadataCatalog.get(name).set(json_file=json_file,
                                      image_root=image_root,
                                      evaluator_type="coco")

    def plain_register_dataset(self):
        """注册数据集和元数据"""
        # 训练集
        DatasetCatalog.register("coco_fish_train", lambda: load_coco_json(self.TRAIN_JSON, self.TRAIN_PATH))
        MetadataCatalog.get("coco_fish_train").set(thing_classes=self.CLASS_NAMES,  # 可以选择开启,但是不能显示中文,这里需要注意,中文的话最好关闭
                                                 evaluator_type='coco',  # 指定评估方式
                                                 json_file=self.TRAIN_JSON,
                                                 image_root=self.TRAIN_PATH)

        # DatasetCatalog.register("coco_my_val", lambda: load_coco_json(VAL_JSON, VAL_PATH, "coco_2017_val"))
        # 验证/测试集
        DatasetCatalog.register("coco_fish_val", lambda: load_coco_json(self.VAL_JSON, self.VAL_PATH))
        MetadataCatalog.get("coco_fish_val").set(thing_classes=self.CLASS_NAMES,  # 可以选择开启,但是不能显示中文,这里需要注意,中文的话最好关闭
                                               evaluator_type='coco',  # 指定评估方式
                                               json_file=self.VAL_JSON,
                                               image_root=self.VAL_PATH)

    def checkout_dataset_annotation(self, name="coco_fish_val"):
        """ 查看数据集标注,可视化检查数据集标注是否正确, 这个也可以自己写脚本判断,其实就是判断标注框是否超越图像边界 可选择使用此方法 """
        # dataset_dicts = load_coco_json(TRAIN_JSON, TRAIN_PATH, name)
        dataset_dicts = load_coco_json(self.TRAIN_JSON, self.TRAIN_PATH)
        print(len(dataset_dicts))
        for i, d in enumerate(dataset_dicts, 0):
            # print(d)
            img = cv2.imread(d["file_name"])
            visualizer = Visualizer(img[:, :, ::-1], metadata=MetadataCatalog.get(name), scale=1.5)
            vis = visualizer.draw_dataset_dict(d)
            # cv2.imshow('show', vis.get_image()[:, :, ::-1])
            cv2.imwrite('./out/' + str(i) + '.jpg', vis.get_image()[:, :, ::-1])
            # cv2.waitKey(0)
            if i == 100:
                break

然后在配置文件yaml中修改train和val的名字,名字为自己定义的,运行

添加参数:--num-gpus 1 --config-file .\configs\coco\instance-segmentation\maskdino_R50_bs16_50ep_3s.yaml

至此,运行train_net.py结束。

4.3 可视化后图片效果不好改进方法

使用demo.py可视化后,得到的结果并不好,会出现很多置信度很低的框。
请添加图片描述

![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/420874c01fda4d848716f79316cf7877.jpeg
修改了NMS_THRESH_TEST、SCORE_THRESH_TEST等参数效果并不明显,还是会有很多框,参考了博客detectron2 中 demo 可视化添加置信度阈值的方法,并且自己修改了一些地方之后可以得到想要的结果。
步骤如下(前面一些步骤都是一样的):
1、设置置信度阈值(score_thredshold)部分代码

 if score_threshold != None:
     top_id = np.where(scores.numpy()>score_threshold)[0].tolist()
     scores = torch.tensor(scores.numpy()[top_id])
     boxes.tensor = torch.tensor(boxes.tensor.numpy()[top_id])
     classes = [classes[ii] for ii in top_id]
     labels = [labels[ii] for ii in top_id]

draw_instance_predictions 函数完整代码(修改后)
只需要把上面的代码复制粘帖到if predictions.has(“pred_masks”):之前就可以了
这个函数的位置是在 detectron2/utils/visualizer.py 里面

以上是博客的内容,只修改博客的内容会报错mask的数量与instance对不上,所以还要修改mask
最终代码

    def draw_instance_predictions(self, predictions, score_threshold=None, jittering: bool = True):
        """
        Draw instance-level prediction results on an image.

        Args:
            score_threshold: 置信度阈值(新增的参数)
            predictions (Instances): the output of an instance detection/segmentation
                model. Following fields will be used to draw:
                "pred_boxes", "pred_classes", "scores", "pred_masks" (or "pred_masks_rle").
            jittering: if True, in color mode SEGMENTATION, randomly jitter the colors per class
                to distinguish instances from the same class

        Returns:
            output (VisImage): image object with visualizations.
        """
        boxes = predictions.pred_boxes if predictions.has("pred_boxes") else None
        scores = predictions.scores if predictions.has("scores") else None
        classes = predictions.pred_classes.tolist() if predictions.has("pred_classes") else None
        labels = _create_text_labels(classes, scores, self.metadata.get("thing_classes", None))
        keypoints = predictions.pred_keypoints if predictions.has("pred_keypoints") else None
        top_id=[]
        # TODO:SYT
        '''新增的部分代码'''
        if score_threshold != None:
            top_id = np.where(scores.numpy() > score_threshold)[0].tolist()
            scores = torch.tensor(scores.numpy()[top_id])
            boxes.tensor = torch.tensor(boxes.tensor.numpy()[top_id])
            classes = [classes[ii] for ii in top_id]
            labels = [labels[ii] for ii in top_id]
            
        if predictions.has("pred_masks"):
            # TODO: 不修改mask会报错
            if len(top_id)!=0:
                mask_id = np.asarray(predictions.pred_masks)
                masks = [mask_id[i] for i in top_id]
                masks = [GenericMask(x, self.output.height, self.output.width) for x in masks]
            else:
                masks = np.asarray(predictions.pred_masks)
                masks = [GenericMask(x, self.output.height, self.output.width) for x in masks]
        else:
            masks = None

        if self._instance_mode == ColorMode.SEGMENTATION and self.metadata.get("thing_colors"):
            colors = [
                self._jitter([x / 255 for x in self.metadata.thing_colors[c]]) for c in classes
            ] if jittering else [
                tuple(
                    mplc.to_rgb([x / 255 for x in self.metadata.thing_colors[c]])
                ) for c in classes
            ]

            alpha = 0.8
        else:
            colors = None
            alpha = 0.5

        if self._instance_mode == ColorMode.IMAGE_BW:
            self.output.reset_image(
                self._create_grayscale_image(
                    (predictions.pred_masks.any(dim=0) > 0).numpy()
                    if predictions.has("pred_masks")
                    else None
                )
            )
            alpha = 0.3

        self.overlay_instances(
            masks=masks,
            boxes=boxes,
            labels=labels,
            keypoints=keypoints,
            assigned_colors=colors,
            alpha=alpha,
        )
        return self.output

在demo下的predictions.py文件中修改run_on_image函数,加上阈值

    def run_on_image(self, image):
        """
        Args:
            image (np.ndarray): an image of shape (H, W, C) (in BGR order).
                This is the format used by OpenCV.
        Returns:
            predictions (dict): the output of the model.
            vis_output (VisImage): the visualized image output.
        """
        vis_output = None
        predictions = self.predictor(image)
        # Convert image from OpenCV BGR format to Matplotlib RGB format.
        image = image[:, :, ::-1]
        visualizer = Visualizer(image, self.metadata, instance_mode=self.instance_mode)
        if "panoptic_seg" in predictions:
            panoptic_seg, segments_info = predictions["panoptic_seg"]
            vis_output = visualizer.draw_panoptic_seg_predictions(
                panoptic_seg.to(self.cpu_device), segments_info
            )
        else:
            if "sem_seg" in predictions:
                vis_output = visualizer.draw_sem_seg(
                    predictions["sem_seg"].argmax(dim=0).to(self.cpu_device)
                )
            if "instances" in predictions:
                instances = predictions["instances"].to(self.cpu_device)
                # TODO:阈值0.5
                vis_output = visualizer.draw_instance_predictions(predictions=instances, score_threshold=0.5)

        return predictions, vis_output

结果
在这里插入图片描述

4.4 使用tensorboard可视化loss

进入到根目录,打开cmd,进入创建的conda环境,
安装tensorboard

pip install tensorboard

在根目录,运行OUTPUT_DIR是weight输出的目录,tensorboard用的是

tensorboard --logdir=“OUTPUT_DIR”

在这里插入图片描述

  • 24
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值