0

My application is taking screenshots from a monitor (nothing else yet). There is an area, which either changes really fast or a bit slow. I want to be able to tell which is it and depending on it I will choose course of action (for now just print 0 or 1). How would I do that? Is there something like measure of how much pixels changed in few milliseconds? Should I be comparing last two images or something else? Is there other approach I could use? Any leads would be awesome! thank you very much

EDIT: I want to learn to work with OpenCV and I play a game. I want to be able to read what is happening in this game (which is windowed) using OpenCV and then process what I see. There is a minigame where there are two states of movement. One is quick, the second is slow. So a set a goal to write an app which will be able to recognize which is which

Jacob
  • 13
  • 1
  • 7

2 Answers2

0

Since you labeled the question with opencv, I am assuming you know how to read the screenshots into a cv::Mat. Now let's use a cv::Rect roi to represent the area that you are interested in monitoring.

The first thing you need to do is define "change". There are many ways to measure the difference between two images, for example, Sum of absolute differences (SAD) or Normalized cross correlation (NCC). Base on what you described, it sounds like you are looking for "The number of changed pixels". In that case, you can create a difference image and then count how many non-zero elements in the image (assuming zero means equal):

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

Here f1 and f2 are two screenshots that you want to compare with, and the result change will give you a ratio of how many pixels has changed inside the area (0 <= change <= 1).

Now, with this measurement, you need to further define "change over time". Let's say you take one screenshots per 50 ms. One naive way to determine if it's a fast change or slow change is to compare change from the last two screenshots with a threshold, say 0.5. If change < 0.5, it's a slow change, otherwise, it's a fast change. Depending on your application, this might work, it could also turns out to be too noisy. A more robust approach would be computing the average of change over the last second (or 500ms). You can make it more fancy with Moving Average.

cxyzs7
  • 1,227
  • 8
  • 15
  • Hello, thnaks for help. I actually tried your code and it says I cant use operator "/" for double and cv::size. Do I have to make some specific conversion? – Jacob Jul 20 '16 at 13:36
  • @Jacob My bad, try roi.area() instead. I edited the answer too. – cxyzs7 Jul 20 '16 at 16:08
  • Yeah, that helped, but anyway, I am a bit lost in here. After I do what we talked about here, I get an exception. Specifically in the countNonZero row. Btw, what is the easiest way to store actual and previous frame? – Jacob Jul 20 '16 at 16:33
  • So, this is what I get so far: https://i.imgsafe.org/faaa449e8c.png (count non zero still does not work) I think its too noisy so I will have to use something else then just plain roi comparison. The object in red rectangle is what I want to measure. It moving around either fast or slow, but there is also other pixels, which ofcourse move too. – Jacob Jul 20 '16 at 16:46
0

Edited 5:13 7/18/2016

Is there something like measure of how much pixels changed in few milliseconds?

I want to be able to tell which is it and depending on it I will choose course of action (for now just print 0 or 1). How would I do that?

Should I be comparing last two images or something else?

You seem to be asking quite a number of questions here, it's probably best if you split them up.

However, to answer the specific issue of how to get the screen info you need to get your algorithm to work... You can use a method like this to work with a video stream from the Windows API.

My advice is to find a way to record a very short stream with a mostly accurate start and end times, then you can use this information to compare each frame in the stream at a timeline you decide on and you can calculate the pixel delta as either an average as cxyzs7 mentioned... aka (in a very notional way)

//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

And here is how you do ROI stuff.

Or, you can use this guide histogram calculation in order to find the values as a group and then compare the changes in histogram values in order to detect the changes of specific values, colors, or saturation etc... rather than an ROI.

The important thing is to make sure you have an accurate time for each frame, which is much easier to calculate based on a video stream rather than a string of singular screen caps.

The screen caps out of a stream will give you frames that are more accurate relative to each other, so there will be some lag time between the screen output and the calculations of the differences, but if it's a short enough loop it should be fast enough to give you the results as accurately as you need them.

Community
  • 1
  • 1
Jeremy Gamet
  • 165
  • 7
  • Hi, thanks for input. I am working on windows 10 machine and it will stay that way. Simply put, I want to learn to work with OpenCV and I play a game. I want to be able to read what is happening in this game (which is windowed) using OpenCV and then process what I see. There is a minigame where there are two states of movement. One is quick, the second is slow. So a set a goal to write an app which will be able to recognize which is which, for starters. Will I be able to do such a think? I will also edit main question with better explanation. – Jacob Jul 18 '16 at 21:25
  • Okay, I've edited it to include information about one of many ways to capture the video stream in the windows API. – Jeremy Gamet Jul 18 '16 at 21:47
  • Thanks again! I actually already had a look into that topic, but they are not capturing video, but single screenshots (if I understand it correctly). – Jacob Jul 18 '16 at 22:28
  • I have updated that link with a more relevant solution. – Jeremy Gamet Jul 18 '16 at 23:15
  • Well, they are all basically linking back to your previous answer. But I will go thru them all. – Jacob Jul 19 '16 at 14:37