2013-01-04 131 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比我快(至少在這裏),但我的答案具有亞像素精度,而我提取藍色曲線的方式可能更容易理解。