在图像中查找对称区域/模式

信息处理 图像处理 互相关 图像配准
2022-01-14 04:32:39

我有一组代表人体背面平均曲率的图像。

我想要做的是“扫描”图像,寻找在图像的其他部分具有相似、反射“对应物”的点(很可能与中线对称,但不一定,因为可能存在畸形)。一些图像拼接技术使用它来“自动检测”图像之间的相似点,但我想在同一图像的两侧检测它们。

最终目标是找到一条连续的、很可能是弯曲的纵向线,将背部自适应地分成对称的“两半”。

下面放置了一个示例图像。请注意,并非所有区域都是对称的(具体而言,就在图像中心上方,红色垂直“条带”向右偏离)。该区域应该得到一个不好的分数,或者其他什么,但是局部对称性将由放置在更远的对称点来定义。无论如何,我必须使任何算法适应我的应用程序域,但我所追求的是某种相关/卷积/模式匹配策略,我认为肯定已经有一些东西了。

(编辑:下面有更多图片,还有更多解释)

在此处输入图像描述

编辑:根据要求,我将包含更多典型的图像,无论是表现良好还是有问题的。但它们不是彩色映射图像,而是灰度图像,因此颜色与数据大小直接相关,而彩色图像不会发生这种情况(仅用于通信)。尽管与彩色图像相比,灰色图像似乎缺乏对比度,但数据梯度是存在的,如果需要,可以通过一些自适应对比度来调出。


1)一个非常对称的主题的图像:

在此处输入图像描述


2)同一主题在不同时刻的图像。虽然有更多的“特征”(更多的渐变),但它并没有像以前那样“感觉”那么对称:

在此处输入图像描述


3)一个瘦弱的年轻受试者,在中线而不是更常见的凹中线有凸起(骨突起,用较亮的区域表示):

在此处输入图像描述


4) X 光证实有脊柱偏斜的年轻人(注意不对称):

在此处输入图像描述


5) 典型的“倾斜”主体(虽然大多围绕弯曲的中线对称,因此没有适当“变形”):

在此处输入图像描述


非常欢迎任何帮助!

2个回答

正如我在评论中所说,医学图像配准是一个有大量研究可用的主题,我不是专家。根据我的阅读,常用的基本思想是定义两个图像之间的映射(在您的情况下是图像及其镜像),然后如果应用映射,则定义平滑度和图像相似性的能量项,最后使用标准(或有时特定于应用程序的)优化技术优化此映射。

我在 Mathematica 中编写了一个快速算法来演示这一点。不是您应该在医疗应用中使用的算法,只是基本思想的演示。

首先,我加载您的图像,对其进行镜像并将这些图像分割成小块:

src = ColorConvert[Import["http://i.stack.imgur.com/jf709.jpg"], 
   "Grayscale"];
mirror = ImageReflect[src, Left -> Right];
blockSize = 30;
partsS = ImagePartition[src, {blockSize, blockSize}];
partsM = ImagePartition[mirror, {blockSize, blockSize}];
GraphicsGrid[partsS]

数学图形

通常,我们会进行近似刚性配准(使用例如关键点或图像时刻),但您的图像几乎居中,所以我会跳过这个。

如果我们看一个块,它是镜像对应的:

{partsS[[6, 10]], partsM[[6, 10]]}

数学图形

我们可以看到它们很相似,但发生了变化。转变的数量和方向是我们试图找出的。

为了量化匹配相似度,我可以使用平方欧几里得距离:

ListPlot3D[
  ImageData[
   ImageCorrelate[partsM[[6, 10]], partsS[[6, 10]], 
    SquaredEuclideanDistance]]]

数学图形

可悲的是,直接使用这些数据进行优化比我想象的要难,所以我使用了二阶近似值:

fitTerms = {1, x, x^2, y, y^2, x*y};

fit = Fit[
   Flatten[MapIndexed[{#2[[1]] - blockSize/2, #2[[2]] - 
        blockSize/2, #1} &, 
     ImageData[
      ImageCorrelate[partsM[[6, 10]], partsS[[6, 10]], 
       SquaredEuclideanDistance]], {2}], 1], fitTerms, {x, y}];

Plot3D[fit, {x, -25, 25}, {y, -25, 25}]

数学图形

该函数与实际的相关函数不同,但对于第一步来说已经足够接近了。让我们为每对块计算这个:

distancesFit = MapThread[
   Function[{part, template},
    Fit[Flatten[
      MapIndexed[{#2[[2]] - blockSize/2, #2[[1]] - blockSize/2, #1} &,
        ImageData[
        ImageCorrelate[part, template, 
         SquaredEuclideanDistance]], {2}], 1], 
     fitTerms, {x, y}]], {partsM, partsS}, 2];

这为我们提供了优化的第一个能量项:

variablesX = Array[dx, Dimensions[partsS]];
variablesY = Array[dy, Dimensions[partsS]];

matchEnergyFit = 
  Total[MapThread[#1 /. {x -> #2, y -> #3} &, {distancesFit, 
     variablesX, variablesY}, 2], 3];

variablesX/Y包含每个块的偏移量,并在matchEnergyFit应用了偏移量的情况下近似原始图像和镜像图像之间的平方欧几里得差。

单独优化这种能量会产生糟糕的结果(如果它完全收敛的话)。我们还希望偏移是平滑的,其中块相似性对偏移没有任何影响(例如,沿着直线或在白色背景中)。

所以我们为平滑度设置了第二个能量项:

smoothnessEnergy = Total[Flatten[
    {
     Table[
      variablesX[[i, j - 1]] - 2 variablesX[[i, j]] + 
       variablesX[[i, j + 1]], {i, 1, Length[partsS]}, {j, 2, 
       Length[partsS[[1]]] - 1}],
     Table[
      variablesX[[i - 1, j]] - 2 variablesX[[i, j]] + 
       variablesX[[i + 1, j]], {i, 2, Length[partsS] - 1}, {j, 1, 
       Length[partsS[[1]]]}],
     Table[
      variablesY[[i, j - 1]] - 2 variablesY[[i, j]] + 
       variablesY[[i, j + 1]], {i, 1, Length[partsS]}, {j, 2, 
       Length[partsS[[1]]] - 1}],
     Table[
      variablesY[[i - 1, j]] - 2 variablesY[[i, j]] + 
       variablesY[[i + 1, j]], {i, 2, Length[partsS] - 1}, {j, 1, 
       Length[partsS[[1]]]}]
     }^2]];

幸运的是,Mathematica 内置了约束优化:

allVariables = Flatten[{variablesX, variablesY}];
constraints = -blockSize/3. < # < blockSize/3. & /@ allVariables;
initialValues = {#, 0} & /@ allVariables;
solution = 
  FindMinimum[{matchEnergyFit + 0.1 smoothnessEnergy, constraints}, 
   initialValues];

让我们看看结果:

grid = Table[{(j - 0.5)*blockSize - dx[i, j], (i - 0.5)*blockSize - 
      dy[i, j]}, {i, Length[partsS]}, {j, Length[partsS[[1]]]}] /. 
   solution[[2]];
Show[src, Graphics[
  {Red,
   Line /@ grid,
   Line /@ Transpose[grid]
   }]]

数学图形

之前的0.1因素smoothnessEnergy是平滑能量相对于图像匹配能量项的相对权重。这些是不同权重的结果:

数学图形

可能的改进:

  • 就像我说的,首先执行严格的注册。在白色背景下,简单的基于图像时刻的配准应该可以正常工作。
  • 这只是一步。您可以使用在一步中找到的偏移量并在第二步中改进它们,可能使用更小的搜索窗口或更小的块大小
  • 我读过文章,他们完全没有块地这样做,但优化了每像素的偏移量。
  • 尝试不同的平滑函数

有趣的问题。首先,也许您正在使用基于兴趣关键点检测器和匹配的方法。这将包括SIFT(尺度不变特征变换)、SURF、ORB 等……甚至是仅基于 Harris 算子的更简单方法(csce.uark.edu/~jgauch/library/Features/Harris.1988.pdf )。从你的帖子中不清楚你尝试了什么,所以如果我在这里很天真,我很抱歉。

话虽如此,让我对数学形态学(MM)采取一种更简单的方法,只是为了好玩:)所有步骤的可视化图像都在最后。

我使用 ImageMagick 将您的示例图像转换为 L a b* 颜色空间,并且仅使用 L* 波段:

convert x.jpg -colorspace Lab -separate %d.png

0.png 对应于 L* 波段。现在,我确定您拥有实际的图像数据,但我正在处理 jpg 压缩伪影等等。为了部分解决这个问题,我使用半径为 5 的扁平圆盘执行了形态学打开,然后执行了形态学闭合。这是使用 MM 减少噪声的基本方法,并且考虑到圆盘半径,图像的变化不大。接下来我的想法是基于这个单一的图像,它很有可能在其他情况下失败。您感兴趣的区域在视觉上通过更暗(彩色图像中的“更热”)来区分,所以我认为基于统计的二值化器可以表现良好。我使用了 Otsu 的方法,这是一种自动的方法。

此时,可以清楚地看到中心感兴趣区域。问题是,在我的方法中,我希望它是一个封闭的组件,但事实并非如此。我首先丢弃每个小于最大连接组件的连接组件(不将背景计为其中之一)。如果二值化结果很好,这在其他情况下工作的机会更大。在您的示例图像中,有一个组件连接到背景,因此它不会被丢弃,但不会导致问题。

如果你还在关注我,我们还没有找到真正所谓的感兴趣的中心区域。这是我的看法。不管这个人有多弯曲(实际上我可以看到一些有问题的情况),该区域类似于一条垂直线。为此,我通过使用长度为 100 的垂直线执行形态打开来简化当前图像。这个长度纯粹是任意的,如果你没有缩放问题,那么这不是一个很难确定的值。现在我们再次丢弃组件,但我在这一步更加小心。我使用图像补全的区域打开来丢弃我认为的小区域,这可以通过以粒度分析的形式(也来自 MM)以更可控的方式完成。

我们现在大致有三个部分:图像的左侧部分、中间部分和图像的右侧部分。中心部分预计是三者中较小的部分,因此很容易获得。

这是最终结果,右下角的图像只是其左侧与原始图像的叠加图像。个别数字未全部对齐,抱歉匆忙。

http://i.imgur.com/XRhYv.png