2014-05-22 3 views
2

XY 튜플을 RGB 튜플에 매핑하는 사전이 있습니다. 예를 들어, x, y -> r, g, b의 결과 인 히트 맵의 히트 맵을 표시합니다.

d = { 
    (0, 0): (0, 0, 0), 
    (0, 1): (0, 0, 200), 
    } 

나는 히트 맵의 어떤 종류, 플롯하고자하는,에서 주어진 XY 좌표, 그들의 상호 거리가 가중 DICT,의 색상의 평균은 색상이있을 것이다; 마치 그들이 "빛의 근원"인 것처럼.

주어진 예에서 좌표 (0, 0.5)(0, 0, 100)으로, 좌표 (0, 0.1)(0, 0, 20)으로 지정되어야합니다.

내 질문에 기술적 인 부분이 있습니다. 어떻게해야합니까? pyplotf(x, y) -> (r, g, b)에서 가져온 색상으로 픽셀 이미지를 그립니 까?

+2

먼저 벡터화 된 Numpy를 사용하여 배열을 생성하고 결과를'imshow'로 전달하는 데 문제가 있습니까? 이것은 함수와 사전을 취하기 위해'imshow'를 해킹하는 것보다 훨씬 간단합니다. 이론적으로 (대략) 동일한 수의 작업이 필요할 것입니다. – ebarr

답변

4

당신이 당신의 X-Y 그리드가있는 경우 :

import numpy 
from matplotlib import pyplot as plt 

width, height = 300, 500 

xs = numpy.arange(width) 
ys = numpy.arange(height) 
data = numpy.dstack(numpy.meshgrid(xs, ys)) 

을 당신은 (r, g, b) 튜플에이지도를해야한다. 다음은 꽤 느리지 만 속도를 높이는 방법은 함수가하는 일에 달려 있습니다. 당신이 당신이 말하는대로 점에서 보간 할 경우는 scipy.interpolate을 사용할 수 있습니다, 지금

plt.imshow(colors, origin='lower') 
plt.show() 

plt.show() result

:

from colorsys import hsv_to_rgb 

import random 
def data_to_color(x, y): 
    return (
     (x/width)**(0.5+random.random()*2), 
     (y/height)**3, 
     (x/width*y/height)*0.6 + random.random()*0.4 
    ) 

colors = [[data_to_color(x, y) for x, y in row] for row in data] 
colors = numpy.array(colors) 
colors.shape 
#>>> (500, 300, 3) 

그런 다음 imshow는 원하는 출력을 제공 할 수 있습니다.(가, 분리를 방지 할 수있을하지만 당신은 자신의 것을 테스트 할 수 있습니다)

from scipy.interpolate import griddata 

gridpoints = data.reshape(width*height, 2) 
d = {(x, y): data_to_color(x, y) for x, y in gridpoints if not random.randint(0, 1000)} 

len(d) 
#>>> 142 

numpy 배열로 사전을 추출하고, 색상을 분리 : 나는 위의 함수에서 추정 할 수있는 사전을 만들거야

points, values = zip(*d.items()) 

points = numpy.array(points) 
values = numpy.array(values) 

reds = values[:, 0] 
greens = values[:, 1] 
blues = values[:, 2] 

는 그런 점에서 griddata을 실행

new_reds = griddata(points, reds, (data[:, :, 0], data[:, :, 1]), method='linear') 
new_greens = griddata(points, greens, (data[:, :, 0], data[:, :, 1]), method='linear') 
new_blues = griddata(points, blues, (data[:, :, 0], data[:, :, 1]), method='linear') 

new_colors = numpy.dstack([new_reds, new_greens, new_blues]) 
new_colors[numpy.isnan(new_colors)] = 0.5 

그리고 음모 :

당신이 너무 추정을 원하는 경우
plt.triplot(points[:,0], points[:,1], 'k-', linewidth=1, alpha=0.5) 

plt.imshow(new_colors, extent=(0, width, 0, height), origin='lower') 
plt.show() 

plt.show() interpolated output

그리고는 마지막으로, 나는 몇 가지 코드 from here 복사 :

import scipy 

def extrapolate_nans(x, y, v): 
    ''' 
    Extrapolate the NaNs or masked values in a grid INPLACE using nearest 
    value. 

    .. warning:: Replaces the NaN or masked values of the original array! 

    Parameters: 

    * x, y : 1D arrays 
     Arrays with the x and y coordinates of the data points. 
    * v : 1D array 
     Array with the scalar value assigned to the data points. 

    Returns: 

    * v : 1D array 
     The array with NaNs or masked values extrapolated. 
    ''' 

    if numpy.ma.is_masked(v): 
     nans = v.mask 
    else: 
     nans = numpy.isnan(v) 
    notnans = numpy.logical_not(nans) 
    v[nans] = scipy.interpolate.griddata((x[notnans], y[notnans]), v[notnans], 
     (x[nans], y[nans]), method='nearest').ravel() 
    return v 

new_reds = extrapolate_nans(data[:, :, 0], data[:, :, 1], new_reds) 
new_greens = extrapolate_nans(data[:, :, 0], data[:, :, 1], new_greens) 
new_blues = extrapolate_nans(data[:, :, 0], data[:, :, 1], new_blues) 

new_colors = numpy.dstack([new_reds, new_greens, new_blues]) 

plt.imshow(new_colors, extent=(0, width, 0, height), origin='lower') 
plt.show() 

ply.show() extrapolated interpolated output


편집 : 어쩌면 뭔가 더 각 광원

import numpy 
from matplotlib import pyplot as plt 
from numpy.core.umath_tests import inner1d 

width, height = 300, 500 

xs, ys = numpy.mgrid[:width, :height] 
coordinates = numpy.dstack([xs, ys]) 

light_sources = { 
    (0, 0): (0, 0, 0), 
    (300, 0): (0, 0, 0), 
    (0, 0): (0, 0, 0), 
    (300, 500): (0, 0, 0), 
    (100, 0): (0, 0, 200), 
    (200, 150): (100, 70, 0), 
    (220, 400): (255, 255, 255), 
    (80, 220): (255, 0, 0), 
} 

weights = numpy.zeros([width, height]) 
values = numpy.zeros([width, height, 3]) 

같은

for coordinate, value in light_sources.items(): 

을 계산 (역변환)의 거리. 가중치에 의해

weights += inverse_distances 
    values += inverse_distances[:, :, numpy.newaxis].repeat(3, axis=-1) * value/255 

나누기 :

shifted_coordinates = coordinates - coordinate + 1e-9 
    inverse_distances = (shifted_coordinates ** 2).sum(axis=-1) ** (-1/2) 

이 합과 합의 가중에 추가 : 더 엄격한 수정 나중에 중요 할 것이다, 그래서이 바보 같은 실패를해야합니다 있지만, 무한대을 방지하기 위해 +1e9를 사용하여 평균해야합니다 :

values /= weights[..., numpy.newaxis] 

그리고 쇼를 ...

0 이를 위해 12,313,992,

:

plt.show() for light-source variant

귀하의 예제에서 (0, 0.1)의 값이 (0, 0, 20) 아니지만 때문에이 원래 들어주지 않은 이유는 : 그래서해야

distances = [0.9, 0.1] 
inverse_distances = [10/9, 10] 
sum_weighting = 100/9 
blue_levels = 200/(109/90) = 18 

이 정의에 따라 (0, 0, 18)이됩니다.

+0

이것은 좋은 대답이지만 임의의 수의 "밝은"소스로부터의 거리를 기반으로 가중치 RGB 색상 혼합을 수행하는 방법 인 질문의 어려운 부분을 다루지는 않습니다. – ebarr

+0

그것이 질문의 일부인지 머리말인지 확실하지 않습니다. 나는 그것에 대해 생각할 것이다. – Veedrac

+0

글쎄, 나는 그것을 쐈어. – Veedrac

관련 문제