Python中的BioImage切片和拼接不丢失信息

问题描述 投票:0回答:1

我是一名Python新手,作为一名医学研究人员,学习大图像,其中包含大量有关细胞标记表达的生物数据。我有一个简短的处理代码,可以进行通道分离并将通道转换为荧光(伪)和/或灰度。 当尝试处理较大的图像时,我们没有足够的内存,因此解决方法是将图像切成可处理的图块,执行通道格式化,然后将图像缝合在一起。 我真的不知道缝合和切片如何与通道分离相结合。

我使用了 scikit_image 中的这些片段

import numpy as np`
import matplotlib.pyplot as plt

from skimage import data
from skimage.color import rgb2hed, hed2rgb

**# Example IHC image(512, 512, 3) uint8**
ihc_rgb = data.immunohistochemistry()

**# Separate the stains from the IHC image**
ihc_hed = rgb2hed(ihc_rgb)

**# Create an RGB image for each of the stains**
null = np.zeros_like(ihc_hed[:, :, 0])
ihc_h = hed2rgb(np.stack((ihc_hed[:, :, 0], null, null), axis=-1))
ihc_e = hed2rgb(np.stack((null, ihc_hed[:, :, 1], null), axis=-1))
ihc_d = hed2rgb(np.stack((null, null, ihc_hed[:, :, 2]), axis=-1))

**# Display**
fig, axes = plt.subplots(2, 2, figsize=(7, 6), sharex=True, sharey=True)
ax = axes.ravel()

ax[0].imshow(ihc_rgb)
ax[0].set_title("Original image")

ax[1].imshow(ihc_h)
ax[1].set_title("Hematoxylin")

ax[2].imshow(ihc_e)
ax[2].set_title("Eosin")  # Note that there is no Eosin stain in this image

ax[3].imshow(ihc_d)
ax[3].set_title("DAB")

for a in ax.ravel():
    a.axis('off')

fig.tight_layout()

from skimage.exposure import rescale_intensity

**# Rescale hematoxylin and DAB channels and give them a fluorescence look**
h = rescale_intensity(ihc_hed[:, :, 0], out_range=(0, 1),
                      in_range=(0, np.percentile(ihc_hed[:, :, 0], 99)))
d = rescale_intensity(ihc_hed[:, :, 2], out_range=(0, 1),
                      in_range=(0, np.percentile(ihc_hed[:, :, 2], 99)))
**
**# Cast the two channels into an RGB image, as the blue and green channels
**# respectively******
zdh = np.dstack((null, d, h))

fig = plt.figure()
axis = plt.subplot(1, 1, 1, sharex=ax[0], sharey=ax[0])
axis.imshow(zdh)
axis.set_title('Stain-separated image (rescaled)')
axis.axis('off')
plt.show()

我想将其转换为大图像。

python image-processing image-stitching image-slicer
1个回答
0
投票

给出了如何使用python按行读取大图像中的建议:

我建议您在开始之前将相当大的 TIFF 平铺在 Python 之外。在这里大量借鉴 John (@jcupitt) 的答案,你可以使用 VIP 来做到这一点。

我尝试重现您的问题。我也是图像处理和Python的新手,所以请耐心等待,我的代码如下,我选择包装libvips图像处理库的pyvips,因为我在这里找到了很多关于它的帮助:

from PIL import Image
import numpy as np

import pyvips

# CREATE 10000*10000*3 black image 

# array = np.zeros((10000, 10000, 3), dtype=np.uint8)
# image = pyvips.Image.new_from_array(array)
# image.write_to_file("huge.tif")


# fields = image.get_fields()
 
# print(fields) 


# img = image.numpy()

# print('img : ', img.size, img.shape , img.ndim)


# load the 10000*10000*3 black image , without loaing it !!! this should be where we can load your huge tif
img_loaded = pyvips.Image.new_from_file('huge.tif', access='sequential')


print(img_loaded, img_loaded.width , img_loaded.height, img_loaded.bands)


hg = 0

for i in range(img_loaded.height//1000):
    
    # https://stackoverflow.com/questions/48281086/extracting-a-region-of-interest-from-an-image-file-without-reading-the-entire-im
    
    
    # uses pyvips pointer to loaded image to load part of it 
    # get the numpy array corresponding to it
    # change same of the images
    # saves them one by one 
    #IMPORTANT script works because we know 10000/10 is round no pixel leftover
    
    a = img_loaded.crop(0, i*1000, img_loaded.width, 1000)
    
    
    arr = a.numpy()
    
    print(arr.size , arr.shape , arr.ndim)
    
    # aa = Image.fromarray(arr)
    # aa.show()
    
    if i%2 == 0 :
        
        arr[:,:,0] = 0
        arr[:,:,1] = 255
        arr[:,:,2] = 0
        
        print('i%2 : ', i % 2)
        
        aa = Image.fromarray(arr)
        aa.show()
        
        aa.save('bit_'+str(i)+'.tif')
        
    
    elif i == 3 or i == 9 :
        
        arr[:,:,0] = 255
        arr[:,:,1] = 0
        arr[:,:,2] = 0
        
    
        aa = Image.fromarray(arr)
        aa.show()
        
        aa.save('bit_'+str(i)+'.tif')
       
    else:
        
        print('i%2 : ', i % 2)
        
        aa = Image.fromarray(arr)
        aa.show()
        
        aa.save('bit_'+str(i)+'.tif')
        
 
        
# https://stackoverflow.com/questions/50297176/merge-large-images-on-disk

# load each of the images from above without loading them , and join again

images = [pyvips.Image.new_from_file(filename, access="sequential")
          for filename in ['bit_'+str(i)+'.tif' for i in range(img_loaded.height//1000)   ] ]

final = pyvips.Image.arrayjoin(images, across = 1)

final.write_to_file('result.tiff')

我的脚本的第一行:

# CREATE 10000*10000*3 black image 

# array = np.zeros((10000, 10000, 3), dtype=np.uint8)
# image = pyvips.Image.new_from_array(array)
# image.write_to_file("huge.tif")

创建我假设的

huge.tif
文件,没有那么大但是……

exiftool huge.tif
给出详细信息:

Image Width                     : 10000
Image Height                    : 10000
Bits Per Sample                 : 8 8 8

第二部分代码加载,没有加载到内存中,这样的文件

并对提取的部分进行相同的更改并转换为

numpy
数组,最终通过
.tif
库保存为较小的
Pillow
文件。

然后生成的图片不会通过

pyvips
再次加载并合并到写入磁盘的不在内存中的文件中,我不知道我是否犯了同样的错误,生成的
result.tiff
文件具有与输入一相同的尺寸:

我是大型 tiff 文件的新手,这应该提供一种处理它们的方法,请在我的代码中查看一些相关 SO 问题的链接,我用这些问题的解决方案创建了此代码片段

© www.soinside.com 2019 - 2024. All rights reserved.