当前位置:网站首页>skimage学习(3)——使灰度滤镜适应 RGB 图像、免疫组化染色分离颜色、过滤区域最大值
skimage学习(3)——使灰度滤镜适应 RGB 图像、免疫组化染色分离颜色、过滤区域最大值
2022-07-07 15:32:00 【原知】
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的区域最大值。当你的图像被不均匀照明时,这个操作特别有用。
边栏推荐
- Cesium (4): the reason why gltf model is very dark after loading
- Laravel service provider instance tutorial - create a service provider test instance
- 二叉搜索树(特性篇)
- 【PHP】PHP接口继承及接口多继承原理与实现方法
- 字节跳动Android金三银四解析,android面试题app
- Laravel post shows an exception when submitting data
- Imitate the choice of enterprise wechat conference room
- Pisa-Proxy SQL 解析之 Lex & Yacc
- Arduino 控制的双足机器人
- 爬虫(17) - 面试(2) | 爬虫面试题库
猜你喜欢
随机推荐
二叉搜索树(特性篇)
Usage of config in laravel
二叉搜索树(基操篇)
【医学分割】attention-unet
Arduino 控制的双足机器人
OpenGL personal notes
AutoLISP series (3): function function 3
Personal notes of graphics (1)
node:504报错
字节跳动Android金三银四解析,android面试题app
PHP realizes wechat applet face recognition and face brushing login function
The team of East China Normal University proposed the systematic molecular implementation of convolutional neural network with DNA regulation circuit
What is the difference between IP address and physical address
As an Android Developer programmer, Android advanced interview
Spark Tuning (III): persistence reduces secondary queries
Binary search tree (features)
logback.xml配置不同级别日志,设置彩色输出
URL和URI的关系
LeetCode 1031. 两个非重叠子数组的最大和 每日一题
JS中null NaN undefined这三个值有什么区别