关于c#:科学色谱图的图像分析

Image analysis on scientific chromatograms

我正在寻找一种从色谱图中提取信息的方法。色谱图如下:

Chromatogram

我不太喜欢图像处理/分析,所以我正在寻找一种工具/算法,从这些色谱图中提取峰的长度(如果可能的话,还可以提取峰下的表面)。解决方案可以是用python或c_。

事先谢谢。


我已经编写了一些快速的python代码,可以从图像文件中提取色谱图(或任何单值)数据。

其要求如下:

  • 图像是干净的(没有文本或其他数据)。
  • 曲线是单值的,即曲线像素宽度为1(如果没有这个,它仍然可以工作,但它总是取上面的值)。
  • 刻度是线性的。
  • 小精灵

    它非常简单,只需遍历图像的每一列,并将第一个黑色值作为数据点。它使用PIL。这些数据点最初位于image坐标系统中,因此需要重新调整到数据坐标系统,如果所有图像共享同一个轴,则这是直接向前的,否则需要根据每个图像手动进行(更涉及自动化)。

    下图显示了我从何处提取图像(我删除了文本)进行处理(非粉色区域),因此为了重新缩放,我们只需要在数据坐标系统中使用白框区域:x_range = 4.4 - 0.55x_offset = 0.55y_range = 23000 - 2500y_offset = 2500

    enter image description here

    下面是用pyplot复制的提取数据:氧化镁

    代码如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    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数组,就可以使用许多选项来查找峰值及其下的相应区域(有关某些方法,请参见本讨论)。噪声是一个很大的问题,所以一般的方法是将数据卷积以平滑噪声(或者,如果峰值很尖锐,您可以阈值),然后进行区分以找到峰值。要查找峰下的区域,可以跨峰区域进行数值积分。

    我做了一些假设并编写了一些简单的代码(如下),以说明一种可能的方法。我已经对数据进行了阈值处理,所以只有5000以上的峰存活下来,然后我们迭代数据,找到峰,并使用梯形法则,np.trapz,找到每个峰下的面积。在峰重叠的地方,区域在重叠点被分开(我怀疑这是标准的)。此外,此代码将只识别局部最大值的峰值(不会检测到肩部)。我已经绘制了结果图表,在相应的峰值位置为每个峰值写入了面积值:氧化镁

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    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()

    无论您在这一点上采取什么方法,都需要对您的数据进行假设(我并不是真的能够做到这一点)。尽管我在上面做了一些!),如何处理重叠的峰值?等。。我相信色谱法中有标准方法,所以你真的需要先检查一下。希望这有帮助!


    当我使用此代码时,会得到以下图像

    氧化镁

    代码同上(稍作修改)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    from PIL 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 range(width):
            for y in range(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('C:\Python\HPLC.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()

    I am not quite sure what the problem might be.