2010-09-15 47 views
9

Làm cách nào để đảo ngược hình ảnh được ánh xạ màu?cách đảo ngược hình ảnh bản đồ màu thành giá trị vô hướng

Tôi có hình ảnh 2D vẽ dữ liệu trên bản đồ màu. Tôi muốn đọc hình ảnh trong và 'đảo ngược' bản đồ màu, nghĩa là tra cứu một giá trị RGB cụ thể và biến nó thành một phao.

Ví dụ: sử dụng hình ảnh này: http://matplotlib.sourceforge.net/_images/mri_demo.png

tôi sẽ có thể để có được một ma trận 440x360 phao, biết bản đồ màu được cm.jet

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

Trả lời

8

Có thể có những cách tốt hơn để làm điều này; Tôi không chắc. Nếu bạn đọc help(cm.jet), bạn sẽ thấy thuật toán được sử dụng để ánh xạ các giá trị trong khoảng [0,1] đến RGB 3-tuple. Bạn có thể, với một tờ giấy nhỏ và bút chì, làm việc ra công thức để đảo ngược các chức năng piecewise-tuyến tính mà xác định các bản đồ.

Tuy nhiên, có một số vấn đề mà làm cho giấy và bút chì giải pháp nào không hấp dẫn:

  1. Đó là rất nhiều đại số khó nhọc, và giải pháp cụ thể cho cm.jet. Bạn sẽ phải thực hiện lại tất cả công việc này nếu bạn thay đổi bản đồ màu. Làm thế nào để tự động hoá việc giải quyết các phương trình đại số là thú vị, nhưng không phải là một vấn đề tôi biết làm thế nào để giải quyết.

  2. Nói chung, bản đồ màu có thể không được không thể đảo ngược (nhiều giá trị có thể được ánh xạ tới cùng một màu). Trong trường hợp của cm.jet, các giá trị giữa 0,11 và 0,125 đều được ánh xạ tới RGB 3-tuple (0,0,1) chẳng hạn. Vì vậy, nếu hình ảnh của bạn chứa một màu xanh lam pixel, thực sự không có cách nào để cho biết liệu hình ảnh đó có đến giá trị 0,11 hoặc giá trị là 0,125 hay không.

  3. Ánh xạ từ [0,1] đến 3-tuple là đường cong trong không gian 3 chiều. Các màu trong hình ảnh của bạn có thể không nằm ở hoàn hảo trên đường cong này. Ví dụ: có thể có là lỗi làm tròn. Vì vậy, bất kỳ giải pháp thực tế nào để có thể nội suy hoặc bằng cách nào đó dự án điểm trong không gian 3 vào đường cong.

Do vấn đề không phải là duy nhất và vấn đề về phép chiếu/nội suy, có thể có nhiều giải pháp khả thi cho vấn đề bạn đặt ra. Dưới đây chỉ là một khả năng.

Dưới đây là một cách để giải quyết vấn đề độc đáo và chiếu/nội suy:

Tạo một gradient đóng vai trò như một "cuốn sách mã". gradient là một mảng RGBA 4-tuples trong bản đồ màu cm.jet. Các màu của gradient tương ứng với các giá trị từ 0 đến 1. Sử dụng chức năng lượng tử vector của scipy scipy.cluster.vq.vq để ánh xạ tất cả các màu trong hình ảnh của bạn, mri_demo.png, lên màu gần nhất trong gradient. Vì bản đồ màu có thể sử dụng cùng một màu cho nhiều giá trị, độ dốc có thể chứa màu trùng lặp. Tôi để nó lên đến scipy.cluster.vq.vq để quyết định (có thể) chỉ mục mã sách không duy nhất nào liên kết với một màu cụ thể.

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() 

Hình ảnh mà bạn nhìn thấy nên được gần gũi với tái tạo mri_demo.png:

alt text

(Các mri_demo.png ban đầu có đường viền màu trắng Kể từ trắng không phải là một màu trong cm.jet. , lưu ý rằng scipy.cluster.vq.vq đồ trắng để đến thời điểm gần nhất trong cuốn sách gradient mã, mà sẽ xảy ra là một màu xanh nhạt.)

+0

vâng, đây thực chất là điều tôi nghĩ là có thể. Giải pháp ban đầu của bạn bao gồm đọc một dòng từ một hình ảnh với cùng một bản đồ màu, điều này có thể hữu ích cho những người nói, quét một hình trong và muốn thực hiện phân tích số riêng của họ. Tôi đã gặp khó khăn trong việc lượng tử hóa vector - ban đầu, có vẻ như đặt cược tốt nhất là chu kỳ qua từng màu có thể trong lut và tính khoảng cách 3d từ giá trị pixel thực tế - mà tôi không thể biết cách làm nhanh vòng lặp. Cảm ơn! – user448764

0

Hy unutbu,

012.

Cảm ơn bạn đã trả lời, tôi hiểu quy trình bạn giải thích và tái tạo nó. Nó hoạt động rất tốt, tôi sử dụng nó để đảo ngược các bức ảnh chụp IR ở các lưới nhiệt độ, vì một bức ảnh có thể dễ dàng làm lại/định hình lại để hoàn thành mục đích của tôi bằng cách sử dụng GIMP.

Tôi có thể tạo lưới vô hướng từ các ảnh chụp thực sự hữu ích trong công việc của mình.

Tôi sử dụng tệp bảng màu mà tôi có thể tạo bằng GIMP + Sample a Gradient Along a Path. Tôi chọn thanh màu của ảnh gốc, chuyển đổi nó thành bảng màu rồi xuất dưới dạng chuỗi màu hex. Tôi đọc tệp bảng màu này để tạo bản đồ màu chuẩn hóa bằng mẫu nhiệt độ được sử dụng làm sách mã. Tôi đọc hình ảnh gốc và sử dụng lượng tử hóa vector để đảo màu thành giá trị. I cải thiện chút ít kiểu mã pythonic của mã bằng cách sử dụng chỉ mục mã như bộ lọc chỉ mục trong mảng mẫu nhiệt độ và áp dụng một số bộ lọc để làm mịn kết quả của tôi.

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') 

Kết quả cuối cùng được xuất khẩu trong .csv

điều quan trọng nhất là để tạo ra một tập tin Palette Well đại diện để có được một độ chính xác tốt. Tôi bắt đầu có được một gradient tốt (cuốn sách mã) sử dụng 12 màu sắc và nhiều hơn nữa. Quá trình này rất hữu ích vì đôi khi ảnh chụp không thể được dịch sang thang màu xám một cách dễ dàng và tuyến tính.

Nhờ tất cả những người đóng góp unutbu, Rob A, cộng đồng scipy;)

0

Các LinearSegmentedColormap không cung cấp cho tôi những suy cùng nếu tôi không làm nó bằng tay trong thử nghiệm của tôi, vì vậy tôi thích sử dụng của riêng tôi:

Là một lợi thế, matplotlib không cần thiết vì tôi tích hợp mã của tôi trong phần mềm hiện có.

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') 
Các vấn đề liên quan