使用pyradiomics库对dcm图像进行特征提取

一 制作掩膜图像

医学掩膜图像的制作可以使用labelme和3D Slicer获得,下文中仅介绍使用labelme对dcm图像标注后获得json文件的一些处理,至于labelme的使用请参考其他博客。

1. 文件批量重命名

#coding=gbk
#文件批量重命名
import os
import sys
def rename():
    path=r"E:\3D slicerTest\NC_OVER51_MRI\3004368644\ScalarVolume_96"
    name=10000
    startNumber="1"
    mask='_mask'
    fileType=".dcm"
    print("正在生成文件")
    count=1
    filelist=os.listdir(path)
    for files in filelist:
        Olddir=os.path.join(path,files)
        if os.path.isdir(Olddir):
            continue
        Newdir=os.path.join(path,str(name+count)+mask+fileType)
        os.rename(Olddir,Newdir)
        count+=1
    print("一共修改了"+str(count)+"个文件")

rename()

2. 分离dcm和png图像

由于labelme只能对png、jpg等格式的图像进行标注,所以需先将dcm图像转换,这里使用MicroDicom进行批量转换,也可使用python进行格式转换

# dcm转png
import pydicom
import matplotlib.pyplot as plt
import scipy.misc
import imageio
import pandas as pd
import numpy as np
import os


def DcmToPng(file_path,png_path):
    # 获取所有图片名称
    c = []
    dirs = os.listdir(file_path)  # 路径
    # 将文件夹中的文件名称与后边的 .dcm分开
    for dir in dirs:
        # print(dirs)
        new_dir = os.path.join(file_path,dir)
        new_png_path = os.path.join(png_path,dir)
        print(new_dir)
        for dir1 in os.listdir(new_dir):
            new_dir1 = os.path.join(new_dir, dir1)
            new_png_path1 = os.path.join(new_png_path, dir1)
            for files in os.listdir(new_dir1):
                if files.lower().endswith('.dcm'):
                    fullpath = os.path.join(new_dir1, files)
                    print(fullpath)
                    out_path = new_png_path + "\\"+files.split('.')[0]+"_mask.png"
                    ds = pydicom.read_file(fullpath)
                    img = ds.pixel_array  # 提取图像信息
                    imageio.imsave(out_path, img)

                # for file in os.listdir(new_dir):
                #     index = name.rfind('.')
                #     name = name[:index]
                #     c.append(name)
    #
    # for files in c:
    #     picture_path = file_path +"/"+ files + ".dcm"
    #     out_path = des_path+"/" + files + ".png"
    #     ds = pydicom.read_file(picture_path)
    #     img = ds.pixel_array  # 提取图像信息
    #     imageio.imsave(out_path,img)
    #     # scipy.misc.imsave(out_path, img)

    print('all is changed')

if __name__ == '__main__':
    src_path = r'E:\3D slicerTest\test\dcm'
    des_path = r'E:\3D slicerTest\test\png'
    DcmToPng(src_path,des_path)

分离dcm和png
#coding:utf8
import os
import shutil
indexs = list()
def png_copy(path,png_path):
    file_list = os.listdir(path)  # 该文件夹下所有的文件(包括文件夹)
    for dirs in file_list:
        # print(dirs)
        new_dir = os.path.join(path,dirs)
        new_png_path = os.path.join(png_path,dirs)
        # print(new_dir)
        for file in os.listdir(new_dir):
            if file.endswith('.png'):
                # print(file)
                new_path = os.path.join(new_dir,file)
                shutil.copy(new_path, new_png_path)
                prefix = new_dir+'\\'+file.split('.')[0] + '.DCM'

                indexs.append(prefix)

def dcm_copy(path,data_path):

    file_list = os.listdir(path)  # 该文件夹下所有的文件(包括文件夹)
    # print(file_list)
    for dirs in file_list:

        # print(dirs)
        new_dir = os.path.join(path,dirs)
        # print(new_dir)
        new_dcm_path = os.path.join(data_path, dirs)
        # print(new_dcm_path)
        for files in os.listdir(new_dir):
            if files.lower().endswith('.dcm'):
                fullpath = os.path.join(new_dir, files)
                # print(fullpath)
                i = 0
                for i in range(len(indexs)):
                    # print(indexs[i])
                    if indexs[i]==fullpath:
                        shutil.copy(fullpath, new_dcm_path)

                    else:
                        continue
                    i = i + 1

def mk_dir1(path1,path2):
    dirs = os.listdir(path1)
    for dir in dirs:
        file_name = path2 + '/'+str(dir)
        os.mkdir(file_name)

def mk_dir2(path1,path2):
    dirs = os.listdir(path1)
    for dir in dirs:
        file_name = path2 + '/' + str(dir)
        os.mkdir(file_name)

if __name__ == '__main__':
    path = r'E:\1Test\test2\dcm' # 全部DCM文件的路径
    png_path = r'E:\1Test\test2\png' #转化后png的保存路径
    data_path = r'E:\1Test\test2\data' #需要转化的dcm序列的保存路径
    mk_dir1(path,png_path) #创建和path中一致的文件夹
    mk_dir2(path,data_path)
    png_copy(path,png_path)
    # print(indexs)
    dcm_copy(path,data_path)


3. 批量解析json

#!/usr/bin/env python
# _*_ coding: UTF-8 _*_
#!/bin/bash
''' 批量解析json 对指定路径中的json文件进行解析,生成相应的数据'''
import os
import natsort
labelme_json = r"C:\\Users\\18943\.conda\envs\labelme\Scripts\labelme_json_to_dataset.exe" #labelme_json_to_dataset.exe 程序路径

file_path = r"E:\1Test\json_test"   # 处理文件所在路径

dir_list = os.listdir(file_path)

for dirs in dir_list:
    new_path = os.path.join(file_path,dirs)
    # dir_info = natsort.natsorted(Olddir)
    for file_name in os.listdir(new_path):
        file_name = os.path.join(new_path,file_name)
        os.system('cd'+''+new_path)
        os.system(labelme_json + " " + file_name)

4. 提取label图像

#coding:utf8
import os
import shutil

def file_rename(path):
    i = 0
    filelist = os.listdir(path)  # 该文件夹下所有的文件(包括文件夹)
    #print(filelist)
    for files in filelist:
        # i=i+1
        Olddir = os.path.join(path, files)
        if os.path.isdir(Olddir):
            sub_path = path +"/"+ filelist[i]
            sub_filelist = os.listdir(sub_path)
            j = 1
            for sub_files in sub_filelist: #子目录
                filename = os.path.splitext(sub_files)[0]  # 文件名
                newpath = sub_path + '/'
                despath = r'E:\1Test\4label\3004325563\\'
                #print(filename)
                newname=''
                if "label"==filename:
                    #print(filelist[i].split("_")[0])
                     newname=filelist[i].split("_")[0]
                     os.rename(newpath+filename + ".png", despath+newname +'_mask'+ ".png")

                     #shutil.copy(newpath+newname + ".png", todir)
                j = j + 1
            i = i + 1
        else:
            continue


if __name__ == '__main__':
    path = (r'E:\1Test\3json\3004325563')  # 全部文件的路径
    file_rename(path)

5. 批量二值化

#coding:utf8
import os
import shutil
import cv2 as cv
import numpy as np

# 二值化后图像保存路径
des_path = r'E:\1Test\5data\3004325563\\'

def file_rename(path):
    filelist = os.listdir(path)  # 该文件夹下所有的文件(包括文件夹)
    # print(filelist)
    for files in sorted(filelist):
        if files.lower().endswith('_mask.png'):
            image = cv.imread(path + files)
            gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)  # 把输入图像灰度化
            h, w = gray.shape[:2]
            m = np.reshape(gray, [1, w * h])
            mean = m.sum() / (w * h)
            print("mean:", mean)
            ret, binary = cv.threshold(gray, mean, 255, cv.THRESH_BINARY)
            cv.imwrite(des_path + files, binary)



if __name__ == '__main__':
    path = r'E:\1Test\4label\3004325563\\' # 全部文件的路径
    file_rename(path)

二 特征提取

# -*- coding: utf-8 -*-

import SimpleITK as sitk
import radiomics
from radiomics.featureextractor import RadiomicsFeatureExtractor
import os
import numpy as np
import pandas as pd
import cv2

# ------------------------------------
os.chdir(r'E:\Demo\')
os.getcwd()  # 获取当前工作目录

yaml_path = './Params.yaml'  # 这是pyradicomisc用得配置文件
dataset_path = "./Test_CT_patient/"
excel_lc_path = './test.csv'

zoom_prixl = 5  # 缩小的像素个数


# predict

def predict_features(image, mask, option_yaml_path):
    extractor = RadiomicsFeatureExtractor(option_yaml_path)
    return extractor.execute(image, mask)
# 特征抽取器是一个封装的类,用于计算影像组学特征。大量设置可用于个性化特征抽取,
# 包括:需要抽取的特征类别及其对应特征;需要使用的图像类别(原始图像/或衍生图像);需要进行什么样的预处理。
# 我们可以使用该类的execute()方法来执行特征抽取操作。execute接受的参数为原始图像及其对应的Mask。


# -----------------------
# path=phase_path
# transform dcm and mask_png to image main function
def prepare_images(path):
    # prepare dcm
    #读取dcm格式图像
    reader = sitk.ImageSeriesReader()
    # 文件夹中包含多个series
    # 根据文件夹获取序列ID,一个文件夹里面通常是一个病人的所有切片,会分为好几个序列
    seriesIDs = reader.GetGDCMSeriesIDs(path)

    # 选取其中一个序列ID,获得该序列的若干文件名
    dicom_names = reader.GetGDCMSeriesFileNames(path, seriesIDs[0])
    # 设置文件名
    reader.SetFileNames(dicom_names)
    #读取dcm序列
    images_dcm = reader.Execute()
    print(images_dcm.GetSize())


    # prepare mask
    tmp = []
    for item in sorted(os.listdir(path)): #用于返回指定的文件夹包含的文件或文件夹的名字的列表
        if item.lower().endswith('_mask.png'):#lower变成小写
            tmp_array = sitk.GetArrayFromImage(sitk.ReadImage(path + item)) #获取图像数组
            #print(tmp_array)
            #将灰度图tmp_array中灰度值小于127的点置0,灰度值大于127的点置255
            ret, thresh = cv2.threshold(tmp_array, 127, 255, 0) #图像阈值处理
            # 参数(1图片源,2阈值(起始值),3最大值,4表示的是这里划分的时候使用的是什么类型的算法,常用值为0)
            #thresh 二值化后的灰度图

            contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)  # 得到轮廓信息 contours 轮廓本身  hierarchy 每条轮廓对应的属性
            imgnew = cv2.drawContours(tmp_array, contours, -1, (0, 0, 0), int(zoom_prixl * 2))  # 把所有轮廓画出来
            imgnew = imgnew / 255
            tmp.append(imgnew.astype(np.int32)) #数据格式转换

    images_mask = sitk.GetImageFromArray(np.array(tmp))
    print(images_mask.GetSize())
    images_mask.CopyInformation(images_dcm)

    return images_dcm, images_mask


results = list()
indexs = list()
if __name__ == '__main__':


    for patients_id in os.listdir(dataset_path):
        patients_path = dataset_path + patients_id + '/'
        # for phase in os.listdir(patients_path):
        #     phase_path = patients_path + phase + '/'
        indexs.append(str(patients_id))
        images, masks = prepare_images(patients_path)
        results.append(predict_features(images, masks, yaml_path))

    df = pd.DataFrame(results)
    df.drop(df.columns[list(range(22))], axis=1, inplace=True)  # drop the non feature
    df.index = indexs
    df.to_csv('5_1_ct_patient.csv')



  • 17
    点赞
  • 105
    收藏
    觉得还不错? 一键收藏
  • 13
    评论
### 回答1: Vue是一种流行的前端框架,它可以用于构建用户界面。尽管Vue本身并无直接的“标注dcm文件”的功能,但可以通过结合其他工具和来实现这一目标。 首先,我假设“dcm文件”是指数字成像与通信医疗图像DICOM(Digital Imaging and Communications in Medicine)文件。DICOM是医学图像的国际标准格式,通常用于医学影像设备生成的图像(例如X射线、CT扫描和磁共振图像)。 在Vue中,我们可以使用第三方如dwv(DICOM Web Viewer)来展示和标注DICOM图像。dwv是一个用于浏览DICOM图像的开源JavaScript,它提供了处理和显示DICOM图像的方法。 要在Vue中使用dwv,可以按照以下步骤操作: 1. 通过npm或其他安装方式,将dwv添加到Vue项目依赖中。 2. 在Vue组件中,导入dwv并设置相关配置,如DICOM图像的路径和其他选项。 3. 在模板中,使用dwv提供的组件来显示DICOM图像并添加标注工具。 4. 如果需要,可以根据需要自定义标注工具,如测量工具、注释工具等。 通过以上步骤,我们可以在Vue中使用dwv来展示和标注DICOM图像。当然,具体的实现细节还取决于项目要求和个人的技术能力,但使用dwv是一个较为常见的解决方案。 需要注意的是,dwv只是一个展示和标注DICOM图像的工具,并不包含DICOM图像的解析和处理功能。如果需要对DICOM文件进行更复杂的处理,可能需要使用其他专门处理DICOM图像或工具。 总之,虽然Vue本身没有直接支持对DICOM文件进行标注的功能,但可以通过结合第三方,如dwv,来实现在Vue中展示和标注DICOM图像的需求。 ### 回答2: Vue是一种流行的JavaScript框架,可以通过使用其中的组件化开发方式来对DCM文件进行标注。DCM文件是医学图像格式,常用于医学影像学领域。 首先,我们可以使用Vue的组件化特性来分离和管理标注工具的不同功能模块。例如,我们可以创建一个图像显示组件,在该组件中使用DCM文件解析DCM文件加载并显示出来。 然后,我们可以创建一个标注工具条组件,该组件包含各种标注工具按钮,如矩形框、圆形框、线条等。每个标注工具按钮都可以绑定相应的事件处理函数,当用户点击某个标注工具按钮时,可以触发对应的事件处理函数,从而实现对DCM文件进行相应标注的功能。 在标注工具条组件中,我们还可以添加一些其他常用的功能按钮,如撤销、保存等。这些按钮也可以通过Vue的事件机制来实现相应的功能。 另外,我们可以利用Vue的数据绑定特性,在标注工具组件中使用数据绑定将标注结果实时反映在主页面上。例如,我们可以使用v-model指令绑定一个标注结果数组,使得当用户进行标注操作时,结果数组会自动更新。 总结起来,利用Vue的组件化开发方式和数据绑定特性,我们可以很方便地实现对DCM文件的标注功能。通过创建图像显示组件、标注工具条组件,并利用事件处理和数据绑定来实现不同标注工具的功能和实时数据显示,可以有效提高标注效率,并方便后续的数据处理和分析。 ### 回答3: Vue是一种流行的JavaScript框架,常用于构建用户界面。虽然Vue本身并不提供对DCM(医学数字成像和通信)文件的直接标注功能,但可以利用Vue的优势和其他来实现这一功能。 要对DCM文件进行标注,我们可以使用外部的JavaScript,例如Cornerstone.js。Cornerstone.js是专门用于在浏览器中显示和操作医学影像的。它支持DICOM文件格式,并提供了各种标注和量度的功能。 在Vue中,我们可以使用npm包管理器安装Cornerstone.js,并在Vue组件中加载和使用它。首先,我们需要在Vue项目中导入Cornerstone.js的必要文件,包括Cornerstone核心、Cornerstone工具和DICOM文件解析器。 在Vue组件的生命周期钩子函数中,我们可以创建一个canvas元素,并使用Cornerstone.js将DICOM文件加载到canvas中显示。接着,我们可以使用Cornerstone.js提供的标注工具,例如线、矩形等来标记DICOM图像。 例如,我们可以在Vue组件中创建一个按钮,当用户点击按钮时,调用一个方法来添加一个线标注到DICOM图像上。在这个方法中,我们可以利用Cornerstone.js的API来添加线标注,并更新画布以显示标注结果。 总之,尽管Vue本身并不直接支持DCM文件的标注,但它可以与外部的JavaScript(如Cornerstone.js)集成来实现这一功能。使用Vue和Cornerstone.js的组合,我们可以方便地在Vue应用中对DCM文件进行标注。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值