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()

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

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()

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

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()

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

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值