4

我想知道是否有一种快速算法可以检测在两个连续屏幕截图之间移动的部分。该算法应该获取两张图像并在一张图像中输出一组(矩形)区域,以及一个描述匹配区域在另一张图像中的位置的向量。

我想将其用于为屏幕捕获而简化的无损视频压缩算法。我认为这使得用例与运动检测的通常应用有点不同:

  • 图片是截图。不太可能有任何伪影或图像噪声
  • 如果图像的一部分移动,它会按像素移动。移动部分的像素差异通常不到 2%
  • 移动的区域通常很大并且呈矩形

由于视频压缩管道还有其他步骤并且应该实时发生,因此运动检测应该很快。

有什么有用的吗?

4

4 回答 4

2

跨帧跟踪运动的常用方法是: 1. 确定要在图像 1 中跟踪的点 2. 将输入图像中的点与输出图像中的点相关联 3. 确定使它们到达那里的变换

对于第 1 步,有很多“跟踪器”,您会在 OpenCV 中找到一些相当标准的用于寻找“有趣”点(边缘的交叉点、局部最大值等)。Kanade-Tomasi 图像跟踪器就是其中之一。但是,为了您的使用,您可能更喜欢只创建一个规则的点网格。

对于第 2 步,一种常见的技术是使用降低分辨率的四叉树......我的意思是拍摄您的图像,创建一个宽度和高度为 1/2 的新图像,一次又一次。现在您在顶部有一个非常低分辨率的图像,您可以更快地搜索数量级,并且会给您一个边界框来查看下一个更高的 rez 图像。在您的情况下,优化可能是首先查看输出以查看它是否发生了变化,当您找到点 x、y 的匹配项时,还要在其旁边查找点 x+1 或 y+1 等。

对于第 3 步,这取决于您……如果您谈论的是在屏幕上滑动的窗口,则会有大块一起移动,但边缘内外是相同的。但是,如果有任何动画,那可能会把事情搞砸。而鼠标光标本身就是一个小东西,它会四处移动并降低算法的有效性。

于 2012-08-24T17:27:04.523 回答
2

我有一些想法,以及您可以考虑的可能可行的解决方案。

首先,考虑跟踪单个像素增量并仅传输/存储这些增量。一个典型的交互会话通常只涉及很小部分的 UI 更改;对于长时间使用计算机的会话,移动或调整窗口大小往往不太常见(有趣的是)。这可以有效地捕获简单的内容,例如输入的文本、光标移动和小的 UI 更新,而无需大量额外工作。

您还可以考虑尝试在较低级别挂钩操作系统,以获取例如像素的显示列表,甚至(最佳)“损坏”矩形列表。例如,Mac OS X 的 Quartz 合成器可以为您提供这些信息。这可以帮助您快速缩小要更新的范围,并且在理想情况下,可以为您提供屏幕本身的有效表示。

如果您可以查询有关窗口的操作系统(窗口管理器)信息,则可以为每个可见窗口存储单独的数据流(像素增量),然后在播放期间应用简单的显示列表方法来“渲染”它们。然后,识别移动窗口很简单,因为您可以简单地区分显示列表。

如果您可以查询操作系统关于光标位置的信息,您可以使用光标移动来快速估计移动增量,因为光标移动通常与屏幕上的对象移动(例如移动窗口、图标、拖动对象等)有很好的相关性。这使您可以避免处理图像以确定移动增量。

一个可能的解决方案(或者如果您仍然无法通过上述方法识别移动增量的最后手段):我们实际上可以相当容易地处理单个移动矩形的(非常常见的)情况。制作帧中所有变化的像素的蒙版。识别掩码中最大的连通分量。如果它近似于一个矩形,那么您可以假设它代表一个移动的区域。窗口移动完全正交(例如完全在 x 或 y 方向),在这种情况下,总增量看起来像一个稍大的矩形,或者窗口沿对角线移动,在这种情况下,总增量将有一个 8 边形状。无论哪种方式,您都可以估计运动矢量,并通过区分区域来验证这一点。请注意,这种处理会故意忽略您必须考虑的细节,例如 像素在窗口附近独立移动,或看起来没有变化的区域(例如窗口中的大块纯色)。实际的实现必须处理上述所有问题。

最后,我将研究有关实时运动估计的现有文献。在优化运动估计和补偿(例如视频编码)方面已经做了很多工作,因此如果您发现上述方法不合适,您也可以使用这些工作。

于 2012-08-23T04:16:39.440 回答
2

Opencv 深入介绍了图像处理,并提供了大量关于该主题的教程。

http://docs.opencv.org/doc/tutorials/tutorials.html

PDF比网站有更多的tuts。Google for... opencv 教程 pdf ...顶部链接。

主要网站。 http://opencv.willowgarage.com/wiki/

本质上,您可以在图像上运行数学函数来为您解决问题。卷积等。

于 2012-08-24T09:17:21.110 回答
1

我做了什么

我实现了一种简单的技术,可以补偿大多数运动并且易于实现。

每一帧都被分成固定大小的瓦片,比如 8×8 像素。编解码器管理可自定义数量的块的环形缓冲区,例如 2 20。现在,对于编解码器在输入流中遇到的每个图块,它检查是否已经在环形缓冲区中找到它。如果是,它只是保存切片索引,如果不是,它将切片存储在环形缓冲区中。

每当图像的一部分从过去的任何图像中移动块大小的倍数时,很可能会在缓存中找到切片。这样,可以补偿大多数运动。由于在 ringbuffer 中找到一个 tile 非常快,这足以实时运行。

于 2012-08-24T15:55:29.510 回答