2015-04-23 2 views
1

Я заинтересован в поиске быстрого метода поиска линейно интерполированных цветов из определенной таблицы поиска. Цель, если назначить цвета большому количеству элементов во время выполнения на основе данной цветовой карты. Таблица поиска цветовой карты представляет собой список кортежей, который содержит значения (по возрастанию), красный, зеленый, синий, непрозрачностьЭффективный поиск цветов с линейной интерполяцией в Python

Ниже представлен простой рецепт со стандартным питоном. Я также мог использовать панды, поскольку я использую это для чего-то еще.

# Interpolate colors from a lookup table 
import bisect 

def find_color(x, vlist, lut): 
    """Finds linearly interpolated color from specified lut and x 
     Returns RGBA tuple 
     Parameters 
     x: value to lookup 
     vlist: list of values in lut 
     lut: List of tuples Value, R, G, B, A 
    """ 
    last = len(lut) - 1 # last index for lut 

    if x <= vlist[0] : #clamp low end 
      return lut[0][1], lut[0][2], lut[0][3], lut[0][4] 
    elif x >= vlist[last]: #clamp high end 
      return lut[last][1], lut[last][2], lut[last][3], lut[last][4] 
    else: 
      # since vlist is sorted we can use bisect 
      hi = bisect.bisect_left(vlist, x) #hi index 
      lo = hi - 1 # lo index 

      # interpolation weight from left 
      w = (x - vlist[lo])/(vlist[hi] -vlist[lo]) 
      #print x, lo, hi, w 

      # use w to interpolate r,g,b,a from lo and hi bins 
      # interpolated_value = low_value + w * bin_size 
      r = lut[lo][1] + w * (lut[hi][1] - lut[lo][1]) 
      g = lut[lo][2] + w * (lut[hi][2] - lut[lo][2]) 
      b = lut[lo][3] + w * (lut[hi][3] - lut[lo][3]) 
      a = lut[lo][4] + w * (lut[hi][4] - lut[lo][4]) 
      return int(r), int(g), int(b), int(a) 


# Color lookup table 
lut = [ (0.0, 255, 0, 0, 64), 
    (0.5, 0, 255, 255,128), 
    (1.0, 0, 0, 255, 255) ] 

# Value list - extract first column from lut 
vlist = [ x[0] for x in lut] 

# Test find_color() for arbitrary value 
for i in xrange(-5, 12): 
    x = i/10.0 
    print find_color(x, vlist, lut) 
+0

Существует множество эффективных способов поиска вещей в пандах, просто найдите pandas для «поиска» здесь, и вы найдете много. Я задал вопрос о n-мерном поиске, который получил хороший ответ и может быть похож на то, что вы пытаетесь сделать: http://stackoverflow.com/questions/25772977/n-dimensional-table-lookup-array-dataframe -or-dictionary – JohnE

+0

Я делал поиск перед публикацией, но результаты, с которыми я столкнулся, были не для поиска с интерполяцией. Мне нужно сделать это несколько раз для 1000 значений, таким образом, потребность в эффективности. Также я не использую ухабистую, но спасибо за ваши мысли. – user3043805

+0

Вы вроде используете numpy, если используете панды, поскольку панды построены поверх numpy ;-) Кроме того, вы отметили эффективность, а numpy будет намного эффективнее стандартного python списки. Что касается поиска + интерполяции, я не думаю, что вы найдете эту комбо, но, похоже, ваша проблема может быть подобрана в два этапа: 1. поиск, 2. интерполяция. FWIW. – JohnE

ответ

0

Если вы можете предварительно обработать вашу таблицу поиска раньше времени, вы можете заменить бинарный поиск + интерполяция с помощью простого поиска. Это до тех пор, пока вы согласны с возможностью получения неточно точного вывода, что должно быть в случае цветов - отключить на одну ошибку, очень трудно обнаружить.

Возьмите значение и умножьте его на некоторую константу, затем преобразуйте в целое число и используйте это целое число как индекс в список.

resolution = 1024 
multiplier = float(resolution)/(lut[-1][0] - lut[0][0]) 
lookup = [(0, 0, 0, 0)] * resolution 
for index in range(resolution): 
    r, g, b, a = find_color(lut[0][0] + i/multiplier, vlist, lut) 
    lookup[index] = (r, g, b, a) 

def find_color2(x): 
    return lookup[int((x - lut[0][0]) * multiplier)] 
+0

Мое впечатление, что это не будет работать предсказуемо, если я не решит проблему значительно, так как мои данные - плавающие данные с двойной точностью. Спасибо за идею, хотя – user3043805

+0

@ user3043805 идти вперед и вверх по разрешению, тогда память дешевая. Точность значений не имеет значения почти столько же, сколько расстояние между ними, если у вас есть два очень близких друг друга, вам нужно высокое разрешение, но если они все разбросаны, вы можете использовать меньше. Попробуйте проверить его и посмотреть. –

Смежные вопросы