我有 16 位原始图像(12 个有效位)。我将其转换为 RGB,现在我想更改动态范围。我创建了 2 个 map 函数。您可以在下面看到它们的可视化。正如您所看到的,第一个函数将值 0-500 映射到 0-100,第二个函数将其余值映射到 101-255。
现在我想在 RGB 图像上应用映射函数。我正在做的是迭代每个像素,为每个 channel 找到适当的函数并将其应用到 channel 上。例如,像素为RGB=[100 2000 4000]。在 R channel 上,我将应用第一个函数,因为 100 在 0-500 范围内。但是,在 G 和 B channel 上,我将应用第二个函数,因为它们的值在 501-4095 之间。
但是,通过这种方式,我实际上改变了像素的实际颜色,因为我在像素的 channel 上应用了不同的函数。
你能建议如何做,或者至少给我一个方向或展示一些文章吗?
最佳答案
您正在做的是非常简单的成像操作,经常应用于图像和视频处理。有时它(不准确地)被称为查找表 (LUT),尽管它并不总是通过实际的查找表来实现。这方面的例子有 Gamma 调整或对数编码。
例如,这种编码的一个例子是 sRGB,它是线性光的 Gamma 编码。您可以在这里阅读:http://en.wikipedia.org/wiki/SRGB 。您会看到它具有非线性调整。
LUT 这个名字暗示了一种很好的实现方法。如果您可以将图像设为 uint8 或 uint16 值集,则可以为任何输入值创建所需输出值的向量。查找表具有与变量类型的可能范围相同数量的元素。如果您使用 uint8,您将拥有一个包含 256 个值的查找表。然后查找就很容易了,您只需使用图像值作为 LUT 的索引即可获取结果值。计算效率是 LUTS 如此广泛使用的原因。
就您而言,由于您在 RGB 空间中工作,因此可以以完全相同的方式将曲线应用于三个颜色 channel 中的每一个。由于这个原因,RGB 空间很不错。然而,由于各种原因,有时每个 channel 实现不同的 LUT。
因此,如果您有一张图像(我们将使用 MATLAB 中包含的图像,并通过缩放来假装它是 12 位):
someimage = uint16(imread('autumn.tif')).*16;
image(someimage.*16); % Need to multiply again to display 16 bit data scaled properly
对于您的 LUT,您可以将其实现为:
lut = uint8([(0:500).*(1/5), (501:4095).*((255-101)/(4095-501)) + 79.5326]);
plot(lut); %Take a look at the lut
这将进行您在问题中描述的分段计算。
您可以这样制作新图像:
convertedimage = lut(double(someimage)+1);
image(convertedimage);
请注意,由于 MATLAB 使用 double 索引(基于 1),因此您需要正确转换并加 1。这并不像你想象的那样减慢速度。 MATLAB 就是为此而生的。我已经使用 MATLAB 几十年了,但这对我来说仍然很奇怪。
此方法可让您喜欢 LUT 创建(日志、exp 等),并且运行速度仍然非常快。
在您的情况下,您的 LUT 仅需要 4096 个元素,因为您的输入数据只有 12 位。您可能需要小心边界,因为 uint16 可能具有更高的值。一种简洁的绑定(bind)方法是使用 min
和 end
函数:
convertedimage = lut(min(double(someimage)+1, end));
现在,这已经实现了您的功能,但也许您想要一个稍微不同的功能。例如,这种类型的常见功能是简单的 Gamma 调整。 Gamma 值为 2.2 意味着输入图像值将按 1/2.2 次方缩放(如果在 0 和 1 之间缩放)。我们可以按如下方式创建这样的 LUT:
lutgamma = uint8(256.*(((0:4095)./4095).^(1/2.2)));
plot(lutgamma);
我们再次通过简单的索引应用 LUT:
convertedimage = lutgamma(min(double(someimage)+1, end));
我们得到以下图像:
使用平滑的 LUT 通常会提高整体图像质量。分段线性 LUT 往往会导致生成的图像在阴影区域出现奇怪的不连续性。
这些在许多成像系统中非常常见,因此 LUT 具有文件格式。要明白我的意思,请看这个 LUT generator来自一家大型相机公司。 LUT 很重要,看起来您的方向是正确的。
关于image - 如何改变RGB图像的动态范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29979689/