Сопоставить трехмерный вектор в массиве 4D путем интерполяции?
Итак... Я пробовал что-то новое ради обучения. Я пытаюсь получить длину волны от sRGB. У меня есть все преобразования sRGB в XYZ и таблица преобразования из XYZ в длину волны - 4-мерная.
Моя проблема остается в последней строке - которая кажется самой сложной, по крайней мере для того, кто я не математик: мне нужно найти ближайшую позицию XYZ в преобразовании таблицы, повторяющую запрошенный XYZ.
Стол выглядит так:
WL,X,Y,Z
380,0.0014,0.0000,0.0065
381,0.0015,0.0000,0.0070
382,0.0016,0.0000,0.0077
383,0.0018,0.0001,0.0085
384,0.0020,0.0001,0.0094
385,0.0022,0.0001,0.0105
386,0.0025,0.0001,0.0120
...,...,...
780,0.0000,0.0000,0.0000
Я использую этот класс, хранящий разные процессы - это будет разделено:
#*************
class Sounder:
#*************
# -----------------
def __init__(self):
# -----------------
self.cursor = -1
self.__wavelengthTable = []
with open(CONVERTER_PATH, 'r') as csvfile:
dictReader = csv.DictReader(csvfile)
for row in dictReader:
self.__wavelengthTable.append(row)
csvfile.close()
self.table = {
'X': [],
'Y': [],
'Z': [],
'WL': []
}
for row in self.__wavelengthTable:
self.table['X'].append(row['X'])
self.table['Y'].append(row['Y'])
self.table['Z'].append(row['Z'])
self.table['WL'].append(row['WL'])
Первым делом я попробовал перебрать таблицу 4D по ее 3 координатам XYZ:
# -------------------------------------
def cursorIterateMatch(self, XYZArray):
# -------------------------------------
x = float(round(XYZArray[0], 4))
y = float(round(XYZArray[1], 4))
z = float(round(XYZArray[2], 4))
# print("[{}:{}:{}]".format(x,y,z))
found = False
while found == False:
if self.cursor >= self.get_tableLength():
break
found = self.cursorMatchAt(x, 'X')
if found != False:
print("x:{}".format(x))
found = self.cursorMatchAt(y, 'Y')
if found != False:
print("y:{}".format(y))
found = self.cursorMatchAt(z, 'Z')
if found != False:
print("z:{}".format(z))
self.cursorReset
return found
# print(found)
found = False
self.cursorReset()
return found
# -----------------------------------------
def cursorMatchAt(self, matchValue, label):
# -----------------------------------------
while matchValue != self.get_cursorAt(label):
self.cursor += 1
if self.cursor > self.get_tableLength():
return False
return self.get_cursorAt(label)
# ----------------------------
def get_cursorAt(self, label):
# ----------------------------
return self.get_tableAt(self.cursor, label)
# ------------------------------------
def get_tableAt(self, rowIdx, label):
# ------------------------------------
if rowIdx >= self.get_tableLength():
return False
return self.__wavelengthTable[rowIdx][label.upper()]
Очевидно, это не сработало, потому что XYZ, который я получаю, никогда не совпадает с позицией.
Итак, я начал проверять функции ближайшего положения и попробовал это:
# -----------------------------
def aproxMatch(self, XYZArray):
# -----------------------------
x = float(round(XYZArray[0], 4))
y = float(round(XYZArray[1], 4))
z = float(round(XYZArray[2], 4))
# print("[{}:{}:{}]".format(x,y,z))
xfound = self.findNearestAt(x, 'X')
yfound = self.findNearestAt(y, 'Y')
zfound = self.findNearestAt(z, 'Z')
print("[{}:{}:{}]".format(xfound,yfound,zfound))
mx = max([xfound, yfound, zfound])
mn = min([xfound, yfound, zfound])
diff = mx - mn
if diff > 5:
return False
return (xfound + yfound + zfound)/3
# -----------------------------------------
def findNearestAt(self, matchValue, label):
# -----------------------------------------
array = np.asarray(self.table[label])
idx = (np.abs(array - matchValue)).argmin()
return idx
Но очевидно, что это не работает, поскольку это все еще слишком строго. Затем я попробовал на стороне интерполяции вещей, и я должен сказать... Я потерян.
Я получил глобальную концепцию интерполяции, но я не могу найти, как применить хороший тип интерполяции. Поэтому мне просто нужно, чтобы кто-то сказал мне, кого мне следует использовать для решения этой проблемы.
Я не спрашиваю о решении, мне просто нужен совет о том, где искать - поскольку интерполяция кажется совершенно новым пространством информации, которую я нашел для "искажения" объекта или для приблизительного определения промежуточных значений из пула. Но я не понимаю, как можно получить приблизительную позицию трехмерного вектора в 4-мерном массиве.
Итак, для возобновления: мне просто нужно направление в мире интерполяции, чтобы понять, как получить 4-е измерение в 4-мерном массиве с ближайшим совпадением из 3-го вектора.
1 ответ
Во-первых, для преобразования из RGB в WaveLength требуется шаг нормализации значения RGB до заданной интенсивности, а затем поиск нормализованного значения и ответ на пару значений длины волны и интенсивности.
То есть
( wavelength( norm(R, G, B) ), intensity(R, G, B) )
Это основано на том, что пропорционально аналогичные значения RGB должны отображаться на одну и ту же длину волны. Аналогичные значения имеют одинаковый цвет, но с разной интенсивностью.
Это говорит о том, что таблица длин волн также должна быть нормализована. И этот черный является частным случаем, когда длина волны не определена, а интенсивность равна нулю.
Во-вторых, не должен findNearestAt
сравнивать расстояния? Обратите внимание, что для сравнения можно использовать квадрат расстояния, который будет намного быстрее для сравнения.
В-третьих, если таблица длин волн нормализована, то все значения таблицы (и значение поиска) помещаются на поверхности трехмерной сферы. Поскольку табличные значения упорядочены (по длине волны), точки должны проходить по сфере упорядоченным образом, хотя, вероятно, не в виде простой линии. Такое упорядоченное размещение вполне возможно может быть использовано для создания функции быстрого поиска.