Log in

View Full Version : Semi-automatic way to tweak thscd1 and thscd2 in mvtools?


Boulder
9th May 2020, 10:28
As the VS version of mvtools does not have the MShow functionality to visualize the motion vectors, I'm having problems tweaking the scene change threshold parameters. Noisy or material having a lot of fast movement is troublesome as they usually require raising the thresholds, otherwise they detect a lot of scene changes in places where it's not true.

I came up with an idea to do the degraining with a range of values for thscd1 or thscd2, maybe with 10 point steps or so. Use MakeDiff to extract the difference between the original and degrained clip. Display the different results along with the original in the same frame (downscaled or simply just cut a small part of the frame to show because you can easily see if no noise is removed).

Could someone help me with scripting this visualization, please? Or port MShow :D

feisty2
9th May 2020, 10:49
you don't need mshow to check if scene change detections worked properly. simply print _SceneChangePrev and _SceneChangeNext frame properties.

Boulder
9th May 2020, 13:03
you don't need mshow to check if scene change detections worked properly. simply print _SceneChangePrev and _SceneChangeNext frame properties.

Cheers, didn't remember/know that there's a function in the pack to provide this info :)

Boulder
9th May 2020, 17:15
I've worked it over like this, getting the property value for different thscd values. But I'm stumped with the current frame number, which is needed in get_frame. How do I get that one?

thscd = 100
sc = []
while thscd < 400 :
finalclip = core.mv.SCDetection(src, fv1, thscd1=thscd, thscd2=80)
scframe = finalclip.get_frame(n)
sc.append(scframe.props['_SceneChangePrev'])
thscd += 10

feisty2
9th May 2020, 17:45
why don't you print frame properties directly on your video clip? (http://www.vapoursynth.com/doc/functions/frameprops.html)
you can then check them in the preview window of vsedit

Boulder
9th May 2020, 18:01
I was thinking of printing the result of all tests in the same frame along with the corresponding thscd value. Or is it possible with FrameProps?

_Al_
9th May 2020, 18:38
to print just a frame with that thscd:
thscd = 45
src = core.text.FrameNum(src, alignment=7)
src = core.text.Text(src, str(thscd), alignment=8)

Boulder
9th May 2020, 18:43
The problem is printing all values in the same frame. In that example, I would check thscd between 100-400 in steps of 10 and print the result of each of them in the same frame. In a real case, I'd probably have a range over 240-350 or something like that.

feisty2
9th May 2020, 18:49
trivial stuff, learn a bit of python

ChaosKing
9th May 2020, 18:50
I've worked it over like this, getting the property value for different thscd values. But I'm stumped with the current frame number, which is needed in get_frame. How do I get that one?

thscd = 100
sc = []
while thscd < 400 :
finalclip = core.mv.SCDetection(src, fv1, thscd1=thscd, thscd2=80)
scframe = finalclip.get_frame(n)
sc.append(scframe.props['_SceneChangePrev'])
thscd += 10

Look also how to use frameeval

Simple example for detecting a blinking clock. (n is your current frame number)
https://forum.doom9.org/showthread.php?p=1906719#post1906719

http://www.vapoursynth.com/doc/functions/frameeval.html


or if you just want to "scan" the whole video before filtering

for i in range(clip.num_frames):
clip.get_frame(i)
Example: https://gist.github.com/dubhater/3a2c8a59841cae49ecae25cd47ff78d2#file-seek-test-py-L38

feisty2
9th May 2020, 19:02
I don't wanna write the code cuz it's boring, but basically you do the following

1. let n = 0
2. evaluate the clip with mv.SCDetection
3. attach scd1_n, scd2_n as frame props
4. let _SceneChangePrev_n = _SceneChangePrev, _SceneChangeNext_n = _SceneChangeNext
5. attach _SceneChangePrev_n, _SceneChangeNext_n as frame props
6. erase _SceneChangePrev, _SceneChangeNext from frame props
7. n = n + 1
8. repeat 2. ~ 7. with different scd1 and scd2
9. print all frame props

_Al_
9th May 2020, 19:21
Do you want to print frame value together with all possible props['_SceneChangePrev'] values in one frame from that loop?
then put those values directly in that sc list right away,
text.Text() accepts new lines


to generate n for each frame it is up to you as Chaos King says, if using FrameEval and put you loop thing in it, where n is passed for your convenience

def using_eval(n, clip):
thscd = 100
sc = []
while thscd < 400 :
finalclip = core.mv.SCDetection(clip, fv1, thscd1=thscd, thscd2=80)
scframe = finalclip.get_frame(n)
sc.append( str(thscd) + ' , ' + str(scframe.props['_SceneChangePrev']) )
thscd += 10
return core.text.Text( clip, '\n'.join(sc), alignment=7)
src = core.text.FrameNum(src, alignment=8)
out = core.std.FrameEval(src, functools.partial(using_eval, clip=src))
oh, that is not going to work, because finalclip will be always the same, or maybe yes, try it, I cannot test it using mvtools now

Boulder
9th May 2020, 21:18
Thanks everyone, I'll do some testing tomorrow when I have more time.
It would be easy if the current frame number could be extracted like clip width or height but looks like it needs some more complex ways.

Boulder
10th May 2020, 10:38
oh, that is not going to work, because finalclip will be always the same, or maybe yes, try it, I cannot test it using mvtools now

To me it looks like it works perfectly :) It is just surprising to see how low you can set thscd1 and/or thscd2 before false scene changes are appearing in the list. I think that it was quite different with the old Avisynth toolset.

Need to test some more, I think I should try to find a nice baseline for my needs.