Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 这些光谱带过去是用眼睛来判断的,如何通过编程来判断?_Python_Image Processing_Signal Processing - Fatal编程技术网

Python 这些光谱带过去是用眼睛来判断的,如何通过编程来判断?

Python 这些光谱带过去是用眼睛来判断的,如何通过编程来判断?,python,image-processing,signal-processing,Python,Image Processing,Signal Processing,操作员用于检查光谱,了解每个峰的位置和宽度,并判断光谱所属的部分。在新的方式中,图像被摄像机捕捉到屏幕上。每个频带的宽度必须通过编程计算 旧系统:分光镜->人眼 新系统:分光镜->摄像机->程序 考虑到每个波段的近似X轴位置,计算每个波段宽度的好方法是什么;考虑到这项任务过去是由眼睛完美完成的,现在必须由程序完成 对不起,如果我缺乏详细资料,但他们是稀缺的 生成上一个图形的程序列表;我希望它是相关的: import Image from scipy import * from scipy.op

操作员用于检查光谱,了解每个峰的位置和宽度,并判断光谱所属的部分。在新的方式中,图像被摄像机捕捉到屏幕上。每个频带的宽度必须通过编程计算

旧系统:分光镜->人眼 新系统:分光镜->摄像机->程序

考虑到每个波段的近似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()

给定一个近似的起点,您可以使用一个简单的算法来查找最接近该点的局部极大值。您的fitting代码可能已经在这样做了(我不确定您是否成功地使用了它)

下面的一些代码演示了从用户给定的起点进行简单的峰值查找:

#!/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()
它不必是最大值一半处的全宽-正如一位评论者所指出的,您可以尝试找出操作员的正常峰值检测阈值,并将其转化为流程这一步的算法

更稳健的方法可能是将高斯曲线(或您自己的模型)拟合到以峰值为中心的数据子集(例如,从一侧的局部极小值到另一侧的局部极小值),并使用该曲线的一个参数(例如sigma)来计算宽度

我意识到这是一大堆代码,但我故意避免分解索引查找函数来“显示我的工作”,当然,绘图函数只是为了演示


希望这至少能给你一个好的起点,让你想出更适合你的特定集合的方法。

最好的方法可能是将一系列方法与人类结果进行统计比较


您将获取大量不同的数据和大量不同的测量估计值(不同阈值的宽度、不同阈值上方的面积、不同的阈值选择方法、二阶矩、不同程度的多项式曲线拟合、模式匹配等),并将这些估计值与同一数据集的人类测量值进行比较。选择与专家人工结果最相关的评估方法。或者选择几种方法,对于不同的高度,对于与其他山峰的不同分离,最好的一种,等等。

晚会晚了,但是对于将来遇到这个问题的人

眼动数据与此非常相似;我会根据你所使用的方法。使用Savitsky-Golay过滤器(
scipy.signal.savgol_过滤器
scipy v0.14+)平滑数据,以消除一些低电平噪声,同时保持大峰值的完整性-作者建议使用2阶,窗口大小约为您想要检测的最小峰值宽度的两倍。通过任意删除某个y值以上的所有值(将其设置为
numpy.nan
),可以找到标注栏的位置。然后取余数的(nan)平均值和(nan)标准偏差,去除所有大于平均值+[参数]*std的值(我认为他们在本文中使用6)。迭代,直到您不删除任何数据点-但根据您的数据,[parameter]的某些值可能无法稳定。然后使用
numpy.isnan()
查找事件与非事件,并使用
numpy.diff()
查找每个事件的开始和结束(值分别为-1和1)。为了获得更准确的起点和终点,您可以从每个起点向后扫描数据,从每个终点向前扫描数据,以找到最近的局部最小值,其值小于mean+[另一个参数]*std(我认为他们在本文中使用了3)。然后,您只需要计算每个起点和终点之间的数据点


这对双峰不起作用;你必须对此进行一些推断。

找出人眼无法区分颜色和背景的阈值。它应该是相当恒定的。然后,对数据点设置阈值,使人眼可以“看到”阈值以上的数据点,然后对这些数据点进行聚类,并找出每个聚类的宽度。也许可以利用曲线的导数轻松找到峰值和斜率?带子的宽度不是很恒定吗?据我所知,振幅和位置是不同的。@Blender,你能详细说明你的观点吗?噪音地板是否相当平坦?你如何(通过眼睛)确定什么是峰值,什么太低?例如,大约660–670的光点是双倍的还是不被计算在内?740点怎么样?@detly,我并不完全了解情况,但山峰的位置事先就知道了。是的,我担心的是两个已知的峰是否彼此太近。如果“基”低于阈值(本例中为峰的0.5),是否可以包含一个例外的修改?@aitchnyu好吧,这里我有点过于简单化:我刚才说的是总高度的0.5,但半高宽最好测量为底部(或噪声地板)上方峰值高度的一半。因此,基数低于峰值的0.5是没有意义的。是的,我希望算法在遇到一个格式不正确的峰值时抛出一个异常:一个峰值不会单调下降到0.5峰值(参见我的图表中的doublet)。我只需要宽度,振幅可以根据仪器的特性改变。“噪音地板”应该是理想的静音,与黑色的强度相对应。@aitchnyu啊,我明白了。我没有时间自己做,但是你可以实现一些东西,看看在峰值范围内的第一个差异。这应该是严格的
# 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()