我如何量化空间模式之间的相似性

问题描述

问题表述

  • 假设我有几个 10000*10000 的网格(可以转换为 10000*10000 灰度图像。我认为 imagegrid 如下相同),并且在每个网格-重点是,有一些(在我的例子中,它是在该像素位置表达的特定基因的拷贝数,请注意,每个网格的位置都相同)。我想要的是量化这种类型的两个二维空间点模式之间的相似性(即两个不同基因的空间表达模式),并将所有基因对排序为“最相似”以“最不同”的方式。请注意,我关心的不是表达水平绝对值方面的空间模式,而是我关心的相对模式。因此,在比较相应的像素时,我可能需要利用一些相关性而不是距离度量。

  • 最简单的方法可能是直接将所有像素视为一个向量,并计算两个向量之间的一些相关度量。然而,这并没有考虑空间信息。我最感兴趣的那些基因具有空间模式,即聚类和自相关影响它们的表达模式(尽管它们的“簇”可能采用非常薄的形状而不是粘在一起,例如,特定于皮肤细胞的基因),这意味着通常图像会有几个峰值局部区域,而其他像素的表达水平会非常低(接近 0)。

可能的方向

  • 我不确定我是否应该 (1) 考虑应用图像处理中的图像相似性比较算法,这些算法将局部结构相似性考虑在内(例如,SSIM、SIFT,如Simple and fast method to compare images for similarity),或 (2) 考虑应用 空间相似性比较 GIS 空间统计中的算法(有一些关于此的论文,但我不确定是否有一些算法处理简单的点数据而不是具有形状的正常区域数据(以更 GIS 意义上的方式,我需要找到一种处理 栅格 数据而不是 多边形 数据的算法),或 (3) 考虑直接应用处理离散 2D 分布的统计方法,我认为这可能有点粗糙(似乎忽略了区域聚类/自相关效应,~Tobler 地理第一定律)。

  • 对于方向(1),我想了一个简单的方法,就是先分别在两张图片中找到一些“峰值”区域,将它们的并集作为ROIs,然后比较两者中的ROIs具体以简单的逐像素方式(将它们一起视为向量)的图像,但我不确定是否可以用相关度量替换距离度量,并且有点担心图像处理中的许多相似性比较方法当两个图像不同时,可能效果不佳。对于方向(2),我觉得这个方向可能更合适一些,因为这个问题确实和空间统计有关,但是我在GIS中还不知道从哪里开始。我猜方向(3)有点被(2)掩盖了,所以我可能不会在这里考虑。

示例

示例图像:(我自己的数据存在一些问题,因此我在这里借用了一张来自 SpatialLIBD http://research.libd.org/spatialLIBD/reference/sce_image_grid_gene.html 的图像)

Sample

假设每个像素的值在 0 到 10 之间离散值(如果需要,可以缩放到 [0,1])。左右子图中的组织形状略有不同,但在我的情况下它们完全相同。

PS:不过,关于空间统计一个可能很严重的问题。特定细胞类型的某些标记基因的表达可能不是聚集成块的,而是薄层或不规则的。例如,如果网格是大脑的一部分,那么皮质层特异性基因的高表达峰值区域(例如 V 层的 Ctip2)可能会在 10000*10000 网格中形成一个薄弧形弯曲层。>

更新:我发现了一种属于(3)方向的方法,称为“最优传输”问题,可能有用。看起来它把位置信息整合到分布的比较中。明天会尝试以这种方式进行测试(似乎是所有三个方向中最容易编码的方式?)。

任何想法将不胜感激!

解决方法

在没有任何示例图像的情况下,我假设您的问题类似于纹理模式识别。

我们可以从 Local Binary Patterns (2002) 或简称为 LBPs 开始。与基于灰度共生矩阵计算纹理全局表示的 previous (1973) 纹理特征不同,LBP 通过将每个像素与其周围像素邻域进行比较来计算纹理的局部表示。对于图像中的每个像素,我们选择围绕中心像素的大小为 r 的邻域(以处理可变的邻域大小)。然后为该中心像素计算 LBP 值,并将其存储在与输入图像具有相同宽度和高度的输出 2D 阵列中。然后您可以计算 LBP 代码的直方图(作为最终特征向量)并应用机器学习进行分类。

在 scikit-image 和 OpenCV 中都可以找到 LBP 实现,但后者的实现是严格在人脸识别的上下文中 - 底层 LBP 提取器未公开用于原始 LBP 直方图计算。 LBP 的 scikit-image 实现提供了对要生成的 LBP 直方图类型的更多控制。此外,scikit-image 实现还包括改进旋转和灰度不变性的 LBP 变体。

一些入门代码:

from skimage import feature
import numpy as np
from sklearn.svm import LinearSVC
from imutils import paths
import cv2
import os

class LocalBinaryPatterns:
    def __init__(self,numPoints,radius):
        # store the number of points and radius
        self.numPoints = numPoints
        self.radius = radius
    def describe(self,image,eps=1e-7):
        # compute the Local Binary Pattern representation
        # of the image,and then use the LBP representation
        # to build the histogram of patterns
        lbp = feature.local_binary_pattern(image,self.numPoints,self.radius,method="uniform")
        (hist,_) = np.histogram(lbp.ravel(),bins=np.arange(0,self.numPoints + 3),range=(0,self.numPoints + 2))
        # normalize the histogram
        hist = hist.astype("float")
        hist /= (hist.sum() + eps)
        # return the histogram of Local Binary Patterns
        return hist

# initialize the local binary patterns descriptor along with
# the data and label lists
desc = LocalBinaryPatterns(24,8)
data = []
labels = []

# loop over the training images
for imagePath in paths.list_images(args["training"]):
    # load the image,convert it to grayscale,and describe it
    image = cv2.imread(imagePath)
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    hist = desc.describe(gray)
    # extract the label from the image path,then update the
    # label and data lists
    labels.append(imagePath.split(os.path.sep)[-2])
    data.append(hist)

# train a Linear SVM on the data
model = LinearSVC(C=100.0,random_state=42)
model.fit(data,labels)

一旦我们的线性 SVM 被训练,我们就可以用它对后续的纹理图像进行分类:

# loop over the testing images
for imagePath in paths.list_images(args["testing"]):
    # load the image,describe it,# and classify it
    image = cv2.imread(imagePath)
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    hist = desc.describe(gray)
    prediction = model.predict(hist.reshape(1,-1))
    
    # display the image and the prediction
    cv2.putText(image,prediction[0],(10,30),cv2.FONT_HERSHEY_SIMPLEX,1.0,(0,255),3)
    cv2.imshow("Image",image)
    cv2.waitKey(0)

查看此出色的 tutorial 以了解更多详情。

Ravi Kumar (2016) 通过结合 LBP 和 Gabor 滤波器过滤 LBP 模式的系数,能够提取更精细纹理的图像