将灰度2D numpy数组转换为RGB图像 [英] Convert grayscale 2D numpy array to RGB image

查看:159
本文介绍了将灰度2D numpy数组转换为RGB图像的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个灰度的"TIF"图像,我将其读取为2D的numpy数组

我的2D阵列中的像素强度在17到317之间.

我有两个挑战

  1. 将此2D数组转换为RGB图像

  2. 将像素强度(在17到317之间)缩放为RGB值,并将灰度图像显示为RGB彩色图像

很遗憾,我无法使用Opencv和Matplotlib,因为我正在使用的最终产品不支持这些

解决方案

在我看来,您的问题涉及三个方面:

  • 创建颜色图或LUT 查找表"
  • 将像素缩放到标准范围
  • 将色彩映射表应用于没有 matplotlib 的图像.

因此,要创建一个颜色图,我们需要一个256个RGB值的列表,其中我们可以查找任何灰度值并找到我们想要显示的颜色.我知道您不能在生产中使用 matplotlib ,但是您可以在其他计算机上从那里获取一两个颜色映射并将其复制到生产计算机中.所以,让我们开始吧.我们将使用 viridis 颜色图:

 #!/usr/bin/env python3将numpy导入为np从matplotlib导入cm#从"viridis"获取256个条目.或任何其他Matplotlib颜色图colmap = cm.get_cmap('viridis',256)#制作一个256个RGB值的Numpy数组#每行对应一个灰度级别的RGB颜色np.savetxt('cmap.csv',(colmap.colors [...,0:3] * 255).astype(np.uint8),fmt ='%d',delimiter =',') 

如果我们查看该文件"cmap.csv" ,则该文件有256行,并且开始如下:

  68,1,8468,2,8568,3,8769,5,8869,6,9069,8,9170,9,92...... 

这意味着在灰度图像中我们看到 0 的任何地方,我们实际上都会对像素 rgb(68,1,86)进行着色.在灰度级中我们看到的任何 1 都映射到 rgb(68,2,85).大概您可以将该文件复制到生产机器上,并且可以选择 Matplotlib

如果在阅读后将灰度图像缩放到整个范围,请使用以下行:

  grey =(((grey.astype(float)-grey.min())* 255/(grey.max()-grey.min())).astype(np.uint8) 

您将获得:


如果要可视化颜色图,请更改上面的行,如下所示:

 灰色= np.array(Image.open('TdoGc.png').convert('L')) 

为此,它会生成一个渐变(斜坡)图像:

 灰色= np.repeat(np.arange(256,dtype = np.uint8).reshape(1,-1),100,轴= 0) 

然后您可以看到自己的颜色图:


一种快速的技巧,可以处理没有类变量枚举颜色的分段线性颜色图.因此,您可以像这样从 autumn 色图制作 cmap.csv 文件:

 将numpy导入为np从matplotlib导入cm#获取秋天"色彩图colmap = cm.get_cmap('秋天')#将256个RGB条目另存为CSV-每个灰度级0..255均保存一个np.savetxt('cmap.csv',np.array([colmap(i/255)[:3] for i in range(256)])* 255,fmt =%d",delimiter =',') 

I have a Grayscale 'TIF' image which I've read as a numpy array which is 2D

The pixel intensities ranging from 17 to 317 in my 2D array.

I have two challenges

  1. convert this 2D array into RGB image

  2. scale the pixel intensities (between 17 to 317) to RGB values and show the Gray scale image as RGB color image

I unfortunately cannot use Opencv and Matplotlib as the end product on which I am working does not support these

解决方案

It seems to me that there are 3 aspects to your question:

  • creating a colormap, or LUT "Lookup Table"
  • scaling your pixels to a standard range
  • applying a colormap to an image without matplotlib.

So, to create a colormap, we need a list of 256 RGB values in which we can lookup any greyscale value and find the colour we want to show it as. I understand you can't use matplotlib in production, but you can grab a colormap or two from there on some other machine and copy it to your production machine. So, let's do that. We'll take the viridis colormap:

#!/usr/bin/env python3

import numpy as np
from matplotlib import cm

# Get 256 entries from "viridis" or any other Matplotlib colormap
colmap = cm.get_cmap('viridis', 256)

# Make a Numpy array of the 256 RGB values
# Each line corresponds to an RGB colour for a greyscale level
np.savetxt('cmap.csv', (colmap.colors[...,0:3]*255).astype(np.uint8), fmt='%d', delimiter=',')

If we look at that file "cmap.csv", it has 256 lines and starts like this:

68,1,84
68,2,85
68,3,87
69,5,88
69,6,90
69,8,91
70,9,92
...
...

That means anywhere we see 0 in the greyscale image, we actually colour the pixel rgb(68,1,86). Anywhere we see 1 in the greyscale it maps to rgb(68,2,85). Presumably you can copy that file to your production machine and you can choose any one of Matplotlibs colormaps.


Regarding scaling, you have posted an 8-bit PNG image with a range of 0..117 rather than a 16-bit TIFF image with a range of 17..317, so that is not most helpful. Also, you have not said how you plan to read a TIFF on a system that doesn't have OpenCV or matplotlib, so I don't know whether you have PIL/Pillow or plan to use tifffile.

Instead then, I will create a dummy 32x32 image with a range of 17..317 like this:

grey = np.random.randint(17,318, (32,32))

That looks like this:

array([[244,  75, 237, ..., 154, 190,  70],
       [286, 247, 158, ..., 150, 267, 124],
       [170, 305, 237, ..., 126, 111, 236],
       ...,
       [163, 292, 184, ...,  24, 253, 177],
       [314,  34,  36, ...,  87, 316, 182],
       [258, 153, 278, ..., 189,  57, 196]])

If we now want to scale that from the range 17..317 into the range 0..255, we can use:

rescaled = ((grey.astype(float) - grey.min())*255/(grey.max() - grey.min())).astype(np.uint8)

which gives us this:

array([[192,  49, 187, ..., 116, 147,  45],
       [228, 195, 119, ..., 113, 212,  90],
       [130, 244, 187, ...,  92,  79, 186],
       ...,
       [124, 233, 141, ...,   5, 200, 136],
       [252,  14,  16, ...,  59, 254, 140],
       [204, 115, 221, ..., 146,  34, 152]], dtype=uint8) 


Looking up can be done by loading the CSV file containing our colourmap, and taking the corresponding elements from the colormap as indexed by your greyscale values in the range 0...255:

#!/usr/bin/env python3

import numpy as np
from PIL import Image

# Load image as greyscale and make into Numpy array
grey = np.array(Image.open('TdoGc.png').convert('L'))

# Load RGB LUT from CSV file
lut = np.loadtxt('cmap.csv', dtype=np.uint8, delimiter=',')

# Make output image, same height and width as grey image, but 3-channel RGB
result = np.zeros((*grey.shape,3), dtype=np.uint8)

# Take entries from RGB LUT according to greyscale values in image
np.take(lut, grey, axis=0, out=result)

# Save result
Image.fromarray(result).save('result.png')

If you scale your greyscale image to the full range after reading, using this line:

grey = ((grey.astype(float) - grey.min())*255/(grey.max() - grey.min())).astype(np.uint8)

You will get this:


If you want to visualise your colormap, change the line above that looks like this:

grey = np.array(Image.open('TdoGc.png').convert('L'))

into this so that it generates a gradient (ramp) image:

grey = np.repeat(np.arange(256,dtype=np.uint8).reshape(1,-1), 100, axis=0)

Then you can see your colourmap:


A quick hack to handle segmented linear colormaps that don't have a class variable enumerating the colours. So you can make the cmap.csv file from the autumn colourmap like this:

import numpy as np
from matplotlib import cm

# Get "autumn" colourmap
colmap = cm.get_cmap('autumn')

# Save 256 RGB entries as CSV - one for each of grey levels 0..255
np.savetxt('cmap.csv', np.array([colmap(i/255)[:3] for i in range(256)]) * 255, fmt="%d", delimiter=',')

这篇关于将灰度2D numpy数组转换为RGB图像的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆