通常荧光成像的定量分析都离不开实验室里相对昂贵的仪器设备,这限制了一系列荧光报告方法的诊断技术的实际应用。所以有不少研究都尝试使用手机相机作为信号检测的工具。

实验室里的荧光检测设备动辄几十上百万,而手机一般数千元,从「一分钱一分货」的常识判断,手机检测必然存在准确性不如酶标仪、显微镜之类的好。不过大家还是想了不少办法来提高手机检测荧光信号的可靠性。

手机彩色相机与色彩滤波阵列

其中一个办法就是数据处理方面。手机相机光学传感器一般是 CMOS,单独CMOS只能感光,而我们知道手机是可以拍摄彩色照片的,这是因为使用了「色彩滤波阵列」,比如 Bayer filter。这类 filter 能够允许通过的光波的光谱如下所示:

有文章也实际测量过20多款主流手机能够检测的光谱范围,基本跟上图一致1


由于色彩滤波阵列的存在,手机采集的彩色图像数据,实际上是这三种光谱的光按照不同比例组合而成。然后手机处理器会自动基于每个像元组合(RGGB,四个像元一组代表一个像素)采集到的原始强度数值换算为RGB颜色数值,从而方便显示到手机屏幕上。

所以使用手机相机进行检测的时候,要想更准确地解析荧光信号强度,就是要还原这个过程,即需要对RGB图像进行处理,基于上述光谱组成和混色原理,来提取指定通道的亮度。

xyz颜色空间

对于一张RGB图像,如果我们想查看它所代表的亮度,一个常见的方法是转换到 HSV 颜色空间,使用 Hue 和 Saturation 两个来表示其颜色,使用 Value 这个分量来表示亮度。但HSB颜色空间中,亮度简单地等于RGB三个分量的最大值(RGB转HSV公式如下),虽然能够比较好地描述这个颜色本身,但这个与人眼对亮度的感知不吻合。

文献中常用的是国际照明委员会(CIE)发布的xyz 颜色空间。XYZ不用于描述颜色,而用于说明光波如何组合会产生什么样的颜色。这个颜色空间提出了三种不使用单色光的假想光源,其RGB颜色匹配函数如下所示:

由于 z 是由 xy 决定的数值,所以直接使用 xy 就能表示一个颜色空间,如下所示:

上面这个图在中文网络中也常被形象地叫做「色域马蹄图」,更多内容详见知乎。可以看到在这个颜色空间中,xy两个分量就表示了颜色。而亮度则用 Y 分量来表示。

CIE通过实验测定了RGB到XYZ颜色空间的转换参数,如上图所示,那么我们就可以直接通过简单的运算,从RGB图像中提取到一个相对更加准确的荧光信号亮度,这也是文献中常用的方法2

不同方法提取的信号强度比较

python中的skimage提供了各种颜色空间转换的函数,非常方便。所以这里可以快速实验下,看看各种从RGB图像中提取出一个能够表示荧光信号强度的指标的差异。

如上图所示,rgb可以转化的色彩空间很多,其它的比如 yuv,虽然也有用一个单独的 y 分量来代表亮度,但是这个色彩空间是为了方便影视工业的,其转换公式也是从这类工程场景中提炼出来的。

所以不同的颜色空间具有不同的用途。这里我们就比较下 hsv, xyzyuv 三种颜色空间里的亮度情况,结果如下:

可以看到,当我们仅增加RGB颜色中Green通道的数值,在上述三种颜色空间中,xyz的亮度变化是最大的,从 0.178增加到0.720,提升了4倍。而其它两种仅提升了两倍不到。这说明 xyz 颜色空间提取的亮度,更加灵敏准确。

相关实验代码如下:

from skimage import color
import matplotlib.pyplot as plt
import numpy as np

c = [36, 135, 23]
tmp = np.ones((20, 20, 3), dtype='int64')
tmp *= c
img = tmp.astype("uint8")
plt.figure(figsize=(2,2))
plt.imshow(img)
plt.text(x=1, y=10, s=f"RGB={c}")
plt.axis("off")
plt.show()


box = []
for item in dir(color):
    if item.startswith("rgb2"):
        box.append(item)
# 将color对象中关于rgb转换颜色空间的方法名收集起来

bag = {
       'hsv': 2,
       'xyz': 1,
       'yuv': 0,
       }
# 不同颜色空间分量中表示亮度的索引


for item in box:
    for key in bag:
        if item.endswith(key):
            dat = getattr(color, item)(img)
            res = dat[0,0]
            v = res[bag[key]]
            print(key, '亮度', v)
# 调用不同的颜色空间转换方法来提取亮度

  1. Measurement and Estimation of Spectral Sensitivity Functions for Mobile Phone Cameras, Sensors, 2021. https://doi.org/10.3390/s21154985
  2. Colorimetric-Luminance Readout for Quantitative Analysis of Fluorescence Signals with a Smartphone CMOS Sensor, Analytical Chemistry, 2018. https://doi.org/10.1021/acs.analchem.8b03521
最后修改:2025 年 05 月 21 日
请大力赞赏以支持本站持续运行!