mmdetection的生物图像实例分割三:自定义数据集的测试与分析

mmdetection的生物图像实例分割全流程记录

第三章 自定义数据集的测试、重建与分析


文章目录

  • mmdetection的生物图像实例分割全流程记录
  • 前言
  • 一、测试集的推理
    • 1.模型测试
    • 2.测试数据解析
  • 二、测试结果的数据整合
  • 三、生物结构的重建效果


前言

mmdetection是一个比较容易入门且上手的深度学习检测框架,其官网为https://github.com/open-mmlab/mmdetection,相关文档https://mmdetection.readthedocs.io/zh-cn/latest/overview.html。

版本为mmdetection 3.3.0.这里可供借鉴。
在这里插入图片描述

一、测试集的推理

1.模型测试

找到文件位置:tools/test.py,复制为tools/test_ac3ac4.py,并进行如下更改:

# Copyright (c) OpenMMLab. All rights reserved.
import argparse
import os
import os.path as osp
import warnings
from copy import deepcopy

from mmengine import ConfigDict
from mmengine.config import Config, DictAction
from mmengine.runner import Runner

from mmdet.engine.hooks.utils import trigger_visualization_hook
from mmdet.evaluation import DumpDetResults
from mmdet.registry import RUNNERS
from mmdet.utils import setup_cache_size_limit_of_dynamo


# TODO: support fuse_conv_bn and format_only
def parse_args():
    parser = argparse.ArgumentParser(
        description='MMDet test (and eval) a model')
    # parser.add_argument('config', help='test config file path')
    # parser.add_argument('checkpoint', help='checkpoint file')
    parser.add_argument('--config', default='Path/to/your/mmdetection/mmdet/configs/mask_rcnn/mask_rcnn_r50_fpn_2x_ac3ac4.py', 
                        help='test config file path')
    parser.add_argument('--checkpoint', default='Path/to/your/DataLog/AC3AC4/MRCNN/epoch_best.pth', 
                        help='checkpoint file')
    parser.add_argument(
        '--work-dir', default='Path/to/your/DataLog/AC3AC4/MRCNNOUT/',
        help='the directory to save the file containing evaluation metrics')
    parser.add_argument(
        '--out',
        type=str, default='Path/to/your/DataLog/AC3AC4/MRCNNOUT/predictions.pkl',
        help='dump predictions to a pickle file for offline evaluation')
    # parser.add_argument(
    #     '--show', action='store_true', help='show prediction results')
    parser.add_argument(
        '--show', default=True, help='show prediction results')
    parser.add_argument(
        '--show-dir',
        default='Path/to/your/DataLog/AC3AC4/MRCNNOUT/show_dir/', 
        help='directory where painted images will be saved. '
        'If specified, it will be automatically saved '
        'to the work_dir/timestamp/show_dir')
    parser.add_argument(
        '--wait-time', type=float, default=2, help='the interval of show (s)')
    parser.add_argument(
        '--cfg-options',
        nargs='+',
        action=DictAction,
        help='override some settings in the used config, the key-value pair '
        'in xxx=yyy format will be merged into config file. If the value to '
        'be overwritten is a list, it should be like key="[a,b]" or key=a,b '
        'It also allows nested list/tuple values, e.g. key="[(a,b),(c,d)]" '
        'Note that the quotation marks are necessary and that no white space '
        'is allowed.')
    parser.add_argument(
        '--launcher',
        choices=['none', 'pytorch', 'slurm', 'mpi'],
        default='none',
        help='job launcher')
    parser.add_argument('--tta', action='store_true')
    # When using PyTorch version >= 2.0.0, the `torch.distributed.launch`
    # will pass the `--local-rank` parameter to `tools/train.py` instead
    # of `--local_rank`.
    parser.add_argument('--local_rank', '--local-rank', type=int, default=0)
    args = parser.parse_args()
    if 'LOCAL_RANK' not in os.environ:
        os.environ['LOCAL_RANK'] = str(args.local_rank)
    return args


def main():
    args = parse_args()

    # Reduce the number of repeated compilations and improve
    # testing speed.
    setup_cache_size_limit_of_dynamo()

    # load config
    cfg = Config.fromfile(args.config)
    cfg.launcher = args.launcher
    if args.cfg_options is not None:
        cfg.merge_from_dict(args.cfg_options)

    # work_dir is determined in this priority: CLI > segment in file > filename
    if args.work_dir is not None:
        # update configs according to CLI args if args.work_dir is not None
        cfg.work_dir = args.work_dir
    elif cfg.get('work_dir', None) is None:
        # use config filename as default work_dir if cfg.work_dir is None
        cfg.work_dir = osp.join('./work_dirs',
                                osp.splitext(osp.basename(args.config))[0])

    cfg.load_from = args.checkpoint

    if args.show or args.show_dir:
        cfg = trigger_visualization_hook(cfg, args)

    if args.tta:

        if 'tta_model' not in cfg:
            warnings.warn('Cannot find ``tta_model`` in config, '
                          'we will set it as default.')
            cfg.tta_model = dict(
                type='DetTTAModel',
                tta_cfg=dict(
                    nms=dict(type='nms', iou_threshold=0.5), max_per_img=100))
        if 'tta_pipeline' not in cfg:
            warnings.warn('Cannot find ``tta_pipeline`` in config, '
                          'we will set it as default.')
            test_data_cfg = cfg.test_dataloader.dataset
            while 'dataset' in test_data_cfg:
                test_data_cfg = test_data_cfg['dataset']
            cfg.tta_pipeline = deepcopy(test_data_cfg.pipeline)
            flip_tta = dict(
                type='TestTimeAug',
                transforms=[
                    [
                        dict(type='RandomFlip', prob=1.),
                        dict(type='RandomFlip', prob=0.)
                    ],
                    [
                        dict(
                            type='PackDetInputs',
                            meta_keys=('img_id', 'img_path', 'ori_shape',
                                       'img_shape', 'scale_factor', 'flip',
                                       'flip_direction'))
                    ],
                ])
            cfg.tta_pipeline[-1] = flip_tta
        cfg.model = ConfigDict(**cfg.tta_model, module=cfg.model)
        cfg.test_dataloader.dataset.pipeline = cfg.tta_pipeline

    # build the runner from config
    if 'runner_type' not in cfg:
        # build the default runner
        runner = Runner.from_cfg(cfg)
    else:
        # build customized runner from the registry
        # if 'runner_type' is set in the cfg
        runner = RUNNERS.build(cfg)

    # add `DumpResults` dummy metric
    if args.out is not None:
        assert args.out.endswith(('.pkl', '.pickle')), \
            'The dump file must be a pkl file.'
        runner.test_evaluator.metrics.append(
            DumpDetResults(out_file_path=args.out))

    # start testing
    runner.test()


if __name__ == '__main__':
    main()

若使用指定GPU,可以在命令行执行:

CUDA_VISIBLE_DEVICES=0 Path/to/your/envs/mmlab3/bin/python Path/to/your/mmdetection/tools/train_cremi.py

在这里插入图片描述

可以看到,在DataLog/AC3AC4/MRCNNOUT/show_dir/路径下已经出现测试的结果,左边是真值,右边是测试结果:
在这里插入图片描述

2.测试数据解析

对于已经推理出来的数据,我们可能不仅仅是作为可视化,还想将其还原为体积数据,进行后续的处理分析。打开我们存放的pkl文件,可以看到:

在这里插入图片描述
其中保存的data为list格式,长度是我们所的测试的图像数量,对于从标注到真实的mask还原的函数,官方给的数据在mmdet/visualization/local_visualizer.py这里。我们根据我们数据的命名方式,将pkl数据重新还原为体积数据:

其实在mmdet/evaluation/metrics/coco_metric.py路径下,我们可以看到官网中已经给出了Mask信息,并将其编码为RLE格式:

            # encode mask to RLE
            if 'masks' in pred:
                result['masks'] = encode_mask_results(
                    pred['masks'].detach().cpu().numpy()) if isinstance(
                        pred['masks'], torch.Tensor) else pred['masks']

我们同样调用pycocotools.mask进行解码,代码如下:


import os
from os.path import join
import pickle
from tqdm import tqdm
from skimage import io
import numpy as np
import pycocotools.mask as mask_util

def pkl2stack(pkl_path, save_path, 
              y_range = [[0, 1024]],
              x_range = [[0, 1024]],
              score_thre = 0.6):
    os.makedirs(save_path, exist_ok=True)
    with open(pkl_path, 'rb') as file:
        data = pickle.load(file)
        for single_item in tqdm(data):
            img_path = single_item['img_path']
            img_name = img_path.split('/')[-1].split('.')[0]
            stack_name, z_name, y_name, x_name = img_name.split('_')
            save_img_name = z_name + '.tif'
            save_sub_path = join(save_path, stack_name)
            os.makedirs(save_sub_path, exist_ok=True)
            if os.path.isfile(join(save_sub_path, save_img_name)):
                save_array = io.imread(join(save_sub_path, save_img_name))
            else:
                save_array = np.zeros(shape=(y_range[-1][-1], x_range[-1][-1]), dtype=np.uint8)
            pred_scores = single_item['pred_instances']['scores'].numpy()
            pred_masks = mask_util.decode(single_item['pred_instances']['masks'])
            for scores_index in range(pred_scores.shape[0]):
                item_score = pred_scores[scores_index]
                if item_score > score_thre:
                    save_array[y_range[int(y_name)][0]:y_range[int(y_name)][1], 
                               x_range[int(x_name)][0]:x_range[int(x_name)][1]] += pred_masks[:, :, scores_index]
            save_array[save_array>0] = 1
            io.imsave(join(save_sub_path, save_img_name), save_array)

if __name__ == '__main__':
    pkl2stack(pkl_path="Path/to/your/DataLog/AC3AC4/MRCNNOUT/predictions.pkl", 
              save_path='Path/to/your/DataPred/MRCNN/AC3AC4/')
    

可以看到相关的路径下已经为每一个体积数据创建了一个文件夹,并将每一个2D结果进行了保存。

在这里插入图片描述
这里可以发现它和真值的结果差异是十分大的。这是由于我们目前的demo仅仅训练了20个epoch,模型可能并未收敛,这里只展示基本流程。同时我们并没有对其中的3D信息,实例信息进行关联。下一节将会简要介绍简单的细胞器重建方法。

二、测试结果的数据整合

2D实例分割模型仅仅是得到了2D层面的结果,但是我们还需要将其整合为3D体积数据,最简单的方式是直接通过连通域进行实例化。然而这样的方法往往会出现大量的假阴和假阳结果。实例化的方法在众多的电镜数据集中都有涉及,包括突触、线粒体等。这里使用最简单的形态学后处理方法进行实现。

未完待续…

三、生物结构的重建效果

未完待续…

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/685408.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】Linux环境基础开发工具_5

文章目录 四、Linux环境基础开发工具Linux小程序---进度条git 未完待续 四、Linux环境基础开发工具 Linux小程序—进度条 上篇我们实现了一个简易的进度条,不过那仅仅是测试,接下来我们真正的正式实现一个进度条。 接着编写 processbar.c 文件 然…

java第二十课 —— 面向对象习题

类与对象练习题 编写类 A01,定义方法 max,实现求某个 double 数组的最大值,并返回。 public class Chapter7{public static void main(String[] args){A01 m new A01();double[] doubleArray null;Double res m.max(doubleArray);if(res !…

如何通俗易懂地理解大模型参数?

大型语言模型 (LLM) 的大小是通过参数数量来衡量的。举几个典型例子,GPT-3 有 1750 亿个参数,1750亿也可称为175B(1B 10亿),Meta最新开源的Llama3 参数数量在 80 亿到 700 亿之间,智谱公司最新开源的GLM4-…

龙叔Linux:别名(alias)

在Linux中,别名(alias)是一个命令的简短形式,通常用于简化或替换更长的命令序列。你可以使用alias命令来创建、查看和删除别名,定制自己专属的命令。一、创建别名 1.1、临时创建 你可以使用alias命令在命令行中直接定…

【MySQL】数据库入门基础

文章目录 一、数据库的概念1. 什么是数据库2. 主流数据库3. mysql和mysqld的区别 二、MySQL基本使用1. 安装MySQL服务器在 CentOS 上安装 MySQL 服务器在 Ubuntu 上安装 MySQL 服务器验证安装 2. 服务器管理启动服务器查看服务器连接服务器停止服务器重启服务器 3. 服务器&…

web刷题记录(4)

[GKCTF 2020]cve版签到 进来应该是给了个提示了,就是要以.ctfhub.com结尾 还有一个超链接,这题的ssrf还是挺明显的,抓包看看 发现回显里面有提示 说是和本地有关,那么也就是说,要访问127.0.0.1,大概意思就…

搜索与图论:树的重心

搜索与图论&#xff1a;树的重心 题目描述参考代码 题目描述 输入样例 9 1 2 1 7 1 4 2 8 2 5 4 3 3 9 4 6输出样例 4参考代码 #include <cstring> #include <iostream> #include <algorithm>using namespace std;const int N 100010, M N * 2;int n, m…

2024 Q1企业级SSD市场暴涨,国产努力追赶!

在2024年第一季度&#xff0c;由于对高容量存储需求的激增&#xff0c;企业级固态硬盘&#xff08;SSD&#xff09;市场的收入实现了显著增长&#xff0c;达到了37.58亿美元&#xff0c;与上一季度相比增长了62.9%。这一增长主要得益于供应商减产导致的高容量订单需求未得到满足…

【WP】猿人学_17_天杀的Http2.0

https://match.yuanrenxue.cn/match/17 抓包分析 居然对Fiddler有检测&#xff0c;不允许使用 那就使用浏览器抓包&#xff0c;好像没发现什么加密参数&#xff0c;然后重放也可以成功&#xff0c;时间长了也无需刷新页面&#xff0c;尝试Python复现。 Python复现 import …

SVM模型实现城镇居民月平均消费数据分类

SVM模型实现城镇居民月平均消费数据分类 一、SVM支持向量机简介二、数据集介绍三、SVM建模流程及分析一、SVM支持向量机简介 支持向量机是由感知机发展而来的机器学习算法,属于监督学习算法。支持向量机具有完备的理论基础,算法通过对样本进行求解,得到最大边距的超平面,并…

Activity->Activity中动态添加Fragment->Fragment回退栈BackStack

Fragment回退栈 Fragment回退栈用于管理Fragment的导航历史(添加、删除、替换)。每个Activity都有一个包含其所有Fragment的FragmentManager&#xff0c;调用其addToBackStack方法时&#xff0c;这个事务就会被添加到FragmentManager的回退栈中当用户按下返回键时&#xff0c;…

跑图像生成模型GAN时,遇到OSError: cannot open resource 报错解决办法

报错信息如下&#xff1a; Traceback (most recent call last): File "/root/autodl-tmp/ssa-gan/pretrain_DAMSM.py", line 276, in <module> count train(dataloader, image_encoder, text_encoder, File "/root/autodl-tmp/ssa-gan/pretrain_DAMSM.py…

三十九、openlayers官网示例Extent Interaction解析——在地图上绘制范围并获取数据

官网demo 地址&#xff1a; Extent Interaction 在openlayers中可以使用ExtentInteraction添加交互事件&#xff0c;配合shiftKeyOnly实现按住shift键绘制边界区域。 const map new Map({layers: [new TileLayer({source: new OSM(),}),],target: "map",view: new …

LeetCode 算法:合并区间c++

原题链接&#x1f517;&#xff1a;合并区间 难度&#xff1a;中等⭐️⭐️ 题目 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰…

一文搞懂常见的数据拆分方案

常见的几种数据拆分方案 1、客户端分片 直接在应用层实现读取分片规则&#xff0c;解析规则&#xff0c;根据规则实现切分逻辑。 这种方案优缺点&#xff1a; 侵入业务(缺点)&#xff1b; 实现简单&#xff0c;适合快速上线&#xff0c;容易定位问题&#xff1b; 对开发人员…

C++基础编程100题-025 OpenJudge-1.4-05 整数大小比较

更多资源请关注纽扣编程微信公众号 http://noi.openjudge.cn/ch0104/05/ 描述 输入两个整数&#xff0c;比较它们的大小。 输入 一行&#xff0c;包含两个整数x和y&#xff0c;中间用单个空格隔开。 0 < x < 2^32, -2^31 < y < 2^31。 输出 一个字符。 若x &…

锁存器(Latch)的产生与特点

Latch 是什么 Latch 其实就是锁存器&#xff0c;是一种在异步电路系统中&#xff0c;对输入信号电平敏感的单元&#xff0c;用来存储信息。锁存器在数据未锁存时&#xff0c;输出端的信号随输入信号变化&#xff0c;就像信号通过一个缓冲器&#xff0c;一旦锁存信号有效&#…

DP读书:如何使用badge?(开源项目下的标咋用)

最近在冲论坛&#xff0c;很少更一些内容了。但遇到了一个真的有趣的&#xff1a; 开源项目下&#xff0c;蓝蓝绿绿的标是怎么用的呢&#xff1f; 这是我的主页Readme&#xff0c;在看一些NXP的主仓时&#xff0c;突然发现没有这个玩&#xff0c;就自己整了个 再比如我的CSDN专…

【stm32/CubeMX、HAL库】swjtu嵌入式实验七 ADC 实验

相关电路与IO引脚 注意&#xff1a;串口打印重定向后使用printf打印需要在keil里勾选 Use MicroLIB &#xff0c;否则会卡住。 参看&#xff1a;https://zhuanlan.zhihu.com/p/565613666 串口重定向&#xff1a; /* USER CODE BEGIN Includes */#include <stdio.h>//…

利用opencv-python实现图像全景拼接技术实现

这个代码的主要功能是将多张图像拼接成一张全景图。它使用了OpenCV库中的SIFT特征提取、特征匹配和图像变换等技术来实现图像拼接。 一、预览效果 二、安装依赖 contourpy1.2.1 cycler0.12.1 fonttools4.53.0 importlib_resources6.4.0 kiwisolver1.4.5 matplotlib3.9.0 numpy…