图像处理: 可见光波长(wavelength)与RGB之间的转换

2024-03-15 22:58

本文主要是介绍图像处理: 可见光波长(wavelength)与RGB之间的转换,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

关于颜色转换,有时间看标准当然最好,不过我手头一时没有相关标准,所以参考了一些网上的资料,

380nm 到 760nm的可见光 对应的RGB大概是这个样子的,

C语言版本程序,

//指定波长转换成RGBA颜色
std::vector<int> lambdaToColor(double lambda,double gamma = 0.8,double intensityMax = 255.0)
{double r, g, b, alpha;if (lambda >= 380.0 && lambda < 440.0) {r = -1.0 * (lambda - 440.0) / (440.0 - 380.0);g = 0.0;b = 1.0;}else if (lambda >= 440.0 && lambda < 490.0) {r = 0.0;g = (lambda - 440.0) / (490.0 - 440.0);b = 1.0;}else if (lambda >= 490.0 && lambda < 510.0) {r = 0.0;g = 1.0;b = -1.0 * (lambda - 510.0) / (510.0 - 490.0);}else if (lambda >= 510.0 && lambda < 580.0) {r = (lambda - 510.0) / (580.0 - 510.0);g = 1.0;b = 0.0;}else if (lambda >= 580.0 && lambda < 645.0) {r = 1.0;g = -1.0 * (lambda - 645.0) / (645.0 - 580.0);b = 0.0;}else if (lambda >= 645.0 && lambda <= 780.0) {r = 1.0;g = 0.0;b = 0.0;}else {r = 0.0;g = 0.0;b = 0.0;}//在可见光谱的边缘处强度较低。if (lambda >= 380.0 && lambda < 420.0) {alpha = 0.30 + 0.70 * (lambda - 380.0) / (420.0 - 380.0);}else if (lambda >= 420.0 && lambda < 701.0) {alpha = 1.0;}else if (lambda >= 701.0 && lambda < 780.0) {alpha = 0.30 + 0.70 * (780.0 - lambda) / (780.0 - 700.0);}else {alpha = 0.0;}//1953年在引入NTSC电视时,计算具有荧光体的监视器的亮度公式如下int Y = static_cast<int>(0.212671*r + 0.715160*g + 0.072169*b);//伽马射线 gamma//照明强度 intensityMaxint R = r == 0.0 ? 0 : static_cast<int>(std::round(intensityMax * std::pow(r * alpha, gamma)));int G = g == 0.0 ? 0 : static_cast<int>(std::round(intensityMax * std::pow(g * alpha, gamma)));int B = b == 0.0 ? 0 : static_cast<int>(std::round(intensityMax * std::pow(b * alpha, gamma)));int A = static_cast<int>(alpha);return std::vector<int>{R, G, B, A, Y};
}

另一个转换是通过建立一个事先计算好的表来计算的,这个还没细看,不过感觉通过建立查找表,牺牲一点点空间,可以极大减少运算量,这也是高速程序的一般处理方式。

static class RgbCalculator {const intLEN_MIN = 380,LEN_MAX = 780,LEN_STEP = 5;static readonly double[]X = {0.000160, 0.000662, 0.002362, 0.007242, 0.019110, 0.043400, 0.084736, 0.140638, 0.204492, 0.264737,0.314679, 0.357719, 0.383734, 0.386726, 0.370702, 0.342957, 0.302273, 0.254085, 0.195618, 0.132349,0.080507, 0.041072, 0.016172, 0.005132, 0.003816, 0.015444, 0.037465, 0.071358, 0.117749, 0.172953,0.236491, 0.304213, 0.376772, 0.451584, 0.529826, 0.616053, 0.705224, 0.793832, 0.878655, 0.951162,1.014160, 1.074300, 1.118520, 1.134300, 1.123990, 1.089100, 1.030480, 0.950740, 0.856297, 0.754930,0.647467, 0.535110, 0.431567, 0.343690, 0.268329, 0.204300, 0.152568, 0.112210, 0.081261, 0.057930,0.040851, 0.028623, 0.019941, 0.013842, 0.009577, 0.006605, 0.004553, 0.003145, 0.002175, 0.001506,0.001045, 0.000727, 0.000508, 0.000356, 0.000251, 0.000178, 0.000126, 0.000090, 0.000065, 0.000046,0.000033},Y = {0.000017, 0.000072, 0.000253, 0.000769, 0.002004, 0.004509, 0.008756, 0.014456, 0.021391, 0.029497,0.038676, 0.049602, 0.062077, 0.074704, 0.089456, 0.106256, 0.128201, 0.152761, 0.185190, 0.219940,0.253589, 0.297665, 0.339133, 0.395379, 0.460777, 0.531360, 0.606741, 0.685660, 0.761757, 0.823330,0.875211, 0.923810, 0.961988, 0.982200, 0.991761, 0.999110, 0.997340, 0.982380, 0.955552, 0.915175,0.868934, 0.825623, 0.777405, 0.720353, 0.658341, 0.593878, 0.527963, 0.461834, 0.398057, 0.339554,0.283493, 0.228254, 0.179828, 0.140211, 0.107633, 0.081187, 0.060281, 0.044096, 0.031800, 0.022602,0.015905, 0.011130, 0.007749, 0.005375, 0.003718, 0.002565, 0.001768, 0.001222, 0.000846, 0.000586,0.000407, 0.000284, 0.000199, 0.000140, 0.000098, 0.000070, 0.000050, 0.000036, 0.000025, 0.000018,0.000013},Z = {0.000705, 0.002928, 0.010482, 0.032344, 0.086011, 0.197120, 0.389366, 0.656760, 0.972542, 1.282500,1.553480, 1.798500, 1.967280, 2.027300, 1.994800, 1.900700, 1.745370, 1.554900, 1.317560, 1.030200,0.772125, 0.570060, 0.415254, 0.302356, 0.218502, 0.159249, 0.112044, 0.082248, 0.060709, 0.043050,0.030451, 0.020584, 0.013676, 0.007918, 0.003988, 0.001091, 0.000000, 0.000000, 0.000000, 0.000000,0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000,0.000000};static readonly double[]MATRIX_SRGB_D65 = {3.2404542, -1.5371385, -0.4985314,-0.9692660,  1.8760108,  0.0415560,0.0556434, -0.2040259,  1.0572252};public static byte[] Calc(double len) {if(len < LEN_MIN || len > LEN_MAX)return new byte[3];len -= LEN_MIN;var index = (int)Math.Floor(len / LEN_STEP);var offset = len - LEN_STEP * index;var x = Interpolate(X, index, offset);var y = Interpolate(Y, index, offset);var z = Interpolate(Z, index, offset);var m = MATRIX_SRGB_D65;var r = m[0] * x + m[1] * y + m[2] * z;var g = m[3] * x + m[4] * y + m[5] * z;var b = m[6] * x + m[7] * y + m[8] * z;r = Clip(GammaCorrect_sRGB(r));g = Clip(GammaCorrect_sRGB(g));b = Clip(GammaCorrect_sRGB(b));return new[] { (byte)(255 * r),(byte)(255 * g),(byte)(255 * b)};}static double Interpolate(double[] values, int index, double offset) {if(offset == 0)return values[index];var x0 = index * LEN_STEP;var x1 = x0 + LEN_STEP;var y0 = values[index];var y1 = values[1 + index];return y0 + offset * (y1 - y0) / (x1 - x0);}static double GammaCorrect_sRGB(double c) {if(c <= 0.0031308)return 12.92 * c;var a = 0.055;return (1 + a) * Math.Pow(c, 1 / 2.4) - a;}static double Clip(double c) {if(c < 0)return 0;if(c > 1)return 1;return c;}
}

另外有一个python版本在这里,暂时用不到,挂个号在这里吧

#!/usr/bin/env python
# vim:set ft=python fileencoding=utf-8 sr et ts=4 sw=4 : See help 'modeline''''== A few notes about color ==Color   Wavelength(nm) Frequency(THz)Red     620-750        484-400Orange  590-620        508-484Yellow  570-590        526-508Green   495-570        606-526Blue    450-495        668-606Violet  380-450        789-668f is frequency (cycles per second)l (lambda) is wavelength (meters per cycle)e is energy (Joules)h (Plank's constant) = 6.6260695729 x 10^-34 Joule*seconds= 6.6260695729 x 10^-34 m^2*kg/secondsc = 299792458 meters per secondf = c/ll = c/fe = h*fe = c*h/lList of peak frequency responses for each type of photoreceptor cell in the human eye:S cone: 437 nmM cone: 533 nmL cone: 564 nmrod:    550 nm in bright daylight, 498 nm when dark adapted. Rods adapt to low light conditions by becoming more sensitive.Peak frequency response shifts to 498 nm.'''import sys
import os
import traceback
import optparse
import time
import loggingdef wavelength_to_rgb(wavelength, gamma=0.8):'''This converts a given wavelength of light to an approximate RGB color value. The wavelength must be givenin nanometers in the range from 380 nm through 750 nm(789 THz through 400 THz).Based on code by Dan Brutonhttp://www.physics.sfasu.edu/astro/color/spectra.html'''wavelength = float(wavelength)if wavelength >= 380 and wavelength <= 440:attenuation = 0.3 + 0.7 * (wavelength - 380) / (440 - 380)R = ((-(wavelength - 440) / (440 - 380)) * attenuation) ** gammaG = 0.0B = (1.0 * attenuation) ** gammaelif wavelength >= 440 and wavelength <= 490:R = 0.0G = ((wavelength - 440) / (490 - 440)) ** gammaB = 1.0elif wavelength >= 490 and wavelength <= 510:R = 0.0G = 1.0B = (-(wavelength - 510) / (510 - 490)) ** gammaelif wavelength >= 510 and wavelength <= 580:R = ((wavelength - 510) / (580 - 510)) ** gammaG = 1.0B = 0.0elif wavelength >= 580 and wavelength <= 645:R = 1.0G = (-(wavelength - 645) / (645 - 580)) ** gammaB = 0.0elif wavelength >= 645 and wavelength <= 750:attenuation = 0.3 + 0.7 * (750 - wavelength) / (750 - 645)R = (1.0 * attenuation) ** gammaG = 0.0B = 0.0else:R = 0.0G = 0.0B = 0.0R *= 255G *= 255B *= 255return (int(R), int(G), int(B))def main(options=None, args=None):#    import ppm_dump
#    import png_canvasimport canvasif options.ppm:canvas = canvas.ppm_canvas(371, 278)canvas.is_ascii = Trueelse:canvas = canvas.png_canvas(371, 278)for wl in range(380, 751):r, g, b = wavelength_to_rgb(wl)for yy in range(0, 278):canvas.pixel(wl - 380, yy, r, g, b)sys.stdout.write(str(canvas))if __name__ == '__main__':try:start_time = time.time()parser = optparse.OptionParser(formatter=optparse.TitledHelpFormatter(),usage=globals()['__doc__'],version='1')parser.add_option('-v', '--verbose', action='store_true',default=False, help='verbose output')parser.add_option('--png', action='store_true',default=True, help='Output as PNG.')parser.add_option('--ppm', action='store_true',default=False, help='Output as PPM ASCII (Portable Pixmap).')(options, args) = parser.parse_args()#if len(args) < 1:#    parser.error ('missing argument')if options.verbose:print(time.asctime())exit_code = main(options, args)if exit_code is None:exit_code = 0if options.verbose:print(time.asctime())print('TOTAL TIME IN MINUTES: %f'% ((time.time() - start_time) / 60.0))sys.exit(exit_code)except KeyboardInterrupt as e:  # The user pressed Ctrl-C.raise eexcept SystemExit as e:  # The script called sys.exit() somewhere.raise eexcept Exception as e:print('ERROR: Unexpected Exception')print(str(e))traceback.print_exc()os._exit(2)

【1】 https://stackoverflow.com/questions/1472514/convert-light-frequency-to-rgb

【2】http://www.noah.org/wiki/Wavelength_to_RGB_in_Python

 

这篇关于图像处理: 可见光波长(wavelength)与RGB之间的转换的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/813534

相关文章

java父子线程之间实现共享传递数据

《java父子线程之间实现共享传递数据》本文介绍了Java中父子线程间共享传递数据的几种方法,包括ThreadLocal变量、并发集合和内存队列或消息队列,并提醒注意并发安全问题... 目录通过 ThreadLocal 变量共享数据通过并发集合共享数据通过内存队列或消息队列共享数据注意并发安全问题总结在 J

Java数字转换工具类NumberUtil的使用

《Java数字转换工具类NumberUtil的使用》NumberUtil是一个功能强大的Java工具类,用于处理数字的各种操作,包括数值运算、格式化、随机数生成和数值判断,下面就来介绍一下Number... 目录一、NumberUtil类概述二、主要功能介绍1. 数值运算2. 格式化3. 数值判断4. 随机

Java文件与Base64之间的转化方式

《Java文件与Base64之间的转化方式》这篇文章介绍了如何使用Java将文件(如图片、视频)转换为Base64编码,以及如何将Base64编码转换回文件,通过提供具体的工具类实现,作者希望帮助读者... 目录Java文件与Base64之间的转化1、文件转Base64工具类2、Base64转文件工具类3、

C语言中自动与强制转换全解析

《C语言中自动与强制转换全解析》在编写C程序时,类型转换是确保数据正确性和一致性的关键环节,无论是隐式转换还是显式转换,都各有特点和应用场景,本文将详细探讨C语言中的类型转换机制,帮助您更好地理解并在... 目录类型转换的重要性自动类型转换(隐式转换)强制类型转换(显式转换)常见错误与注意事项总结与建议类型

Python实现视频转换为音频的方法详解

《Python实现视频转换为音频的方法详解》这篇文章主要为大家详细Python如何将视频转换为音频并将音频文件保存到特定文件夹下,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1. python需求的任务2. Python代码的实现3. 代码修改的位置4. 运行结果5. 注意事项

使用Python实现图片和base64转换工具

《使用Python实现图片和base64转换工具》这篇文章主要为大家详细介绍了如何使用Python中的base64模块编写一个工具,可以实现图片和Base64编码之间的转换,感兴趣的小伙伴可以了解下... 简介使用python的base64模块来实现图片和Base64编码之间的转换。可以将图片转换为Bas

Linux使用dd命令来复制和转换数据的操作方法

《Linux使用dd命令来复制和转换数据的操作方法》Linux中的dd命令是一个功能强大的数据复制和转换实用程序,它以较低级别运行,通常用于创建可启动的USB驱动器、克隆磁盘和生成随机数据等任务,本文... 目录简介功能和能力语法常用选项示例用法基础用法创建可启动www.chinasem.cn的 USB 驱动

Python 标准库time时间的访问和转换问题小结

《Python标准库time时间的访问和转换问题小结》time模块为Python提供了处理时间和日期的多种功能,适用于多种与时间相关的场景,包括获取当前时间、格式化时间、暂停程序执行、计算程序运行时... 目录模块介绍使用场景主要类主要函数 - time()- sleep()- localtime()- g

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

Java将时间戳转换为Date对象的方法小结

《Java将时间戳转换为Date对象的方法小结》在Java编程中,处理日期和时间是一个常见需求,特别是在处理网络通信或者数据库操作时,本文主要为大家整理了Java中将时间戳转换为Date对象的方法... 目录1. 理解时间戳2. Date 类的构造函数3. 转换示例4. 处理可能的异常5. 考虑时区问题6.