Эти полосы спектра раньше судили на глаз, как это сделать программно?

введите описание изображения здесь

Операторы, используемые для проверки спектра, зная местоположение и ширину каждого пика и оценивая участок, к которому принадлежит спектр. По-новому, изображение захватывается камерой на экран. И ширина каждой полосы должна быть рассчитана программно.

Старая система: спектроскоп -> человеческий глаз Новая система: спектроскоп -> камера -> Программа

Что является хорошим методом для вычисления ширины каждой полосы , учитывая их приблизительное положение по оси X; учитывая, что эта задача раньше выполнялась на глаз, а теперь должна выполняться программой?

Извините, если мне не хватает деталей, но их мало.


Список программ, сгенерировавших предыдущий график; Надеюсь это актуально:

import Image
from scipy import *
from scipy.optimize import leastsq

# Load the picture with PIL, process if needed
pic         = asarray(Image.open("spectrum.jpg"))

# Average the pixel values along vertical axis
pic_avg     = pic.mean(axis=2)
projection  = pic_avg.sum(axis=0)

# Set the min value to zero for a nice fit
projection /= projection.mean()
projection -= projection.min()

#print projection

# Fit function, two gaussians, adjust as needed
def fitfunc(p,x):
    return p[0]*exp(-(x-p[1])**2/(2.0*p[2]**2)) + \
        p[3]*exp(-(x-p[4])**2/(2.0*p[5]**2))
errfunc = lambda p, x, y: fitfunc(p,x)-y

# Use scipy to fit, p0 is inital guess
p0 = array([0,20,1,0,75,10])
X  = xrange(len(projection))
p1, success = leastsq(errfunc, p0, args=(X,projection))
Y = fitfunc(p1,X)

# Output the result
print "Mean values at: ", p1[1], p1[4]

# Plot the result
from pylab import *
#subplot(211)
#imshow(pic)
#subplot(223)
#plot(projection)
#subplot(224)
#plot(X,Y,'r',lw=5)
#show()

subplot(311)
imshow(pic)
subplot(312)
plot(projection)
subplot(313)
plot(X,Y,'r',lw=5)
show()
7 голосов | спросил Jesvin Jose 26 Mayam12 2012, 11:50:06

3 ответа


0

Учитывая приблизительную начальную точку, вы можете использовать простой алгоритм, который находит локальные максимумы, наиболее близкие к этой точке. Ваш подходящий код уже может это сделать (я не был уверен, успешно ли вы его использовали).

Вот некоторый код, который демонстрирует простое обнаружение пиков из заданной пользователем начальной точки:

#!/usr/bin/env python
from __future__ import division
import numpy as np
from matplotlib import pyplot as plt

# Sample data with two peaks: small one at t=0.4, large one at t=0.8
ts = np.arange(0, 1, 0.01)
xs = np.exp(-((ts-0.4)/0.1)**2) + 2*np.exp(-((ts-0.8)/0.1)**2)

# Say we have an approximate starting point of 0.35
start_point = 0.35

# Nearest index in "ts" to this starting point is...
start_index = np.argmin(np.abs(ts - start_point))

# Find the local maxima in our data by looking for a sign change in
# the first difference
# From http://stackoverflow.com/a/9667121/188535
maxes = (np.diff(np.sign(np.diff(xs))) < 0).nonzero()[0] + 1

# Find which of these peaks is closest to our starting point
index_of_peak = maxes[np.argmin(np.abs(maxes - start_index))]

print "Peak centre at: %.3f" % ts[index_of_peak]

# Quick plot showing the results: blue line is data, green dot is
# starting point, red dot is peak location
plt.plot(ts, xs, '-b')
plt.plot(ts[start_index], xs[start_index], 'og')
plt.plot(ts[index_of_peak], xs[index_of_peak], 'or')
plt.show()

Этот метод будет работать только в том случае, если подъем по пику идеально плавный от вашей начальной точки. Если это должно быть более устойчивым к шуму, я не использовал его, но PyDSTool похоже, это может помочь. В этом сообщении SciPy подробно описано, как использовать его для обнаружения 1D пики в шумном наборе данных.

Итак, предположим, что в этот момент вы нашли центр пика. Теперь по ширине: есть несколько методов, которые вы можете использовать, но самый простой - это, вероятно, «полная ширина на половине максимума» (FWHM). Опять же, это просто и потому хрупко. Это сломается для близких двойных пиков или для шумных данных.

FWHM - именно то, что следует из его названия: вы найдете ширину пика, где он находится на полпути к максимуму. Вот некоторый код, который делает это (он просто продолжается сверху):

# FWHM...
half_max = xs[index_of_peak]/2

# This finds where in the data we cross over the halfway point to our peak. Note
# that this is global, so we need an extra step to refine these results to find
# the closest crossovers to our peak.

# Same sign-change-in-first-diff technique as above
hm_left_indices = (np.diff(np.sign(np.diff(np.abs(xs[:index_of_peak] - half_max)))) > 0).nonzero()[0] + 1
# Add "index_of_peak" to result because we cut off the left side of the data!
hm_right_indices = (np.diff(np.sign(np.diff(np.abs(xs[index_of_peak:] - half_max)))) > 0).nonzero()[0] + 1 + index_of_peak

# Find closest half-max index to peak
hm_left_index = hm_left_indices[np.argmin(np.abs(hm_left_indices - index_of_peak))]
hm_right_index = hm_right_indices[np.argmin(np.abs(hm_right_indices - index_of_peak))]

# And the width is...    
fwhm = ts[hm_right_index] - ts[hm_left_index]

print "Width: %.3f" % fwhm

# Plot to illustrate FWHM: blue line is data, red circle is peak, red line
# shows FWHM
plt.plot(ts, xs, '-b')
plt.plot(ts[index_of_peak], xs[index_of_peak], 'or')
plt.plot(
    [ts[hm_left_index], ts[hm_right_index]],
    [xs[hm_left_index], xs[hm_right_index]], '-r')
plt.show()

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

Более надежным способом может быть подгонка гауссовой кривой (или вашей собственной модели) к подмножеству данных, центрированных вокруг пика - скажем, от локальных минимумов с одной стороны до локальных минимумов с другой - и использование один из параметров этой кривой (например, сигма) для расчета ширины.

Я понимаю, что это много кода, но я сознательно избегал выделять функции поиска индексов, чтобы "показать мою работу" немного больше, и, конечно, функции построения графиков предназначены только для демонстрации.

Надеюсь, это даст вам хотя бы хорошую отправную точку для того, чтобы придумать что-то более подходящее для вашего конкретного набора.

ответил detly 26 Maypm12 2012, 13:09:36
0

Поздно на вечеринку, но для любого, кто столкнется с этим вопросом в будущем ...

Данные о движении глаз выглядят очень похоже на это; Я бы основывал подход, который использовался в Nystrom + Holmqvist, 2010 , Сглаживание данных с использованием фильтра Савицкого-Голея (scipy.signal.savgol_filter в scipy v0.14 +), чтобы избавиться от некоторых шумов низкого уровня при сохранении больших пиков нетронутыми - авторы рекомендуют использовать порядок 2 и размер окна примерно в два раза больше ширины наименьшего пика, который вы хотите обнаружить. Вы можете узнать, где находятся полосы, произвольно удалив все значения выше определенного значения y (установите для них значение numpy.nan). Затем возьмите (nan) среднее и (nan) стандартное отклонение от остатка и удалите все значения, превышающие среднее значение + [параметр] * std (я думаю, что они используют 6 в статье). Повторяйте до тех пор, пока вы не удалите какие-либо точки данных - но в зависимости от ваших данных некоторые значения [параметра] могут не стабилизироваться. Затем используйте numpy.isnan(), чтобы найти события против не-событий, и numpy.diff(), чтобы найти начало и конец каждого события (значения -1 и 1 соответственно). Чтобы получить еще более точные начальную и конечную точки, вы можете сканировать данные в обратном направлении от каждого начала и вперед от каждого конца, чтобы найти ближайший локальный минимум, значение которого меньше среднего + [другой параметр] * std (я думаю, они используют 3 в газете). Тогда вам просто нужно посчитать точки данных между каждым началом и концом.

Это не сработает для этого двойного пика; вам придется сделать некоторую экстраполяцию для этого.

ответил Tunisia 14 52014vEurope/Moscow11bEurope/MoscowFri, 14 Nov 2014 03:46:39 +0300 2014, 03:46:39
0

Наилучшим методом может быть статистическое сравнение группы методов с результатами, полученными человеком.

Вы бы взяли большое разнообразие данных и большое разнообразие оценок измерений (ширины при различных порогах, площадь выше различных порогов, разные методы выбора порогов, 2-е моменты, подборы полиномиальных кривых различной степени, сопоставление с образцом и т. д.) и сравните эти оценки с человеческими измерениями того же набора данных. Выберите метод оценки, который лучше всего соотносится с результатами эксперта. Или, может быть, выбрать несколько методов, лучший для каждого из различных высот, для различного отделения от других пиков и т. Д.

ответил hotpaw2 27 Mayam12 2012, 01:19:57

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132