2012-04-28 22 views
1

我正在尋找一種將色譜圖中的信息從GC或HPLC中提取出來的方法。色譜圖如下所示:科學色譜圖上的圖像分析

Chromatogram

我不是真的到圖像處理/分析,所以我在尋找一種工具/ algorithim提取的(峯值如果可能的話和下表面)的長度來自這些色譜圖的峯。解決方案可以是Python或C#。

在此先感謝。

+0

色譜圖是否有數字和座標軸(如圖所示)?或者我們可以假設他們會乾淨?即。沒有文字或軸 – fraxel 2012-04-28 20:51:47

+0

我不確定您是否意識到您要查找的複雜性。你有什麼樣的文件格式?二進制 – joaquin 2012-04-28 21:04:38

+0

@fraxel,我們可以假設他們是乾淨的,或與框架。這在這個國家並不重要。 joaquin,不,我不知道複雜程度的水平,它是所有圖像格式(在這種情況下,所以.PNG) – wvd 2012-04-28 21:07:22

回答

3

我寫了一些快速的Python代碼,可以從圖像文件中提取色譜圖(或任何單值)數據。

它具有以下要求:

  • 圖片是乾淨的(沒有文本或其他數據)。
  • 曲線是單值的,即。曲線的像素寬度爲1(即使沒有這個,它仍然會工作,但它總是會取上面的值)。
  • 比例是線性的。

這很簡單,只是遍歷圖像的每一列,並將第一個黑色值作爲數據點。它使用PIL。這些數據點最初在image座標系統中,因此如果所有圖像共享同一個座標軸,則需要重新縮放到數據座標系統,這很簡單,否則需要手動進行圖像基礎(自動化將更多地涉及)。

下面的圖片顯示了我在哪裏提取圖像(我刪除了文本)進行處理(非粉色區域),因此爲了重新縮放,我們只需要在數據座標系統中使用白色框區域:x_range = 4.4 - 0.55x_offset = 0.55y_range = 23000 - 2500y_offset = 2500

enter image description here

這裏被重新繪製與pyplot提取的數據: enter image description here

下面是代碼:

import Image 
import numpy as np 

def get_data(im, x_range, x_offset, y_range, y_offset): 
    x_data = np.array([]) 
    y_data = np.array([]) 
    width, height = im.size 
    im = im.convert('1') 
    for x in xrange(width): 
     for y in xrange(height): 
      if im.getpixel((x, y)) == 0: 
       x_data = np.append(x_data, x) 
       y_data = np.append(y_data, height - y) 
       break 
    x_data = (x_data/width) * x_range + x_offset 
    y_data = (y_data/height) * y_range + y_offset 
    return x_data, y_data 

im = Image.open('clean_data_2.png') 
x_data, y_data = get_data(im,4.4-0.55,0.55,23000-2500,2500) 

from pylab import * 
plot(x_data, y_data) 
grid(True) 
savefig('new_data.png') 
show() 

一旦你有你的數據作爲numpy的陣列,也有很多選項,你可用於查找峯值及其下的相應區域(有關某些方法,請參閱this討論)。噪聲是一個很大的問題,所以一般的方法是將數據進行卷積以平滑噪聲(或者如果峯值很尖銳,可以進行閾值處理)然後區分以找到峯值。要找到峯下的區域,您可以對峯區進行數值積分。

我已經做了一些假設,並編寫了一些簡單的代碼(下面),以說明一種可能的方法。我已經對閾值數據進行了閾值處理,只有5000以上的峯值才能存活,然後我們遍歷數據找到峯值,並使用空速規則np.trapz找到每個峯值下的面積。當峯重疊時,區域在重疊點處分開(我懷疑這是標準..)。此外,該代碼將只識別局部最大值的峯值(肩膀不會被檢測到)。我繪製的結果,在相應的峯值位置寫每個峯的面積值: enter image description here

def find_peak(start, grad): 
    for index, gr in enumerate(grad[start:]): 
     if gr < 0: 
      return index + start 

def find_end(peak, grad): 
    for index, gr in enumerate(grad[peak:]): 
     if gr >= 0: 
      return index + peak + 1 

def find_peaks(grad): 
    peaks=[] 
    i = 0 
    while i < len(grad[:-1]): 
     if grad[i] > 0: 
      start = i 
      peak_index = find_peak(start, grad) 
      end = find_end(peak_index, grad) 
      area = np.trapz(y_data[start:end], x_data[start:end]) 
      peaks.append((x_data[peak_index], y_data[peak_index], area)) 
      i = end - 1 
     else: 
      i+=1 
    return peaks 

y_data = np.where(y_data > 5000, y_data, 0) 

grad = np.diff(y_data) 

peaks = find_peaks(grad) 

from pylab import * 
plot(x_data, y_data)  
for peak in peaks: 
    text(peak[0], 1.01*peak[1], '%d'%int(peak[2])) 
grid(True) 
show() 

你需要在這一點上無論方法需要有關數據的假設(這我不能在一個位置儘管我做了上面的一些!),你如何處理重疊峯?等等。我確信在色譜中有標準的方法,所以你真的需要先檢查一下。希望這可以幫助!

+0

看起來不錯!我相信我可以使用它並進一步專門化。關於數據;在使用該程序之前,數據將始終由人類驗證,因此處理諸如疊加峯值之類的事情對我來說不會成爲問題。非常感謝你的出色答案! – wvd 2012-05-02 14:16:13

+0

最後一個問題;有時峯值的高度印在峯頂(僅略高於上),例如: http://i49.tinypic.com/vi0hup.png - 你有一個建議的編程方法去除這個問題嗎?我不需要像這樣的完整示例,只需要一些我可以查看的地方或其他東西。 – wvd 2012-05-02 14:22:54

+0

@wvd - 謝謝:)。我不認爲這些數字可以代表峯的高度,因爲1.995比1.545小?你可能有點卡在這裏,因爲看起來峯值實際上是在圖像之外裁剪的,所以我們不知道它們的實際高度 - 無論我們有沒有這些信息 - 在這種情況下,我們需要根據那個峯值數據。還有更多的例子可以說明。值得打開另一個問題值得嗎? – fraxel 2012-05-02 15:46:03