2013-01-04 81 views
6

我有这样一个一堆图像:图像分析曲线拟合

enter image description here

相应的数据不可用。我需要在蓝色曲线上自动检索约100个点(常规x间隔)。所有的曲线都非常相似,所以我需要至少1个像素的精度,但是亚像素是首选。好消息是所有曲线从0,0开始并以1,1结束,所以我们可能会忘掉网格。

任何提示可以帮助或任何其他方法的Python库?谢谢 !

+0

有趣的问题,我正在研究一个解决方案,但亚像素精度不太可能。 –

+1

只有半自动但仍然相关的问题,这个网络应用程序可以做的奇迹:http://arohatgi.info/WebPlotDigitizer/ –

回答

6

我将您的图片保存到文件14154233_input.png。那么这个程序

import pylab as plt 
import numpy as np 

# Read image from disk and filter all grayscale 
im = plt.imread("14154233_input.png")[:,:,:3] 
im -= im.mean(axis=2).reshape(im.shape[0], im.shape[1], 1).repeat(3,axis=2) 
im_maxnorm = im.max(axis=2) 

# Find y-position of remaining line 
ypos = np.ones((im.shape[1])) * np.nan 
for i in range(im_maxnorm.shape[1]): 
    if im_maxnorm[:,i].max()<0.01: 
     continue 
    ypos[i] = np.argmax(im_maxnorm[:,i]) 

# Pick only values that are set 
ys = 1-ypos[np.isfinite(ypos)] 
# Normalize to 0,1 
ys -= ys.min() 
ys /= ys.max() 

# Create x values 
xs = np.linspace(0,1,ys.shape[0]) 

# Create plot of both 
# read and filtered image and 
# data extracted 
plt.figure(figsize=(4,8)) 
plt.subplot(211) 
plt.imshow(im_maxnorm) 
plt.subplot(212, aspect="equal") 
plt.plot(xs,ys) 
plt.show() 

产生以下情节:

Ausgabe

你可以接着用xs和任何你想要做ys。也许你应该把这个代码放在一个返回xs和ys左右的函数中。

可以通过在每列左右拟合gaussians来提高精度。如果你真的需要它,告诉我。

+0

我不实用pylab,我可以问你解释如何'im - = im.mean(axis = 2).reshape(im.shape [0],im.shape [1],1).repeat(3,axis = 2)'line works? –

+0

当然。 imread给了我们一个RGBA图像,也就是说,我们的数组有形状(x,y,4),我立即通过丢弃前一行中的alpha([:,:,3])来减少它。 然后我想用红色=绿色=蓝色(从黑色到白色的所有灰色)将所有颜色设置为黑色,以便只保留蓝色线条。 我通过从每个像素中减去R,G和B值的平均值来做到这一点。如果它们相等,则全部变为零。 '.mean(axis = 2)'计算平均值,制作一个二维数组; '.reshape()'再次使它成为3d,只需添加一个3. dim的len 1; '.repeat()'将数组的形状重置为'im'的形状 –

2

首先,经由

from scipy.misc import imread  
im = imread("thefile.png") 

这给出了与所述第三尺寸的颜色通道(RGB +阿尔法)一个3D numpy的阵列读出的图像。曲线在蓝色通道中,但网格也在那里。但在红色通道中,您拥有网格而不是曲线。所以我们使用

a = im[:,:,2] - im[:,:,0] 

现在,我们要沿每列的最大位置。具有一个像素精度,其由以下公式给出:

y0 = np.argmax(a, axis=0) 

当列中没有蓝色曲线时,即在帧外部时,结果为零。 On可以得到帧的限制

xmin, xmax = np.where(y0>0)[0][[0,-1] 

有了这个,您可以重新调整x轴。

然后,你想要亚像素分辨率。让我们专注于单一列

f=a[:,x] 

我们使用牛顿方法的单次迭代改进的极值位置

y1 = y0 - f'[y]/f''[y] 

请注意,我们不能再重复,因为谨慎的采样。但是,我们想要一个很好的衍生物近似值,所以我们将使用两点的5点方案。

coefprime = np.array([1,-8, 0, 8, -1], float) 
coefsec = np.array([-1, 16, -30, 16, -1], float) 
y1 = y0 - np.dot(f[y0-2:y0+3], coefprime)/np.dot(f[y0-2:y0+3], coefsec) 

P.S. :Thorsten Kranz比我快(至少在这里),但我的答案具有亚像素精度,而我提取蓝色曲线的方式可能更容易理解。