• skimage学习(3)——使灰度滤镜适应 RGB 图像、免疫组化染色分离颜色、过滤区域最大值


    1、使灰度滤镜适应 RGB 图像

    有很多滤镜是用于灰度图像而不是彩色图像的。为了简化创建可以适应RGB图像的函数的过程,scikit-image提供了adapt_rgb装饰器。
    要实际使用adapt_rgb装饰器,您必须决定如何调整RGB图像,以便与灰度过滤器一起使用。有两个预定义的处理程序:
    each_channel:将每个RGB通道逐一传递给过滤器,然后将结果缝合回RGB图像中。
    hsv_value:将RGB图像转换为HSV,并将值通道传递给滤波器。过滤后的结果被插入到HSV图像中,并转换回RGB。

    import skimage
    from skimage.color.adapt_rgb import adapt_rgb, each_channel, hsv_value
    from skimage import filters
    
    '''
    一般的滤波器都是针对灰度图像的,scikit-image 库提供了针对彩色图像滤波的decorator:
    adapt_rgb,adapt_rgb 提供两种形式的滤波,一种是对rgb三个通道分别进行处理,
    另外一种方式是将rgb转为hsv颜色模型,然后针对v通道进行处理,最后再转回rgb颜色模型。
    https://blog.csdn.net/weixin_30244681/article/details/95619723
    '''
    @adapt_rgb(each_channel)
    def sobel_each(image):
        return filters.sobel(image)#使用 Sobel 滤波器查找图像中的边缘。
    
    
    @adapt_rgb(hsv_value)
    def sobel_hsv(image):
        return filters.sobel(image)
    #我们可以像平常一样使用这些函数,但现在它们可以同时处理灰度图像和彩色图像。让我们用彩色图像来绘制结果:
    from skimage import data
    from skimage.exposure import rescale_intensity
    import matplotlib.pyplot as plt
    
    #image = data.astronaut()
    image=skimage.io.imread('11.jpg',)
    fig, (ax_each, ax_hsv) = plt.subplots(ncols=2, figsize=(14, 7))
    
    # 我们使用1 - sobel_each(image),但如果图像没有标准化,这将不起作用
    ax_each.imshow(rescale_intensity(1 - sobel_each(image)))#这句话的意思?,我猜测是调整分别对对rgb三个通道的滤波,并且显示图片
    '''
    rescale_intensity:
    拉伸或缩小其强度级别后返回图像。
    输入和输出所需的强度范围,in_range和 out_range分别用于拉伸或缩小输入图像的强度范围。请参阅下面的示例。
    '''
    ax_each.set_xticks([]), ax_each.set_yticks([])#设置带有刻度列表的x、y刻度
    ax_each.set_title("Sobel filter computed\n on individual RGB channels")
    '''
    调整强度
    函数:skimage.exposure.rescale_intensity(image, in_range='image', out_range='dtype')
    in_range:表示输入图片的强度范围,默认为'image', 表示用图像的最大/最小像素值作为范围
    out_range:表示输出图片的强度范围,默认为'dype', 表示用图像的类型的最大/最小值作为范围
    默认情况下,输入图片的[min,max]范围被拉伸到[dtype.min, dtype.max],如果dtype=uint8, 那么dtype.min=0, dtype.max=255
    '''
    '''
    matplotlib库的axiss模块中的Axes.set_xticks()函数用于设置带有刻度列表的x刻度。
    用法: Axes.set_xticks(self, ticks, minor=False)
    参数:此方法接受以下参数。
    ticks:此参数是x轴刻度位置的列表。
    minor:此参数用于设置主要刻度线还是设置次要刻度线
    返回值:此方法不返回任何值。
    '''
    # We use 1 - sobel_hsv(image) but this won't work if image is not normalized
    ax_hsv.imshow(rescale_intensity(1 - sobel_hsv(image)))
    ax_hsv.set_xticks([]), ax_hsv.set_yticks([])
    ax_hsv.set_title("Sobel filter computed\n on (V)alue converted image (HSV)")
    
    '''
    注意,经过值过滤的图像的结果保留了原始图像的颜色,但经过通道过滤的图像以一种更令人惊讶的方式组合在一起。
    在其他常见的情况下,例如平滑,通道滤波图像会产生比值滤波图像更好的结果。
    您还可以为adapt_rgb创建自己的处理程序函数。为此,只需创建一个具有以下签名的函数
    '''
    def handler(image_filter, image, *args, **kwargs):
        # Manipulate RGB image here...
        image = image_filter(image, *args, **kwargs)
        # Manipulate filtered image here...
        return image
    '''
    注意,adapt_rgb处理程序是为图像是第一个参数的过滤器编写的。
    作为一个非常简单的例子,我们可以将任何RGB图像转换为灰度,然后返回过滤后的结果:
    '''
    from skimage.color import rgb2gray
    
    def as_gray(image_filter, image, *args, **kwargs):
        gray_image = rgb2gray(image)#将RGB图像转换为灰度
        return image_filter(gray_image, *args, **kwargs)
    '''
    创建一个使用*args和**kwargs向过滤器传递参数的签名是很重要的,这样修饰后的函数就可以有任意数量的位置和关键字参数。
    最后,我们可以像之前一样对adapt_rgb使用这个处理程序:
    '''
    #灰度滤波
    @adapt_rgb(as_gray)
    def sobel_gray(image):
        return filters.sobel(image)
    
    
    fig, ax = plt.subplots(ncols=1, nrows=1, figsize=(7, 7))
    
    # We use 1 - sobel_gray(image) but this won't work if image is not normalized
    ax.imshow(rescale_intensity(1 - sobel_gray(image)), cmap=plt.cm.gray)
    ax.set_xticks([]), ax.set_yticks([])
    ax.set_title("Sobel filter computed\n on the converted grayscale image")
    
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93

    在这里插入图片描述
    在这里插入图片描述

    2、免疫组化染色分离颜色

    颜色反褶积是指特征的颜色分离。
    本例中,我们将免疫组化染色(IHC)与苏木精反染色分离。分离是用1中所述的方法实现的,称为“颜色反褶积”。
    免疫组化染色显示,二氨基联苯胺(DAB)显示FHL2蛋白的表达为棕色。
    颜色空间、hed颜色通道概念:https://www.cnblogs.com/fydeblog/p/9737261.html

    import numpy as np
    import matplotlib.pyplot as plt
    
    from skimage import data
    from skimage.color import rgb2hed, hed2rgb
    
    # 获取图片
    ihc_rgb = data.immunohistochemistry()
    
    # 从免疫组化图像中分离污渍
    #RGB到Haematoxylin-Eosin-DAB (HED) 颜色空间转换。
    ihc_hed = rgb2hed(ihc_rgb)
    
    # 为每个污渍创建一个RGB图像
    #np.zeros_like(a)的目的是构建一个与a同维度的数组,并初始化所有变量为零。
    null = np.zeros_like(ihc_hed[:, :, 0])#是取三维矩阵中第一维的所有数据,并且赋值为0
    ihc_h = hed2rgb(np.stack((ihc_hed[:, :, 0], null, null), axis=-1))#苏木精到 RGB 颜色空间的转换,axis=-1:在最后一维操作,并且转换为rgb
    hed2rgb(np.stack((null, ihc_hed[:, :, 1], null), axis=-1))#伊红到 RGB 颜色空间的转换
    ihc_d = hed2rgb(np.stack((null, null, ihc_hed[:, :, 2]), axis=-1))#DAB (HED) 到 RGB 颜色空间的转
    
    # 展示
    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
    #D通道
    ax[3].imshow(ihc_d)
    ax[3].set_title("DAB")
    
    for a in ax.ravel():
        a.axis('off')
    
    fig.tight_layout()
    
    #现在我们可以轻松操作苏木素和DAB通道:
    from skimage.exposure import rescale_intensity
    
    # 将h和d通道的亮度水平rescale到(0,1)
    #重新测量苏木素和DAB通道并给予它们荧光观察,按照一定比例调整图像强度
    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)))
    '''
    调整强度
    函数:skimage.exposure.rescale_intensity(image, in_range='image', out_range='dtype')
    in_range:表示输入图片的强度范围,默认为'image', 表示用图像的最大/最小像素值作为范围
    out_range:表示输出图片的强度范围,默认为'dype', 表示用图像的类型的最大/最小值作为范围
    默认情况下,输入图片的[min,max]范围被拉伸到[dtype.min, dtype.max],如果dtype=uint8, 那么dtype.min=0, dtype.max=255
    '''
    #将两个通道渲染成RGB图像,蓝色和绿色通道
    #两个通道相加
    zdh = np.dstack((null, d, h))#为什么这样做
    #np.dstack详解:https://www.cjavapy.com/article/894/
    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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67

    在这里插入图片描述
    在这里插入图片描述

    3、过滤区域最大值

    在这里,我们使用形态重建来创建一个背景图像,我们可以从原始图像中减去它来分离明亮的特征(区域最大值)。
    首先,我们从图像的边缘开始,尝试通过扩张重建。我们将种子图像初始化为图像的最小强度,
    并将其边界设置为原始图像中的像素值。这些最大的像素会被放大以重建背景图像。

    import skimage
    
    '''
    通过形态学重建来创建一个背景图像,从原始图像中减去背景图像来让前景增强。
    形态学重建涉及两幅图像和一个结构元,一幅图像是标记(也就是我们接下来要用的seed),它包含变换的起始点,另一幅图像是模板(mask),它用来约束该变换。
    '''
    import numpy as np
    import matplotlib.pyplot as plt
    
    from scipy.ndimage import gaussian_filter
    from skimage import data
    from skimage import img_as_float
    from skimage.morphology import reconstruction
    
    #转换为浮点数:这对后面的减法很重要,但不适用于uint8
    #image = img_as_float(data.coins())#转换格式
    image=img_as_float(skimage.io.imread('11.jpg',))
    image = gaussian_filter(image, 1)#高斯滤波是一种线性平滑滤波,可以去除高斯噪声,其效果是降低图像灰度的尖锐变化,也就是图像模糊了
    '''
    def gaussian_filter(input, sigma, order=0, output=None,
                        mode="reflect", cval=0.0, truncate=4.0):
    输入参数:
    input: 输入到函数的是矩阵
    sigma:标量或标量序列,就是高斯函数里面的\sigma,这个值越大,滤波之后的图像越模糊
    返回值:
    返回值是和输入形状一样的矩阵
    '''
    #种子图像初始化图像的最小值,并将其边界设置为原始图像的像素值
    seed = np.copy(image)
    seed[1:-1, 1:-1] = image.min()
    mask = image#使用原图作为mask
    #采用膨胀的形态学重建
    dilated = reconstruction(seed, mask, method='dilation')
    
    #减去膨胀的图像只剩下硬币和一个平坦的黑色背景,如下图所示。
    fig, (ax0, ax1, ax2) = plt.subplots(nrows=1,
                                        ncols=3,
                                        figsize=(8, 2.5),
                                        sharex=True,
                                        sharey=True)
    
    ax0.imshow(image, cmap='gray')
    ax0.set_title('original image')
    ax0.axis('off')
    
    ax1.imshow(dilated, vmin=image.min(), vmax=image.max(), cmap='gray')
    ax1.set_title('dilated')
    ax1.axis('off')
    
    ax2.imshow(image - dilated, cmap='gray')
    ax2.set_title('image - dilated')
    ax2.axis('off')
    
    fig.tight_layout()
    
    '''
    虽然特征(即硬币)是明显孤立的,但在原始图像中被明亮背景包围的硬币在减去的图像中更暗淡。
    我们可以尝试使用不同的种子图像来纠正这个问题。
    我们可以使用图像本身的特征来播种重建过程,而不是在图像边界上创建一个极大值的种子图像。
    这里,种子图像是原始图像减去一个固定值h
    '''
    #使用图像本身的特征来作为重建过程的seed,这次的seed设置为原始图像减去一个固定值h。
    h = 0.4
    seed = image - h
    dilated = reconstruction(seed, mask, method='dilation')
    hdome = image - dilated
    
    #为了获得重建过程的感觉,我们沿着图像的一个切片(用红线表示)绘制掩模、种子和放大图像的强度。
    fig, (ax0, ax1, ax2) = plt.subplots(nrows=1, ncols=3, figsize=(8, 2.5))
    yslice = 100
    
    ax0.plot(mask[yslice], '0.5', label='mask')
    ax0.plot(seed[yslice], 'k', label='seed')
    ax0.plot(dilated[yslice], 'r', label='dilated')
    ax0.set_ylim(-0.2, 2)
    ax0.set_title('image slice')
    ax0.set_xticks([])
    ax0.legend()
    
    ax1.imshow(dilated, vmin=image.min(), vmax=image.max(), cmap='gray')
    ax1.axhline(yslice, color='r', alpha=0.4)
    ax1.set_title('dilated')
    ax1.axis('off')
    
    ax2.imshow(hdome, cmap='gray')
    ax2.axhline(yslice, color='r', alpha=0.4)
    ax2.set_title('image - dilated')
    ax2.axis('off')
    '''
    函数功能:绘制平行于x轴的水平参考线
    调用签名:plt.axhline(y=0.0, c="r", ls="--", lw=2)
    y:水平参考线的出发点
    c:参考线的线条颜色
    ls:参考线的线条风格
    lw:参考线的线条宽度
    '''
    
    fig.tight_layout()
    plt.show()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99

    正如你在图像切片中看到的,每个硬币在重建图像中被赋予不同的基线强度;
    这是因为我们使用了局部强度(偏移h)作为种子值。因此,被减去的图像中的硬币具有相似的像素强度。
    最终的结果被称为图像的h-dome,因为这往往会隔离高度h的区域最大值。当你的图像被不均匀照明时,这个操作特别有用。
    在这里插入图片描述

    在这里插入图片描述

  • 相关阅读:
    RPC框架核心技术
    聚观早报 | 微软打造Xbox 手游商店;三星与TikTok推出StemDrop
    你的 Python 代码太慢了吗?协程和多线程来拯救!
    【毕业项目】 云备份
    场景应用:如何在SpringBoot框架下实现一个定时任务?
    896. 最长上升子序列 II 线性dp (优化版 nlogn 贪心+二分)
    vue和react的区别
    「go查漏补缺」命名规则以及 GROM 结构体的应用
    Docker 批量导入镜像
    CentOS 7 安装LibreOffice 7.4.0 过程
  • 原文地址:https://blog.csdn.net/qq_43705330/article/details/125466581