SAM_ca17_level123_tumor_pad+crop_24039

文章描述了一个使用Python编写的脚本,通过OpenSlide库处理数字病理切片(WSI),对肿瘤区域进行分割,然后裁剪并保存含有肿瘤部分的高分辨率图像。脚本涉及json文件读取、图像处理、多级维度操作和边界检测等技术。
摘要由CSDN通过智能技术生成
在这里插入代码片
import os
import numpy as np
import cv2
import json
from PIL import Image
import openslide
from tqdm import tqdm
from math import ceil
#export LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libffi.so.7
os.environ['LD_PRELOAD'] = '/usr/lib/x86_64-linux-gnu/libffi.so.7'

def run_bach_ori(wsi_path,level,json_path,names,sel_names):
    # get the level * dimensions e.g. tumor0.tif level 6 shape (1589, 7514)
    slide = openslide.OpenSlide(wsi_path)
    w, h = slide.level_dimensions[level]
    mask_tumor = np.zeros((h, w)) # the init mask, and all the value is 0
    # get the factor of level * e.g. level 6 is 2^6
    factor = slide.level_downsamples[level]
    with open(json_path) as f:
        dicts = json.load(f)
    tumor_polygons = dicts['positive']

    for tumor_polygon in tumor_polygons:
        name = tumor_polygon["name"]
        if name not in names:
            names.append(name)
        if name in sel_names:
            vertices = np.array(tumor_polygon["vertices"]) / factor
            vertices = vertices.astype(np.int32)
            cv2.fillPoly(mask_tumor, [vertices], (255))
    mask_tumor = mask_tumor[:] > 127
    #print(names)
    return mask_tumor,names


def run(wsi_path,level,json_path):
    # get the level * dimensions e.g. tumor0.tif level 6 shape (1589, 7514)
    slide = openslide.OpenSlide(wsi_path)
    w, h = slide.level_dimensions[level]
    mask_tumor = np.zeros((h, w)) # the init mask, and all the value is 0
    # get the factor of level * e.g. level 6 is 2^6
    factor = slide.level_downsamples[level]
    with open(json_path) as f:
        dicts = json.load(f)
    tumor_polygons = dicts['positive']
    for tumor_polygon in tumor_polygons:
        name = tumor_polygon["name"]
        vertices = np.array(tumor_polygon["vertices"]) / factor
        vertices = vertices.astype(np.int32)
        cv2.fillPoly(mask_tumor, [vertices], (255))
    mask_tumor = mask_tumor[:] > 127
    return mask_tumor

def mask_show(npy_path,wsi_path,mask_save_path):
    wsi_name = wsi_path.split('/')[-1]
    mask = np.load(npy_path)
    num = np.zeros((mask.shape[0], (mask.shape[1])), dtype=np.int32)
    num[mask] = 1
    img_mask = num * 255
    cv2.imwrite(mask_save_path,img_mask)

def wsi_png(wsi_path,level,slide_save_path):
    wsi_name = wsi_path.split('/')[-1]
    slide = openslide.OpenSlide(wsi_path)
    downsamples = slide.level_downsamples
    [w, h] = slide.level_dimensions[0]
    # size1=int(w*(downsamples[0]/downsamples[4]))
    # size2=int(h*(downsamples[0]/downsamples[4]))
    size_w = round(w * (downsamples[0] / downsamples[level]))
    size_h = round(h * (downsamples[0] / downsamples[level]))
    region = np.array(slide.read_region((0, 0), level, (size_w, size_h)))
    im = Image.fromarray(region.astype('uint8')).convert('RGB')
    #save_path = os.path.join(slide_save_path,wsi_name)
    im.save(slide_save_path, quality=100)

def main():
    level = 2
    crop_size = 1024
    padding_color = (0, 0, 0)
    names = []
    # json_route = '/media/wagnchogn/data_2tb/path_sam/dataset/camleyon17/label/json'
    # wsi_route = '/media/wagnchogn/data_16t/camelyon/CAMELYON17/training_wsi/center_4'
    # #npy_route = r'D:\code\pre_code\wsi_prepocessing\dataset\camelyon\tumor4'
    # #mask_save_route = r'D:\code\pre_code\wsi_prepocessing\dataset\camelyon\tumor4_show'
    # save_route = '/media/wagnchogn/data_2tb/path_sam/dataset/camleyon17_10x/center_4/tumor'


    json_route = r'/media/dell/disk_8t/data_tokaili_0325/bach/json'
    wsi_route = r'/media/dell/disk_8t/data_tokaili_0325/bach/svs'
    #npy_route = r'D:\code\pre_code\wsi_prepocessing\dataset\camelyon\tumor4'
    #mask_save_route = r'D:\code\pre_code\wsi_prepocessing\dataset\camelyon\tumor4_show'
    save_route = r'/media/dell/disk_8t/data_tokaili_0325/bach/test_3_level2'

    mask_save_route = os.path.join(save_route,'mask','Invasive')
    crop_save_route = os.path.join(save_route, 'img','Invasive')
    if not os.path.exists(mask_save_route):
        os.makedirs(mask_save_route)
    if not os.path.exists(crop_save_route):
        os.makedirs(crop_save_route)
    label_files = os.listdir(json_route)

    wsi_files = os.listdir(wsi_route)
    for wsi_file in tqdm(wsi_files):
        json_path = os.path.join(json_route, wsi_file.replace('.svs', '.json'))
        wsi_path = os.path.join(wsi_route, wsi_file)
        ###

        ###shou dong gai  dedao  butong  wenjianjia
        ##  'Carcinoma in situ'  'In situ carcinoma'                 'Benign'
        sel_names = ['Invasive carcinoma', 'Carcinoma invasive']
        # wsi_files = os.listdir(wsi_route)
        for label_file in label_files:

            wsi_path = os.path.join(wsi_route, label_file.replace('.json', '.svs'))
            wsi_file = label_file.replace('.json', '.svs')
            # wsi_path = os.path.join(wsi_route, wsi_file)
            json_path = os.path.join(json_route, label_file)

            mask_tumor, names = run_bach_ori(wsi_path, level, json_path, names, sel_names)

            slide = openslide.OpenSlide(wsi_path)
            level_downsample = slide.level_downsamples[level]

            tumor_img = np.uint8(mask_tumor * 255)
            contours, _ = cv2.findContours(tumor_img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
            bounding_rects = [cv2.boundingRect(contour) for contour in contours]  # (x,y,width,height)
            for i in range(len(bounding_rects)):
                ###
                x_ori, y_ori, width_ori, height_ori = bounding_rects[i]
                # 1. 计算高和宽能否被1024整除,求商的最大值
                ####?
                factor_width = (width_ori // 1024) + (1 if width_ori % 1024 != 0 else 0)
                factor_height = (height_ori // 1024) + (1 if height_ori % 1024 != 0 else 0)

                # 2. 新的宽度和高度
                factor_all = max(factor_width, factor_height)

                width = factor_all * 1024
                height = factor_all * 1024

                # 3. 计算增量并调整x和y,以保持中心不变
                delta_width = width - width_ori
                delta_height = height - height_ori
                x = x_ori - delta_width // 2
                y = y_ori - delta_height // 2

                ###
                if x < 0:
                    x = 0
                if y < 0:
                    y = 0
                # cv2.rectangle(tumor_img, (x, y), (x + width, y + height), (0, 255, 0), 2) #显示裁剪区域

               ###
                if x + width > tumor_img.shape[1]:  # 检查宽度
                    new_width = x + width
                    right_padding = new_width - tumor_img.shape[1]
                    tumor_img = np.pad(tumor_img, ((0, 0), (0, right_padding)), 'constant', constant_values=0)

                if y + height > tumor_img.shape[0]:  # 检查高度
                    new_height = y + height
                    bottom_padding = new_height - tumor_img.shape[0]
                    tumor_img = np.pad(tumor_img, ((0, bottom_padding), (0, 0)), 'constant', constant_values=0)

                mask = tumor_img[y:y + height, x:x + width]

                x_level_0 = int(x * level_downsample)
                y_level_0 = int(y * level_downsample)
                sel_wsi = slide.read_region((x_level_0, y_level_0), level, (width, height))
                sel_wsi = sel_wsi.convert('RGB')

                sel_wsi_np = np.array(sel_wsi)
                height, width = sel_wsi_np.shape[:2]

                padded_width = crop_size * ceil(width / crop_size)
                padded_height = crop_size * ceil(height / crop_size)
                padded_image = cv2.copyMakeBorder(sel_wsi_np, 0, padded_height - height, 0, padded_width - width,
                                                  cv2.BORDER_CONSTANT, value=padding_color)
                padded_mask = cv2.copyMakeBorder(mask, 0, padded_height - height, 0, padded_width - width,
                                                  cv2.BORDER_CONSTANT, value=(0,0))


                # 裁剪并保存图像
                for i in range(0, padded_height, crop_size):
                    for j in range(0, padded_width, crop_size):
                        crop_mask = padded_mask[i:i + crop_size, j:j + crop_size]
                        crop_img = padded_image[i:i + crop_size, j:j + crop_size]

                        # filename = img_name + f"_{mag}x{i}i_{j}j.png"
                        mask_out_save_path = os.path.join(mask_save_route,
                                                 wsi_file.split('.svs')[0] + '_' + str(x) + '_' + str(y) + '_' + str(
                                                     width) + '_' + str(height) + '_' + str(level) + '_'   + str(i) + 'i' + str(j) + 'j' + '.png')

                        sel_wsi_path = os.path.join(crop_save_route,
                                                    wsi_file.split('.svs')[0] + '_' + str(x) + '_' + str(y) + '_' + str(
                                                        width) + '_' + str(height) + '_' + str(level) + '_' + str(i) + 'i' + str(j) + 'j' + '.png')





                        sel_wsi.save(sel_wsi_path)


                        cv2.imwrite(mask_out_save_path, crop_mask)
                        cv2.imwrite(sel_wsi_path, crop_img)

                # mask_path = os.path.join(mask_save_route,
                #                          wsi_file.split('.svs')[0] + '_' + str(x) + '_' + str(y) + '_' + str(
                #                              width) + '_' + str(height) + '_' + str(level) + '_' + '.tif')
                # cv2.imwrite(mask_path, mask)
                #
                # sel_wsi_path = os.path.join(crop_save_route,
                #                             wsi_file.split('.svs')[0] + '_' + str(x) + '_' + str(y) + '_' + str(
                #                                 width) + '_' + str(height) + '_' + str(level) + '_' + '.tif')
                # sel_wsi.save(sel_wsi_path)

                # print(bounding_rects)
        print(names)




if __name__ == "__main__":
    main()


####   level=3 one bug
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值