光流的简单案例

10

概述:我希望描述的使用案例是一个简单的光流问题,由于我对这个主题没有很多了解,所以我想知道是否有人能提供解决问题的建议。

已经进行的研究:我已开始阅读基于变形理论的高精度光流估计论文,并计划查看Particle Video论文。我找到了MATLAB 高精度光流实现的光流代码。然而,这些论文(和代码)似乎描述了非常复杂的概念,可能需要我花费很多时间去深入了解。我希望解决我的问题可能更简单。

问题:我有一系列图像。这些图像描述了材料断裂过程,其中材料和背景是黑色的,裂缝是白色的。我有兴趣在尝试将发生断裂过程中形成的所有裂缝映射到第一个黑色图像时,反向遍历图像序列。您可以将材料想象为一个大拼图,我正在尝试按照它们断裂的相反顺序将它们重新拼合在一起。

在每个图像中,可能会出现一些刚开始出现的裂缝和/或一些已经完全形成(因此创建了一个片段)的裂缝。在破碎过程中,某些片段可能会分离并进一步破裂。这些片段也可以相互移动(在连续帧之间变化很小)。 期望输出:将序列中所有的裂缝/线条映射到序列中的第一张图像上。 附加说明:图像以灰度格式(即原始格式)和二进制格式提供,其中裂缝已用白色轮廓勾画出来,背景完全为黑色。请参见下面的一些图像示例。

orig_img1 orig_img2 orig_img3

binary_img1 binary_img2 binary_img3

顶部一行显示原始图像,底部一行显示二进制图像。您可以看到,中间的裂缝随着图像序列的推进而越来越宽。因此,底部的裂缝与下部碎片一起移动。当以相反的顺序遍历序列时,我希望能够算法地实现中间的裂缝合并为一个(并将其正确映射到第一幅图像),并正确映射底部的裂缝,保持其与底部碎片的正确对应关系(大小和位置)。

一个序列通常包含约30~40个图像,因此我只显示了开始的子集。此外,尽管这些图像没有显示出来,但可能有特定的图像仅包含裂缝的开头(即其最初的出现),在随后的图像中,它会变得越来越长,并可能与其他裂缝连接。

语言:虽然不是必需的,但我想使用MATLAB实现解决方案(只是因为与项目相关的大多数其他代码都是用MATLAB完成的)。但是,如果OpenCV可能更容易,我对语言/库的使用非常灵活。

任何想法都非常感激。


2
光流(Optical flow)对于黑白图像不会产生有意义的结果。此外,您的问题缺乏明确说明——您想要什么样的输出?正如之前一样,提供样本图像可以帮助我们更好地理解情境。 - etarion
为什么最后一张图不是期望的输出?片段能够移动并增加彼此之间的间隙吗? - Andrey Sboev
1
请提供图片。一般来说,OF算法需要纹理,不太适合二进制图像。如果您提供所阅读的论文名称而非PDF链接,将会很有帮助。 - Adi Shavit
@Andrey:是的,片段通常会在整个序列中与彼此之间的间隙增加而移动。@etarion:创建二进制图像是因为我认为它可能会使算法更简单。原始灰度图像可用(请参见编辑)。@Adi:请查看编辑。 - Myx
你对“期望输出”进行的解释相当简短 - 你能提供一个你希望从这三张图片中提取的示例输出数据集吗? - Jonas Heidelberg
3个回答

3
遍历前进而不是倒退,不要使用光流。使用裂缝线来分割黑色部分,跟踪每个黑色片段的质心随时间变化。每当出现一条新的横穿一个黑色片段的裂缝线时,将该片段分成两个部分,并继续单独跟踪每个片段。
从这里,您应该能够构建代表黑色部分随时间分割的树形结构。裂缝线可以作为元数据添加到此树中,可能将裂缝线分配给它们首次出现的片段节点。

0

我同意Damian的观点。大多数光流方法(如HAOF)依赖于强度恒定约束方程I(x,t)= I(x + v,t + dt)的一阶泰勒近似。这意味着解决方案取决于图像导数,其中梯度确定运动矢量的大小和角度,即需要一定数量的纹理。但是,您的非二值化图像的纹理非常低,可能已经足够了。您可以尝试直方图均衡化来增加输入数据的对比度,但重要的是为两个输入图像应用相同的转换。例如:

cv::Mat equalizeMat(grayInp1.rows, grayInp1.cols * 2 , CV_8UC1);
grayInp1.copyTo(equalizeMat(cv::Rect(0,0,grayInp1.cols,grayInp1.rows))); 
grayInp2.copyTo(equalizeMat(cv::Rect(grayInp1.cols,0,grayInp2.cols,grayInp2.rows)));
cv::equalizeHist(equalizeMat,equalizeMat);
equalizeMat(cv::Rect(0,0,grayInp1.cols,grayInp1.rows)).copyTo(grayInp1);
equalizeMat(cv::Rect(grayInp1.cols,0,grayInp2.cols,grayInp2.rows)).copyTo(grayInp2);
// estimate optical flow

0
我建议你跟随最初的想法,回溯裂缝。你知道裂缝的样子,所以可以追踪所有属于裂缝的点。你只需要使用光流跟踪器跟踪所有白色点,从Lukas-Kanade跟踪器开始,看看你能得到什么结果。高精度光流方法是一种全局方法,更加通用,我会尝试跟踪图像中的所有像素,尽量保持平滑性。LK是一种局部方法,将仅在每个点周围使用一个小窗口进行跟踪。问题是除了裂缝外,所有像素都是纯黑色的,因此没有什么可跟踪的,你只会浪费时间去跟踪那些无法跟踪且不需要跟踪的东西。
如果线条非常直,你可能会遇到所谓的光圈问题,并且会得到不准确的结果。你也可以尝试基于蛇的形状拟合/变形。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接