Allow arbitrary value of lightswitch detect
Closes https://github.com/motioneye-project/motioneye/issues/2596
@zagrim @MichaIng mind taking a look at this PR? It allows users to select via the UI a lightswitch detection of less than 5%. For some reason (aesthetics over functionality?) it was snapping to 5% intervals and gave users no way to have granular control
I also added a comment on the issue, and now I'm wondering if light switch detection threshold and maximum motion threshold both do the same thing... (except for light switch detect having the number of frames to ignore, which in some cases might make a difference). Percentages are easier to interpret and validate mentally than absolute number of pixels, and sliders are (for many) nicer to use than number inputs, so I kind of see why users would gravitate to using light switch detection for setting the max change threshold.
If I'm not mistaken, in the original issue the setting was misunderstood: One needs to set the percentage higher if motion detection does not work anymore. I'm not sure how exactly "motion" detects this "sudden massive light intensity change", but if you use 5% or less, it makes sense that also regular motion on a small area triggers this setting to ignore it, as long as the colour/"brightness" change on the changing pixels is sufficiently "massive". Could be tested when doing motion which implies only a minimal colour change on the pixels, whether this does not trigger the lightswitch detection (so that motion is detected/recorded).
So, allowing a value below 5%, if I understand it correctly, doesn't make sense because it would imply false "lightswitch" detection too often, breaking motion detection that way.
But probably it is fine to still allow users testing all values they want, as it probably it highly depending on the camera and actual light conditions. Would be okay for me to allow setting values in single percentage steps.
My experiments suggest that this works in the opposite way of "maximum motion threshold". Rather than setting a maximum # of changed pixels before detection gets disabled, it effectively sets a minimum # of changed pixels which disables detection. It's useful for me to go below 5% because at night I am often getting false alarms because the headlights from passing cars light up fewer than 5% of the pixels (yet still many more pixels than I have my threshold set to).
Take the docs: https://motion-project.github.io/motion_config.html#lightswitch_percent
Ignore sudden massive light intensity changes when the percentage of the picture area that changed intensity is greater than this value.
So if it's set to 5%, it is sufficient that >5% of the area changes, to "ignore" the motion. If you go below 5%, motion is ignored from even less changes. Setting it to 95% means that nearly the whole image needs to change for the motion to be ignored.
So what I get from this is that the setting should be set to a value larger than the share of the largest expected moving thing on the camera image. If you set it to 5% and a moving person takes 6% of the camera view, it will be interpreted as lightswitch and ignored.
But that's only what the docs say, while I didn't do any tests.
If it was indeed a threshold, it would indeed double with "Frame Change Threshold".
EDIT:
the headlights from passing cars
But that to me seems more a task for the motion mask to exclude the street for motion detection. Lights from passing cars cannot be differentiated from flashlights from thieves based on their size on the camera view. You do not want to exclude too much motion based on size, since it becomes more and more likely that you get false negatives.
Because of the way I've positioned my camera, a thief would come gradually into the frame and so only between .1% and less than 5% would be a reasonable detection range.
I'm not sure I see why the UI would artificially impose a restriction on the range of values the user can provide, if the underlying software (motion) can handle it? Don't think that's user-friendly and is somewhat presumptuous about the user's situation.
Yes, difference between a thief's flashlight and a passing car is a valid problem. But in my case, masking doesn't solve this problem. The area that would be masked to solve the problem is an area that I actually want to be able to detect. Instead, I think allowing an external user-provided signal to be considered as part of "detection" criteria would be needed (my suggestion here). That gives the user infinite ways of solving the problem by coming up with their own way of telling difference between thief's flashlight and car's headlamp.
I'm not sure I see why the UI would artificially impose a restriction on the range of values the user can provide
Basically I agree. snap="2" seems to be used on any 0/1-100 bar, resulting in any value 5 or closer to the highlighted 5-6 values being unselectable, which doesn't make so much sense. I think it just feels a little nicer being able to apply round values easily, at the cost flexibility. I vote for converting all snap="2" to snap="0", as all cases are similar percentages with zero decimals, and the pointer will jump to the next integer automatically when released.
Also I confused the post of the original issue (where I think a value below 5% will make the issue of false negatives worse, not better) with yours, where it might help, if a thief (or whatever you want to detect/record) really changes less than X% of frames while car lights change more than those X%.
If I'm not mistaken, in the original issue the setting was misunderstood: One needs to set the percentage higher if motion detection does not work anymore.
Good point @MichaIng on the original issue, you are absolutely right.
Important point to note (to also @lowlyocean ) is that AFAIK motion only works with grey-scale images, and everything it does is calculated from frame-to-frame pixel changes (diff of the frames, possibly filtering out the smallest changes as noise, and then summing up the absolute value of the pixel intensity changes for the purposes of thresholding on frame level). Thus, it can't really tell the difference between the illumination change from headlights (or a flashlight) and a moving object, which is really sad for us that have outside cameras.
I don't know how the lightswitch detection actually works, but since it has also lightswitch_frames beside lightswitch_percent, it seems to be suited well for sudden significant changes (by default it ignores only 5 frames when the area covered by changes is above the set percent of the frame). Given how it is documented, it might even operate on it's "private" hardcoded pixel change threshold which is set high enough to not be interfered by noise or slight motion. If that is the case, it really could make a difference trying to use lightswitch detection with a small percentage value and not use max threshold with a value that is the same percentage of of pixels of the frame. I've never thought it that way, but it makes sense to me now.
I applied to change now to all percentage settings for the same argument/reason. Works and looks GTM now.