将RGB像素转换为波长

3
我需要确定一个光源发出的光谱(分光仪)。为了做到这一点,我需要将每个像素转换为波长。
为了解决RGB值没有单一值的问题,我将使用棱镜来获得光学格子。这样,我就可以接收到光谱的部署,而光谱的差异仅沿X轴。
我的问题是,如何将像素转换为波长,并以波长的强度作为函数获得图形。

1
这个问题是虚假的。RGB表达的并不是所有单色光。例如,白色对应的波长是多少? - user2271770
在光谱范围内没有白色。 - Moti S
@MotiS 在连续光谱中,没有任何三种波长的组合(一种红色、一种绿色和一种蓝色)可以相加得到另一种单一的波长(除非其中两种波长的强度为零)。 - user2271770
棱镜用于获取衍射,结果是光谱。 - Moti S
@CST-Link 是的,大多数颜色范围是波长的组合,但非常明确地不包括来自任何光源的棱镜或光栅扩展光谱。 - Carl Witthoft
显示剩余2条评论
4个回答

3
  1. You have to get wavelength from x position

    You can not compute wavelength from color as the two are not the same thing. So first you should calibrate your spectroscope with known wavelengths. From that infer function:

    wavelength = f(x)
    

    either by LUT and interpolation, or by approximation polynomial. For more info see:

    You can use Sun light as a reference and calibrate based on the known spectral (Fraunhofer) lines. Here first example I found on google:

    Sun reference

    So take/plot a sunlight shot here mine:

    My shot of Sun

    cross match the Fraunhofer lines (the darker lines, beware of over exponated images they can screw things up, also the Intensity is R+G+B without weight we do not want human perception like conversion) and make a table of Known wavelengths x positions in your image. From that interpolate your wavelength = f(x).

    As you can see my shot of Sun's spectra more or less matches the reference one (discrepances are due to grating material, bayer filter, camera properties, clouds and atmosphere,etc...). How ever the Fraunhofer lines are not easily detectable by local minima so may be some user assistance GUI style will be a better idea to start with.

    But beware that most spectra images on the WEB is wrong or nonlinear or shifted !!! So to be sure I created a reference spectra from linearized spectral data like this and here the result 400-700 [nm]:

    real linearized unshifted sunlight spectra

    And here the plot:

    plot for real data

    the gray lines are grid from 400-700 nm with 10 nm step.

    Here is how your setup should look like:

    spectro-meter

    Here is image from mine spectro-scope (looking at White area on my LCD):

    White on my LCD

    I am using grating grid made from DVD hence the circular arc shapes. Now if your camera is in fixed position relative to your prism then for selected horizontal line the x position of pixel directly corresponds to a specific wavelength.

    If you do not see any Fraunhofer lines then you are missing aperture before the prism/grating. I usually use 2 razor blades distanced by 0.1 mm set by thin paper. If your image is out of focus you need to add lens(es) before your camera/sensor and or add more shielding from outside light.

    As I mentioned before You cannot get wavelength from color because there is "infinite" combinations of input spectra creating the same RGB response. For example take white color ... it can be composed form 3 or more distinct wavelengths or even continuous white noise. So from RGB you can not tell which one it is... If you add also the x positon with combination of prism/grating then you can get the wavelength but it would be much more complicated and less precise then direct conversion from just x position...

  2. compute intensity from RGB

    this may be a bit tricky as your sensor may have different sensitivity for different wavelengths. You can normalize intensity similarly to #1. Just take shot of known intensity light source and approximate for the missing wavelengths. Also this can be done with Sunlight as a source

    From normalized color you just compute gray-scale intensity and that is it.

    To improve accuracy you can average all the pixels for the same x.

    Also to boost accuracy and sensitivity usually non color sensor is used (mostly linear cameras) either by design or by removing the Bayer filter so it does not mess up the data.

  3. plot the data

    on x axis is the wavelength and on y axis is the intensity. If you want to apply spectral colors you can use this:

注意校准数据可能随温度变化而改变...

2
晚来了。但这里有一个准确(接近科学方法)将传感器像素的RGB转换为波长图中强度值的想法。
  1. 获取已知波长的光源。

发射带宽越窄,越好。激光适用于此类要求,但也请注意功率,并确保不超过您的图像传感器限制。最好使用三种波长(红色、绿色、蓝色)校准测量系统。理想情况下,当使用红色激光时,读取原始图像并查看像素的绿色和蓝色通道上是否存在任何电荷积累。(因为每个像素都有贝尔滤波器模式)。如果积累过高,请考虑使用高质量的图像传感器。然后,按照Noel Segura Meraz建议的HSV方法进行操作。对您拍摄的图像使用垂直合并。垂直合并是指简单地将传感器阵列中一列的强度值相加。一旦您使用这三种激光校准了系统,请混合和匹配它们以验证您的插值函数是否有效。

  1. 获取图像传感器中像素的波长效率
如果无法从图像传感器的规格表中获取此信息,则在图像传感器之前的光学设置中引入一个细长的垂直缝隙,从而仅选择特定波长。获取每个波长的所有垂直分组强度值以表征您的图像传感器。缝隙应该不要太细,以免引入光的衍射效应。如果图像传感器对每个波长具有几乎相同的强度值,则其特性将非常好。使用此数据来缩放从步骤1获得的波长与强度图。

  1. 在光学设置之前使用宽带输入光源以获得最佳光谱效果
虽然您正在尝试实现的目标是完全有效的,但这并不是高度精确的仪器系统,因此不被研究人员/工业所使用。在真正的光谱仪中,主要使用光栅,通过光栅上线条之间的距离和入射角度来计算CCD传感器(或事实上任何线性阵列的光电传感器)上的波长展宽。通常,调整此角度以实现所需的波长展宽而不失分辨率。以下是一个Andor的示例,用于设计一个使用其产品的系统。

1
如果我正确理解你想要实现的内容,那么它是可行的(有点),但需要校准。
首先,您想要在hsv空间中工作,可以使用rgb2hsv来完成此操作。
在HSV空间中,“V”或“value”将为您提供给定像素的光强度。这将是您想要绘制的值,以获得所示图形的值。您可以获取每个像素列的平均值,或仅分析中心行,以获得更好的效果。
现在,有趣的部分。如何获取您图表的x轴值。理论上讲,您的棱镜将把光分成特定的波长,并且每个波长都将具有唯一的“H”或“hue”值,相关性由
Hue = (650 - wavelength)*240/(650-475)

更多关于此的信息在这里

但这只在理想光照条件下并且您的相机足够灵敏且其CCD具有真正的绿色,红色和蓝色时才能起作用,我不知道如何测试。更不用说您在显示器中看到的波长也取决于显示器的校准,所以我不会信任它。

您可以通过'S'或'saturation'的值来检查每个像素的纯度和理想程度。值越高,效果越好。

我建议您手动校准它。查看您的光谱,并使用铅笔或其他东西标记您知道其波长的颜色的位置,然后使用这些标记来定义图表的x轴。


我忘了提到,你只需要进行一次校准,一旦你知道相机中哪个波长对应哪个色调,你就可以自动进行设置,甚至使用scatter(hue_wavelenght,value)可能也可以。


我相信OP正在使用未经过滤的探测器,即每个像素对所有波长都有响应(尽管效率不同)。这就是光谱仪的工作原理。 - Carl Witthoft

0

我建议先尝试反转this code,因为它实际上是与你所需要的相反的。而最终的部分(% LET THE INTENSITY SSS FALL OFF NEAR THE VISION LIMITS)对于你的案例来说没有什么关联性,它只是试图重新创建人类感知。

如果你真的想要一个准确运行的系统,你需要建立某种校准流程。大多数摄像头并不是非常准确,而且行为会随着温度等因素的改变而变化,因此必须重复操作。

你是否也考虑过使用位置来识别波长呢?当一切都设置在固定位置时,你可以计算出每种波长在表面上的位置。剩下的工作就是建立某种校准映射,将像素与波长相关联,需要付出一些努力,但一旦你将所有东西设置在固定位置,这是一次性的校准。另一个优点是,一旦你把比例尺写在表面上,你就有了一种简单的方式来记录和验证传感数据。


1
没错,但你需要重新校准棱镜。这是一项繁琐的工作,因为大多数玻璃类型都具有非线性色散。这就是为什么所有商用光谱仪都使用光栅的原因。 - Carl Witthoft
@CarlWitthoft 自制光谱仪也使用光栅,因为它更容易获得(由CD或DVD制成)。要获得棱镜,通常需要解剖一些光学系统。 - Spektre

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接