如何将彩色映射图像反转为标量值

2024-05-09 06:13:51 发布

您现在位置:Python中文网/ 问答频道 /正文

如何反转彩色映射图像?在

我有一个二维图像在彩色地图上打印数据。我想读入图像并“反转”颜色贴图,也就是说,查找特定的RGB值,并将其转换为浮点值。在

例如: 使用此图像:http://matplotlib.sourceforge.net/_images/mri_demo.png

我应该能得到一个440x360的浮动矩阵,知道颜色图是厘米喷气式飞机在

from pylab import imread
import matplotlib.cm as cm
a=imread('mri_demo.png')
b=colormap2float(a,cm.jet) #<-tricky part

Tags: 数据图像importhttppngmatplotlib颜色demo
3条回答

也许有更好的方法来做这件事,我不确定。 如果您阅读help(cm.jet),您将看到用于将间隔[0,1]中的值映射到rgb3元组的算法。你可以用一点纸和铅笔,算出公式来反转定义映射的分段线性函数。在

然而,有许多问题使纸笔解决方案有些不吸引人:

  1. 这是一个很费劲的代数,而且 解决方案针对厘米喷气式飞机. 你得把这些工作再做一遍 如果你改变颜色贴图。如何自动解决这些代数方程是有趣的,但不是一个我知道如何解决的问题。

  2. 一般来说,颜色贴图可能不是 可逆(多个值可能 映射到相同的颜色)。在 案例厘米喷气式飞机,值在0.11之间 和0.125都映射到RGB 例如,三元组(0,0,1)。所以如果 你的图像包含纯蓝色 像素,真的没有办法 判断它是否来自0.11的值 或者一个0.125的值。

  3. 从[0,1]到 三元组是3空间中的曲线。这个 你形象中的颜色可能不会说谎 完全在这条曲线上。有可能 例如,舍入误差。因此,任何实际的解决方案都必须能够插值或以某种方式将3维空间中的点投影到曲线上。在

由于非唯一性问题和投影/插值问题,您提出的问题可能有许多可能的解决方案。以下只是一种可能性。在

以下是解决唯一性和投影/插值问题的一种方法:

创建一个gradient,它充当“代码本”。gradient是厘米喷气式飞机彩色地图。gradient的颜色对应于从0到1的值。使用scipy的矢量量化函数scipy.cluster.vq.vq来映射图像中的所有颜色,mri_演示.png,转换为gradient中最近的颜色。 由于颜色贴图可能对许多值使用相同的颜色,因此渐变可能包含重复的颜色。我把它留给scipy.cluster.vq.vq来决定哪个(可能)非唯一的代码本索引与特定的颜色相关联。在

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
import scipy.cluster.vq as scv

def colormap2arr(arr,cmap):    
    # http://stackoverflow.com/questions/3720840/how-to-reverse-color-map-image-to-scalar-values/3722674#3722674
    gradient=cmap(np.linspace(0.0,1.0,100))

    # Reshape arr to something like (240*240, 4), all the 4-tuples in a long list...
    arr2=arr.reshape((arr.shape[0]*arr.shape[1],arr.shape[2]))

    # Use vector quantization to shift the values in arr2 to the nearest point in
    # the code book (gradient).
    code,dist=scv.vq(arr2,gradient)

    # code is an array of length arr2 (240*240), holding the code book index for
    # each observation. (arr2 are the "observations".)
    # Scale the values so they are from 0 to 1.
    values=code.astype('float')/gradient.shape[0]

    # Reshape values back to (240,240)
    values=values.reshape(arr.shape[0],arr.shape[1])
    values=values[::-1]
    return values

arr=plt.imread('mri_demo.png')
values=colormap2arr(arr,cm.jet)    
# Proof that it works:
plt.imshow(values,interpolation='bilinear', cmap=cm.jet,
           origin='lower', extent=[-3,3,-3,3])
plt.show()

你看到的图像应该接近于核磁共振成像_演示.png公司名称:

alt text

(最初的核磁共振成像_演示.png有一个白色的边界。因为白色不是一种颜色厘米喷气式飞机,请注意,scipy.cluster.vq.vq将白色映射到gradient代码本中最近的点,这恰好是淡绿色。)

LinearSegmentedColormap不会提供相同的插值,如果我在测试期间不手动进行插值,那么我更喜欢使用我自己的:

作为一个优点,matplotlib并不需要,因为我将代码集成到现有软件中。在

def codeBook(color_list, N=256):
    """
    return N colors interpolated from rgb color list
    !!! workaround to matplotlib colormap to avoid dependency !!!
    """
    # seperate r g b channel
    rgb = np.array(color_list).T
    # normalize data points sets
    new_x = np.linspace(0., 1., N)
    x = np.linspace(0., 1., len(color_list))
    # interpolate each color channel
    rgb = [np.interp(new_x, x, channel) for channel in rgb]
    # round elements of the array to the nearest integer.
    return np.rint(np.column_stack( rgb )).astype('int')

你不知道

谢谢你的回复,我理解你解释的过程,并复制它。它工作得很好,我用它来反转温度网格中的红外相机镜头,因为使用GIMP可以很容易地对图片进行返工/重塑以实现我的目的。在

我能够从相机快照创建标量网格,这在我的任务中非常有用。在

我使用一个可以使用GIMP+Sample a Gradient Along a Path创建的调色板文件。 我选择我的原始图片的颜色条,将其转换为调色板,然后导出为十六进制颜色序列。 我阅读这个调色板文件来创建一个由温度样本规范化的colormap,用作代码手册。 我读取原始图像并使用矢量量化将颜色反转为值。 通过在temperature sample数组中使用codebook索引作为索引过滤器,我对代码的python风格进行了轻微改进,并应用了一些过滤器pass来平滑我的结果。在

from numpy import linspace, savetxt
from matplotlib.colors import Normalize, LinearSegmentedColormap
from  scipy.cluster.vq import vq

# sample the values to find from colorbar extremums
vmin = -20.
vmax = 120.
precision = 1.

resolution = 1 + vmax-vmin/precision
sample = linspace(vmin,vmax,resolution)

# create code_book from sample
cmap = LinearSegmentedColormap.from_list('Custom', hex_color_list)
norm = Normalize()
code_book = cmap(norm(sample))

# quantize colors
indices = vq(flat_image,code_book)[0]
# filter sample from quantization results **(improved)**
values = sample[indices]

savetxt(image_file_name[:-3]+'.csv',values ,delimiter=',',fmt='%-8.1f')

结果最终以.csv格式导出

最重要的是创建一个具有良好代表性的调色板文件,以获得良好的精度。我开始获得一个良好的梯度(代码书)使用12种颜色和更多。 这一过程很有用,因为有时相机镜头无法轻松线性地转换为灰度。在

感谢所有贡献者unutbu,Rob A,scipy community;)

相关问题 更多 >