目录
引言
最近在研究光谱图如何分析,在Github上面找到了一份开源项目,在此分享一下。
光谱分析(Spectroscopy)是一种通过测量和分析物质与电磁辐射相互作用来研究物质组成和性质的方法。它广泛应用于化学、物理、生物学、天文学等多个领域。
光谱分析基于的原理:当物质与电磁辐射(如光)相互作用时,不同物质会吸收、发射或散射特定波长的电磁辐射。这些相互作用的特征波长可以作为物质的“指纹”,帮助识别物质的种类和结构。
光谱分析系统由网络摄像头、简单的激光切割部件、电池外壳和合适的LED照明组件组成。光谱仪通过USB连接到计算机,从而可以运行此存储库中提供的脚本来运行实验并进行测量。该存储库的两个主要组件是analysis.py和calibrate.py。analysis.py脚本用于绘制网络摄像头光谱仪测量的吸收光谱。calibrate.py脚本提供了科学测量机制与如何评估所生成数据质量的标准。
组件介绍
1.analysis.py组件
为了从光谱数据中提取有效的信息,并将其可视化为吸光度图表,编制了analyse_csv.py代码提取、处理和可视化图像中的光谱数据,设置多个重要步骤和函数进行实现。
如何使用analysis.py做实验并收集数据?
- 通过USB将光谱仪连接至电脑
- 将液体样品转移到比色皿(光谱用液体容器)中,并将其放置在光谱仪中。 如果是叶绿素A和B,您可以自己进行提取和分离。
- 使用上述光谱工作台通过网络摄像头光谱仪进行测量。
- 将参考文件名插入到referenceFile槽中,将所有示例的文件名插入到samples槽中,并用逗号分隔。
- 在下方插入所需的绘图标题和图例标题。
- 查看测量结果和脚本,并将获得的图与文献中找到的叶绿素A和B的光谱吸光度进行比较(在线搜索叶绿素吸光度)。
analyse.py代码
analyse.py组件部分代码如下所示:
# 导入必要的库
import math # 用于数学计算
import matplotlib.image as img # 用于处理PNG图像
import matplotlib.pyplot as plt # 用于生成图表
import matplotlib.patches as mpatches # 用于添加图表的补丁
import numpy as np # 用于数组操作和数学运算
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置为支持中文的字体
plt.rcParams['axes.unicode_minus'] = False # 防止使用中文时出现负号显示异常
# 用户定义的参数,包括要处理的文件和其他设置
referenceFile = "IPA_Glass.png" # 基准文件名
samples = ["1_IPA_Glass.png", "2_IPA_Glass.png"] # 样本文件名列表
plotDirectly = [] # 尚未使用的变量,可能用于直接绘制的样本
# 图表标题和颜色
title = "异丙醇中的叶绿素A和B" # 图表标题
plotColors = ["purple", "darkgreen"] # 图表中不同数据的颜色
patchLabels = ["叶绿素a", "叶绿素b"] # 图表补丁的标签
# 保存绘制图表的文件名
saveFilename = "plot.png" # 保存的PNG文件名
# 校准信息,描述了像素与波长的对应关系
pixel = [115, 146, 193, 250, 312, 329, 404] # 像素位置
wavelength = [405.4, 436.6, 487.7, 546.5, 611.6, 631.1, 708] # 对应的波长
# 从PNG文件提取光谱数据的函数
def getSpectrum_PNG(filename):
'''
从PNG图像中提取光谱。光谱是通过对整个图像的每个列的RGB值进行平均计算出来的。
'''
# 读取PNG图像
print("读取图像") # 打印正在读取图像的消息
image = img.imread(filename) # 使用matplotlib.image读取图像
# 初始化变量
imageR, imageG, imageB = [], [], [] # 分别存储RGB通道的数值
imgWidth = len(image[0]) # 图像宽度
imgHeight = len(image) # 图像高度
# 获取每个像素列的RGB值
for i in range(imgWidth): # 遍历每个列
imageR.append(image[0][i][0]) # 获取红色通道
imageG.append(image[0][i][1]) # 获取绿色通道
imageB.append(image[0][i][2]) # 获取蓝色通道
# 计算每个像素列的RGB值总和
for i in range(imgHeight): # 遍历每个行
for j in range(imgWidth): # 遍历每个列
imageR[j] += image[i][j][0] # 将每个像素的红色值累加
imageG[j] += image[i][j][1] # 将每个像素的绿色值累加
imageB[j] += image[i][j][2] # 将每个像素的蓝色值累加
# 计算每个像素列的RGB值的平均值
for i in range(imgWidth): # 遍历每个列
imageR[i] /= imgHeight # 平均红色通道
imageG[i] /= imgHeight # 平均绿色通道
imageB[i] /= imgHeight # 平均蓝色通道
# 合并RGB通道来计算光谱
spectrum = [] # 光谱结果
for i in range(imgWidth): # 遍历每个列
spectrum.append((imageR[i] + imageG[i] + imageB[i]) / 3) # 合并RGB通道
# 返回光谱结果
return spectrum
# 从CSV文件中提取光谱数据的函数
def getSpectrum_CSV(filename):
'''
从CSV文件中提取光谱数据。该文件包含一系列数值,函数会将其拆分并返回光谱数据列表。
'''
# 读取CSV文件
print("Reading csv file") # 打印正在读取CSV文件的消息
with open(filename, "r") as inFile: # 打开CSV文件
CSVline = inFile.read() # 读取CSV文件内容
# 拆分数值
spectrumSTR = CSVline.split(",") # 使用逗号拆分
# 将字符串转换为浮点数
spectrum = [] # 初始化光谱数据列表
for value in spectrumSTR: # 遍历拆分后的字符串
spectrum.append(float(value)) # 将字符串转换为浮点数并添加到列表
# 返回光谱结果
return spectrum
#getSpectrum_PNG(filename): 从PNG文件中提取光谱,基于图像的RGB通道。
#getSpectrum_CSV(filename): 从CSV文件中提取光谱,基于文件中的数值。
#它还设置了一些全局参数,包括图表的颜色和标题,以及像素与波长的校准信息。
# 这些函数可以用于从图像和CSV文件中提取光谱数据,然后可以用于进一步的分析或图表绘制。
2.calibrate.py组件
如何使用calibrate.py校准您的设备?
calibrate_csv.py组件主要是针对analyse_csv.py组件进行校准工作。校准光谱仪意味着将原本代表像素的数值转换成波长,元素的数值是由光谱仪测量的。为了在元素和波长之间建立关联,使用了一种汞灯泡,即紧凑型荧光灯(CFL)。由于其发射峰很尖锐,因此可以为某些元素指定一些特定的波长值,并推断出所有其他波长值。
作为参考,标记的荧光光谱峰值图像如下:
使用calibrate.py的步骤:
- 使用紧凑型荧光灯 (CFL)生成的文件运行脚本 calibrate.py。
- 使用放大镜记录维基百科参考图中哪个像素对应于哪个峰值。
- 至少取3个相关性,但越多越好。
- 打开主脚本,并按升序插入(替换)先前在相应插槽中记录的像素和波长。
calibrate.py代码
calibrate.py部分代码如下所示:
#从PNG图像中提取光谱,并绘制图表
import io, sys # 导入输入/输出和系统模块
import matplotlib.image as img # 用于读取图像
import matplotlib.pyplot as plt # 用于绘制图表
import math # 用于数学运算
from mpl_toolkits.mplot3d.axes3d import Axes3D # 用于3D绘图
from matplotlib import cm # 用于颜色映射
from matplotlib.collections import PolyCollection # 用于处理多边形集合
from matplotlib import colors as mcolors # 用于颜色操作
plt.rcParams['font.sans-serif'] = ['SimHei'] # 设置为支持中文的字体
plt.rcParams['axes.unicode_minus'] = False # 防止使用中文时出现负号显示异常
# ------ 文件名配置 ----------------
calibFile = "cfl.png" # 待处理的PNG图像
saveFilename = "cfl_plot.png" # 保存图表的文件名
# ----------- 函数定义 ----------------------------
def getSpectrumPNG(filename):
'''从PNG文件中提取光谱。每个通道的光谱是通过对整个图像的列进行平均来计算的'''
# 读取图像
image = img.imread(filename)
# 初始化RGB通道的数组
imageR = [] # 存储红色通道
imageG = [] # 存储绿色通道
imageB = [] # 存储蓝色通道
imgWidth = len(image[0]) # 图像宽度
imgHeight = len(image) # 图像高度
# 准备数组,初始化第一行的RGB值
for i in range(imgWidth):
imageR.append(image[0][i][0]) # 第一个像素的红色通道
imageG.append(image[0][i][1]) # 第一个像素的绿色通道
imageB.append(image[0][i][2]) # 第一个像素的蓝色通道
# 对每个列进行累加
for i in range(imgHeight): # 遍历每个行
for j in range(imgWidth): # 遍历每个列
imageR[j] += image[i][j][0] # 累加红色通道
imageG[j] += image[i][j][1] # 累加绿色通道
imageB[j] += image[i][j][2] # 累加蓝色通道
# 计算每个列的平均值
for i in range(imgWidth):
imageR[i] = imageR[i] / imgHeight # 红色通道的平均值
imageG[i] = imageG[i] / imgHeight # 绿色通道的平均值
imageB[i] = imageB[i] / imgHeight # 蓝色通道的平均值
# 将RGB通道合并,得到最终的光谱
spectrum = []
for i in range(imgWidth): # 遍历每个列
spectrum.append((imageR[i] + imageG[i] + imageB[i]) / 3) # 平均RGB通道
# 返回光谱
return spectrum
两个组件可以分析通过分光仪形成的光谱图,并且可以生成csv格式的数据文件进行进一步的分析。