【问题标题】:How to measure changes in pixel colors in certain area of picture如何测量图片特定区域中像素颜色的变化
【发布时间】:2016-11-20 11:10:06
【问题描述】:

我的应用程序正在从监视器截取屏幕截图(还没有其他内容)。有一个区域,要么变化非常快,要么有点慢。我希望能够分辨出它是什么,并根据它选择行动方案(现在只打印 0 或 1)。我该怎么做?有没有类似测量几毫秒内改变多少像素的方法?我应该比较最后两张图片还是其他什么?我可以使用其他方法吗?任何线索都会很棒!非常感谢

编辑:我想学习使用 OpenCV 并玩游戏。我希望能够使用 OpenCV 阅读这个游戏(窗口化)中发生的事情,然后处理我看到的内容。有一个小游戏,其中有两种运动状态。一是快,二是慢。所以设定一个目标来编写一个能够识别哪个是哪个的应用程序

【问题讨论】:

  • 尝试使用光流

标签: opencv colors pixel screen-capture


【解决方案1】:

由于您使用 opencv 标记问题,我假设您知道如何将屏幕截图读入cv::Mat。现在让我们使用cv::Rect roi 来表示您有兴趣监控的区域。

您需要做的第一件事是定义“改变”。有很多方法可以测量两个图像之间的差异,例如,Sum of absolute differences (SAD) 或 Normalized cross correlation (NCC)。根据您的描述,听起来您正在寻找“更改的像素数”。在这种情况下,您可以创建一个差异图像,然后计算图像中有多少非零元素(假设零表示相等):

cv::Mat diff = (f1(roi) != f2(roi));
double change = static_cast<double>(cv::countNonZero(diff))/roi.area();

这里f1f2 是您要比较的两个屏幕截图,结果change 将为您提供该区域内像素变化的比率(0 &lt;= change &lt;= 1)。

现在,通过此测量,您需要进一步定义“随时间变化”。假设您每 50 毫秒截取一张屏幕截图。确定它是快速变化还是缓慢变化的一种天真的方法是将最后两个屏幕截图中的change 与阈值(例如 0.5)进行比较。如果change &lt; 0.5,则为缓慢变化,否则为快速变化。根据您的应用程序,这可能会起作用,但也可能会变得太嘈杂。一种更强大的方法是计算最后一秒(或 500 毫秒)内change 的平均值。您可以使用Moving Average 使其更加精美。

【讨论】:

  • 您好,感谢您的帮助。我实际上尝试了您的代码,它说我不能将运算符“/”用于 double 和 cv::size。我必须进行一些特定的转换吗?
  • @Jacob 我的错,试试 roi.area() 代替。我也编辑了答案。
  • 是的,这有帮助,但无论如何,我在这里有点迷路了。在我做了我们在这里谈论的事情之后,我得到了一个例外。特别是在 countNonZero 行中。顺便说一句,存储实际和前一帧的最简单方法是什么?
  • 所以,这就是我到目前为止得到的:i.imgsafe.org/faaa449e8c.png(计数非零仍然不起作用)我认为它太吵了,所以我必须使用其他东西,然后只是简单的 roi 比较。红色矩形中的对象是我要测量的。它移动的速度或快或慢,但也有其他像素,当然也会移动。
【解决方案2】:

已于 2016 年 7 月 18 日 5:13 编辑

是否有类似测量几毫秒内改变多少像素的方法?

我希望能够分辨出它是什么,并根据它选择行动方案(现在只打印 0 或 1)。我该怎么做?

我应该比较最后两张图片还是其他什么?

您似乎在这里问了很多问题,最好将它们分开。

但是,要回答如何获取屏幕信息的具体问题,您需要让算法正常工作...您可以使用this 之类的方法来处理来自 Windows API 的视频流。

我的建议是找到一种方法来记录一个非常短且开始和结束时间非常准确的流,然后您可以使用此信息在您决定的时间线上比较流中的每一帧,然后您可以计算像素delta 作为cxyzs7 提到的平均值...又名(以非常概念的方式)

//do in a loop of some kind of your choice
cv::Mat diff = (f1(roi) != f2(roi));
//followed by a calculation of how long it's been since the last change

if(diff == a_Mat_ofZeros)
     changeDetected[i++] = 1;
else changeDetected[i++] = 0;
//then track the changes through an array in a loop

here 是您实现 ROI 的方式。

或者,您可以使用本指南histogram calculation 来查找一组值,然后比较直方图值的变化,以检测特定值、颜色或饱和度等的变化......而不是投资回报率。

重要的是要确保每一帧都有准确的时间,这比基于视频流而不是一串单一的屏幕截图更容易计算。

流中的屏幕截图将为您提供相对于彼此更准确的帧,因此屏幕输出和差异计算之间会有一些延迟时间,但如果它是一个足够短的循环,它应该以足够快的速度为您提供所需的准确结果。

【讨论】:

  • 您好,感谢您的意见。我正在使用 Windows 10 机器,它将保持这种状态。简而言之,我想学习使用 OpenCV 并玩游戏。我希望能够使用 OpenCV 阅读这个游戏(窗口化)中发生的事情,然后处理我看到的内容。有一个小游戏,其中有两种运动状态。一是快,二是慢。因此,为初学者设定一个目标,即编写一个能够识别哪个是哪个的应用程序。我能有这样的想法吗?我还将用更好的解释编辑主要问题。
  • 好的,我已经对其进行了编辑,以包含有关在 Windows API 中捕获视频流的多种方法之一的信息。
  • 再次感谢!实际上,我已经看过该主题,但他们不是在捕获视频,而是单个屏幕截图(如果我理解正确的话)。
  • 我已经用更相关的解决方案更新了该链接。
  • 嗯,它们基本上都链接回您之前的答案。但我会通过所有这些。
猜你喜欢
  • 1970-01-01
  • 2021-04-30
  • 1970-01-01
  • 2012-02-06
  • 1970-01-01
  • 2012-03-25
  • 2015-12-15
  • 1970-01-01
相关资源
最近更新 更多