光流的简单情况

时间:2011-05-26 16:07:10

标签: image matlab image-processing opencv opticalflow

一般:我希望我将要描述的用例是一个光流问题的简单案例,因为我对这个问题知之甚少,我想知道是否有人对如何解决我的问题提出任何建议。

我已经完成的研究:我已经开始阅读High Accuracy Optical Flow Estimation Based on a Theory for Warping论文,并且正计划查看Particle Video论文。我找到了光流的MATLAB High Accuracy Optical Flow实现。然而,论文(和代码)似乎描述了非常复杂的概念,可能需要大量时间来深入挖掘和理解。我希望我的问题的解决方案可能更简单。

问题:我有一系列图片。图像描绘了材料破损过程,其中材料和背景是黑色的,裂缝是白色的。我有兴趣反过来遍历图像序列,试图将破损过程中形成的所有裂缝映射到第一个黑色图像。您可以将材料视为一个大型拼图,我试图将它们按照它们破坏的相反顺序重新组合在一起。

在每张图片中,可能会出现一些刚刚出现的裂缝和/或一些已完全形成的裂缝(从而形成碎片)。在整个破损过程中,一些碎片可能会分离并进一步破碎。片段也可以彼此远离移动(后续帧之间的变化很小)。

所需输出:序列中的所有裂缝/线都映射到序列中的第一个图像。

附加说明:图像以灰度格式(即原始图像)以及二进制格式提供,其中裂缝以白色轮廓,背景为全黑。有关图像示例,请参见下文。

orig_img1 orig_img2 orig_img3

binary_img1 binary_img2 binary_img3

顶行显示原始图像,底行显示二进制图像。正如您所看到的,随着图像序列的进展,沿着中间向下的裂缝变得越来越宽。因此,底部裂缝与下部裂缝一起移动。当反向遍历序列时,我希望通过算法实现中间裂缝合为一体(并将其正确映射到第一幅图像),并正确映射底部裂缝,保持其正确的对应关系(大小和位置)与底部片段。

一个序列通常包含大约30~40个图像,所以我刚刚显示了初始子集。此外,虽然这些图像没有显示,但特定图像可能只包含裂缝的开始(即其初始外观),并且在随后的图像中,它会变得越来越长,并且可能与其他裂缝结合。

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

非常感谢任何想法。

3 个答案:

答案 0 :(得分:4)

向前而不是向后移动,不使用光流。使用断裂线来分割黑色部分,跟踪每个黑色部分的质心随时间的变化。每当出现切割黑色片段的新骨折线时,将该片段分成两个并继续分别跟踪每个片段。

由此您应该能够构建一个树结构,表示黑色部分随时间的分割。可以将断裂线作为元数据添加到该树中,可能将断裂线分配给它们首次出现的分段节点。

答案 1 :(得分:0)

我建议你按照你最初的想法回溯裂缝。哟有点知道裂缝的样子,所以你可以跟踪属于裂缝的所有点。您只需使用光流跟踪器跟踪所有白点,从Lukas-Kanade跟踪器开始,查看您的位置。高精度光流方法是全球性的,更通用的,我会跟踪图像中的所有像素,试图保持一定的平滑度。 LK是一种本地方法,它只使用每个点周围的小窗口来进行跟踪。问题是从裂缝中得到的所有像素都是纯黑色,所以没有什么可以跟踪那里,你只是腰部时间试图跟踪你无法跟踪的东西,你不需要跟踪。 如果线条非常直,你可能会得到所谓的aperture problem,你会得到不准确的结果。你也可以尝试一些基于蛇的形状拟合/变形。

答案 2 :(得分:0)

我同意达米安。大多数光学流动方法如HAOF依赖于强度恒定consural方程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