Welcome to Doom9's Forum, THE in-place to be for everyone interested in DVD conversion.

Before you start posting please read the forum rules. By posting to this forum you agree to abide by the rules.

 

Go Back   Doom9's Forum > Capturing and Editing Video > Avisynth Usage

Reply
 
Thread Tools Search this Thread Display Modes
Old 8th February 2015, 03:22   #1  |  Link
flyvholm
Semper Tiro
 
flyvholm's Avatar
 
Join Date: Jan 2015
Location: Denmark
Posts: 29
MCTD and memory

I'm new to Avisynth, jumping in because I'm looking to do some noise reduction. I'm working with DSLR timelapse image sequences that I'm making a film from, importing the sequences in Adobe After Efffects for post processing (such as pan/zoom). For best results I should apply the noise reduction to the original image sequences where most of the image is static from frame to frame, and due to the further processing I generally can't reduce the resolution before denoising. Images are mostly 12MP, in some cases 21MP.

The only hardware I have available for the task is an ASUS G73JH laptop (i7-720QM, 8GB RAM, ATI Mobility Radeon HD 5870 w. 1 GB RAM).

As you can guess, my initial attempts were not successful. Using Avisynth 2.5.8 because 2.6 made MCTD crash. Starting out very basic:
Code:
Import("C:\Path\to\MCTemporalDenoise.v1.4.20.avsi")
ImageSource("I:\Path\to\DSC_%05d.jpg", 0, 99, 23.976)
ConverttoYv12()
MCTemporalDenoise(settings="low")
ConvertToRGB24()
This will open in VirtualDub, but image is black and status line at bottom reveals an out-of-memory error ("I think we have run out of memory folks!"). Using gpu=true crashes with an E_OUTOFMEMORY error. Sadly, this is just the 12MP images.

Questions:
1) Is it possible to do some memory management to prevent errors? SetMemoryMax() seems to make no difference.
2) How do I most effectively lower MCTD's memory consumption without crippling it too much?

Last edited by flyvholm; 8th February 2015 at 03:27.
flyvholm is offline   Reply With Quote
Old 8th February 2015, 03:39   #2  |  Link
poisondeathray
Registered User
 
Join Date: Sep 2007
Posts: 5,470
What are the dimensions of the image sequence ?

Can you open the image sequence up without MCTD ?

EDIT: sorry I didn't see the 12MP
poisondeathray is offline   Reply With Quote
Old 8th February 2015, 03:45   #3  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,010
Have you tried with "MCTemporalDenoise(settings="low")" commented out ?
Have you tried low setting for SetMemoryMax(), eg SetMemoryMax(256) ?

Some of the functions in Avisynth do not cope with frame bigger than about 4Kx4K eg AverageLuma() (at least up to v2.6 Alpha 5).

EDIT: @PDR, 12 -> 21 MP.
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???
StainlessS is offline   Reply With Quote
Old 8th February 2015, 06:15   #4  |  Link
flyvholm
Semper Tiro
 
flyvholm's Avatar
 
Join Date: Jan 2015
Location: Denmark
Posts: 29
The 12MP images are 4256x2832 pixels, 21MP are 5616x3744. Both resolutions open fine when MCTD is commented out. I did try SetMemoryMax(256), both with or without GPU, and it made no difference in either case.

Monitoring the task manager, VirtualDub "only" takes ~870MB of memory with a 12MP sequence opened. This is with > 50% memory free. When trying to open a 21MP sequence VirtualDub fails with an out-of-memory error when hitting 1GB (memory usage appears to be directly proportional to resolution btw). But from what I read, 32-bit Avisynth + VirtualDub should be able to use up to 2GB. So I wonder why I run short at < 1GB? With 12MP sequence open VirtualDub status bar shows:

Avisynth read error: GetFrameBuffer: Returned a VFB with a 0 data pointer! size=91527424, max=268435456, used=294194112 I think we have run out of memory folks!
flyvholm is offline   Reply With Quote
Old 8th February 2015, 07:36   #5  |  Link
Overdrive80
Anime addict
 
Overdrive80's Avatar
 
Join Date: Feb 2009
Location: Spain
Posts: 673
Try SetMemoryMax(1024)
__________________
Intel i7-6700K + Noctua NH-D15 + Z170A XPower G. Titanium + Kingston HyperX Savage DDR4 2x8GB + Radeon RX580 8GB DDR5 + ADATA SX8200 Pro 1 TB + Antec EDG750 80 Plus Gold Mod + Corsair 780T Graphite
Overdrive80 is offline   Reply With Quote
Old 8th February 2015, 11:47   #6  |  Link
Groucho2004
 
Join Date: Mar 2006
Location: Barcelona
Posts: 5,034
Quote:
Originally Posted by flyvholm View Post
The 12MP images are 4256x2832 pixels, 21MP are 5616x3744. Both resolutions open fine when MCTD is commented out. I did try SetMemoryMax(256), both with or without GPU, and it made no difference in either case.

Monitoring the task manager, VirtualDub "only" takes ~870MB of memory with a 12MP sequence opened. This is with > 50% memory free. When trying to open a 21MP sequence VirtualDub fails with an out-of-memory error when hitting 1GB (memory usage appears to be directly proportional to resolution btw). But from what I read, 32-bit Avisynth + VirtualDub should be able to use up to 2GB. So I wonder why I run short at < 1GB? With 12MP sequence open VirtualDub status bar shows:

Avisynth read error: GetFrameBuffer: Returned a VFB with a 0 data pointer! size=91527424, max=268435456, used=294194112 I think we have run out of memory folks!
It's not surprising that you get an out of memory error with that resolution and a temporal filter.
Avisynth tries to allocate memory for the number of frames requested by the filter and throws the error if there is not enough available. The memory usage you read in Taskmanager shows the current state.

One way to increase the available memory to Avisynth is to pipe the script to the client application (avs2yuv, etc). If the piping application is "Large Address Aware", up to 4 GB can be allocated on a 64 Bit OS.
I have not used MCTD but maybe there are settings with less memory usage.
Lastly - How about a non-temporal noise filter?

Last edited by Groucho2004; 8th February 2015 at 12:45.
Groucho2004 is offline   Reply With Quote
Old 8th February 2015, 18:22   #7  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,010
Perhaps try temporal Hqdn3d() or FFT3DFilter() or Spatial Vaguedenoise().

EDIT: I'm not aware of any RGB temporal denoisers to avoid colorspace conversions, anybody suggestions ?
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 8th February 2015 at 19:59.
StainlessS is offline   Reply With Quote
Old 9th February 2015, 02:27   #8  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
Join Date: Jun 2012
Posts: 1,371
What if you processed the frames in slices to lower peak memory requirements?
Say you split each into 9 smaller frames, processed them, then joined them together again?

Sounds simple, but you need overlap between the slices for a smooth result.
Here's some code for you to try (it seems to work OK in a quick test):
Code:
Assert(IsClip(Last) && IsYV12(Last), 
\ "YV12 source required for noise filter")
Assert(Last.Width>48 && Last.Height>48, 
\ "source resolution too low")

pad=8 ## size of mirror border / overlapped area as rq'd
pad2=2*pad

wid=Width
hgt=Height
wid3 = Round(wid/3.0)
hgt3 = Round(hgt/3.0)
new_wid = wid3 - (wid3 % 2)
new_hgt = hgt3 - (hgt3 % 2)

## create the 9 slices
##   (slice numbers refer to position in 'numeric keypad' aka Subtitle notation)
C7=Crop(0, 0, new_wid+pad, new_hgt+pad)
\ .MirrorBorderLTRB(pad, pad, 0, 0)
\ .Crop(0, 0, new_wid+pad2, new_hgt+pad2)

C8=Crop(new_wid-pad, 0, new_wid+pad2, new_hgt+pad)
\ .MirrorBorderLTRB(0, pad, 0, 0)
\ .Crop(0, 0, new_wid+pad2, new_hgt+pad2)

C9=Crop(2*new_wid-pad, 0, wid-2*new_wid+pad, new_hgt+pad)
\ .MirrorBorderLTRB(0, pad, pad, 0)
\ .Crop(0, 0, new_wid+pad2, new_hgt+pad2)


C4=Crop(0, new_hgt-pad, new_wid+pad, new_hgt+pad2)
\ .MirrorBorderLTRB(pad, 0, 0, 0)
\ .Crop(0, 0, new_wid+pad2, new_hgt+pad2)

C5=Crop(new_wid-pad, new_hgt-pad, new_wid+pad2, new_hgt+pad2)
\ .MirrorBorderLTRB(0, 0, 0, 0)
\ .Crop(0, 0, new_wid+pad2, new_hgt+pad2)

C6=Crop(2*new_wid-pad, new_hgt-pad, wid-2*new_wid+pad, new_hgt+pad2)
\ .MirrorBorderLTRB(0, 0, pad, 0)
\ .Crop(0, 0, new_wid+pad2, new_hgt+pad2)


C1=Crop(0, 2*new_hgt-pad, new_wid+pad, hgt-2*new_hgt+pad)
\ .MirrorBorderLTRB(pad, 0, 0, pad)
\ .Crop(0, 0, new_wid+pad2, new_hgt+pad2)

C2=Crop(new_wid-pad, 2*new_hgt-pad, new_wid+pad2, hgt-2*new_hgt+pad)
\ .MirrorBorderLTRB(0, 0, 0, pad)
\ .Crop(0, 0, new_wid+pad2, new_hgt+pad2)

C3=Crop(2*new_wid-pad, 2*new_hgt-pad, wid-2*new_wid+pad, hgt-2*new_hgt+pad)
\ .MirrorBorderLTRB(0, 0, pad, pad)
\ .Crop(0, 0, new_wid+pad2, new_hgt+pad2)

## join the 9 slices temporally - add 30 frames of filler at each end:
count=Last.FrameCount
T = C7.Trim(0, 29).Reverse + C7 + C7.Trim(count-30, 0).Reverse
\ + C8.Trim(0, 29).Reverse + C8 + C8.Trim(count-30, 0).Reverse
\ + C9.Trim(0, 29).Reverse + C9 + C9.Trim(count-30, 0).Reverse
\ + C4.Trim(0, 29).Reverse + C4 + C4.Trim(count-30, 0).Reverse
\ + C5.Trim(0, 29).Reverse + C5 + C5.Trim(count-30, 0).Reverse
\ + C6.Trim(0, 29).Reverse + C6 + C6.Trim(count-30, 0).Reverse
\ + C1.Trim(0, 29).Reverse + C1 + C1.Trim(count-30, 0).Reverse
\ + C2.Trim(0, 29).Reverse + C2 + C2.Trim(count-30, 0).Reverse
\ + C3.Trim(0, 29).Reverse + C3 + C3.Trim(count-30, 0).Reverse
#return T 

## x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x 
## NOTE: if memory is still a problem, split the script at this point:
## create a lossless dub of the above video, then continue
## with the rest of this script using the dub.
#T = AviSource("lossless.avi")

## do noise processing etc
## (I don't have MCTemporalDenoise handy, but here is where it would go)
#T = T.hqdn3d(0, 0, 35, 25, 40) 
#T = T.TemporalSoften(3, 28, 36, 28, 2) 


## extract the slices from the processed video:
count2=framecount+60
P7=T.Trim(30,          -framecount)
P8=T.Trim(30+count2,   -framecount)
P9=T.Trim(30+2*count2, -framecount)

P4=T.Trim(30+3*count2, -framecount)
P5=T.Trim(30+4*count2, -framecount)
P6=T.Trim(30+5*count2, -framecount)

P1=T.Trim(30+6*count2, -framecount)
P2=T.Trim(30+7*count2, -framecount)
P3=T.Trim(30+8*count2, -framecount)

## crop off the padding
P7=P7.Crop(pad, pad, new_wid,       new_hgt)
P8=P8.Crop(pad, pad, new_wid,       new_hgt)
P9=P9.Crop(pad, pad, wid-2*new_wid, new_hgt)

P4=P4.Crop(pad, pad, new_wid,       new_hgt)
P5=P5.Crop(pad, pad, new_wid,       new_hgt)
P6=P6.Crop(pad, pad, wid-2*new_wid, new_hgt)

P1=P1.Crop(pad, pad, new_wid,       hgt-2*new_hgt)
P2=P2.Crop(pad, pad, new_wid,       hgt-2*new_hgt)
P3=P3.Crop(pad, pad, wid-2*new_wid, hgt-2*new_hgt)

## reconstruct the frame from slices and exit:
StackVertical(
\  StackHorizontal(P7, P8, P9),
\  StackHorizontal(P4, P5, P6),
\  StackHorizontal(P1, P2, P3)
\ )
return Last


##################################
#
function MirrorBorderLTRB(clip C, 
\   int "bdrLt", int "bdrTp", int "bdrRt", int "bdrBt")
{
    bdrLt = Max(2, Default(bdrLt, 16))
    bdrTp = Max(2, Default(bdrTp, 16))
    bdrRt = Max(2, Default(bdrRt, 16))
    bdrBt = Max(2, Default(bdrBt, 16))

    bdrLt = Max(0, bdrLt - (bdrLt % 2))
    bdrTp = Max(0, bdrTp - (bdrTp % 2))
    bdrRt = Max(0, bdrRt - (bdrRt % 2))
    bdrBt = Max(0, bdrBt - (bdrBt % 2))

    CL = C.Crop(0, 0, bdrLt, 0)
    CR = C.Crop(C.Width-bdrRt, 0, bdrRt, 0)

    C2 = (bdrLt==0) 
    \  ? (bdrRt==0) 
    \     ? C
    \     : StackHorizontal(C, CR.FlipHorizontal)
    \  : (bdrRt==0)
    \     ? StackHorizontal(CL.FlipHorizontal, C)
    \     : StackHorizontal(CL.FlipHorizontal, C, CR.FlipHorizontal)

    CT = C2.Crop(0, 0, 0, bdrTp) 
    CB = C2.Crop(0, C2.Height-bdrBt, 0, bdrBt)

    C3 = (bdrTp==0) 
    \  ? (bdrBt==0) 
    \     ? C2
    \     : StackVertical(C2, CB.FlipVertical)
    \  : (bdrBt==0)
    \     ? StackVertical(CT.FlipVertical, C2)
    \     : StackVertical(CT.FlipVertical, C2, CB.FlipVertical)

    return C3
}

__END__

Last edited by raffriff42; 9th February 2015 at 02:49. Reason: typo
raffriff42 is offline   Reply With Quote
Old 9th February 2015, 04:49   #9  |  Link
flyvholm
Semper Tiro
 
flyvholm's Avatar
 
Join Date: Jan 2015
Location: Denmark
Posts: 29
Thanks for all the input! I tried SetMemoryMax() with values from 256 to 2048. It doesn't appear to make any difference in memory consumption.

I also tried using avs2yuv to pipe to x264 (64-bit). I get the same Avisynth out-of-memory error when hitting ~1GB of memory usage. I've seen VirtualDub take up to about 1.5GB of memory for something else (that crashed too ), so I don't know why it seems impossible to allocate more than 1 GB for this task.

I'm working with nighttime timelapse footage. It needs strong noise reduction and mostly works quite favorably with temporal filters, so I do want to take advantage of that. I tried FFT3DFilter() on its own. I suspect that's the big memory hog inside MCTD, and it crashes (access violation) if I use the MCTD "high" settings. I can open the 12MP image sequence with default settings, but once I try to encode VirtualDub just hangs.

Hqdn3d() appears to be a whole different beast. Opens even 21MP image sequences fine and processing is fast! It looks like it will do the job in at least some cases, but I suspect it will fall short in others. We'll see, it's at least something to get me started.

Also, I'm able to open 1080p footage with MCTD, so even though it's not ideal it's an option to use that on the finished video.

@raffriff42: That is awesome. I was thinking of that, but being new to Avisynth it would have taken a lot of effort to get all of that figured out. Unsure of success, I wouldn't even have attempted. But what an excellent illustration of the power of knowing how to use scripting. With the rising popularity of 4K (and timelapse for that matter) I could see this come in handy for many others. I haven't tested yet, but I will do that and return with results (or questions ).
flyvholm is offline   Reply With Quote
Old 9th February 2015, 05:13   #10  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 11,010
Yeh nice work rr42 - ever the show off

If Hqdn3d() works ok, then there is another filter (that I have never actually tried) but is also very fast, and because it is very fast I suspect
that it may too work ok (fast == less memory usage - Probably), FluxSmooth().
Might also be worth a try.

EDIT: Fluxsmooth: http://avisynth.nl/index.php/FluxSmooth
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 9th February 2015 at 10:27.
StainlessS is offline   Reply With Quote
Old 9th February 2015, 05:35   #11  |  Link
Stereodude
Registered User
 
Join Date: Dec 2002
Location: Region 0
Posts: 1,436
Quote:
Originally Posted by flyvholm View Post
I'm new to Avisynth, jumping in because I'm looking to do some noise reduction. I'm working with DSLR timelapse image sequences that I'm making a film from, importing the sequences in Adobe After Efffects for post processing (such as pan/zoom). For best results I should apply the noise reduction to the original image sequences where most of the image is static from frame to frame, and due to the further processing I generally can't reduce the resolution before denoising. Images are mostly 12MP, in some cases 21MP.
When I suggested MCTD to you I didn't realize you were panning and zooming still images. I thought you had HD video footage. AFAIK MCTD isn't well suited for noise reduction of still images like you have. It works by comparing frames temporally for what's changing (grain & noise). It does work well on the output footage from After Effects (at least in your title sample).

The Noise Ninja Photoshop plug-in worked pretty well at removing noise from still photos when I played with it in several years ago. It was highly customizable.
Stereodude is offline   Reply With Quote
Old 9th February 2015, 06:50   #12  |  Link
flyvholm
Semper Tiro
 
flyvholm's Avatar
 
Join Date: Jan 2015
Location: Denmark
Posts: 29
Thanks for continued suggestions - I won't be running out of things to experiment with any time soon.

Quote:
Originally Posted by Stereodude View Post
AFAIK MCTD isn't well suited for noise reduction of still images like you have. It works by comparing frames temporally for what's changing (grain & noise).
Actually the still images are highly suitable for a temporal noise filter because most of the image is static from frame to frame. My guess is that you pointed me right to the filter that will give me the highest quality output - if only I can avoid running out of memory. rr42's code above may just be the tool I need to get there.

EDIT: @Stereodude: I think I see... the title video we've been playing with looks like it's panning across a single image, but it's actually an image sequence (you can tell because the noise changes from frame to frame).

Last edited by flyvholm; 9th February 2015 at 06:59.
flyvholm is offline   Reply With Quote
Old 9th February 2015, 10:02   #13  |  Link
Groucho2004
 
Join Date: Mar 2006
Location: Barcelona
Posts: 5,034
Quote:
Originally Posted by flyvholm View Post
I also tried using avs2yuv to pipe to x264 (64-bit). I get the same Avisynth out-of-memory error when hitting ~1GB of memory usage.
Make sure that you are using a avs2yuv version that has been linked with the "LARGE_ADDRESS_AWARE" flag. Here is the one I use.
Groucho2004 is offline   Reply With Quote
Old 10th February 2015, 11:27   #14  |  Link
flyvholm
Semper Tiro
 
flyvholm's Avatar
 
Join Date: Jan 2015
Location: Denmark
Posts: 29
Quote:
Originally Posted by Groucho2004 View Post
Make sure that you are using a avs2yuv version that has been linked with the "LARGE_ADDRESS_AWARE" flag. Here is the one I use.
That helped - I see avs2yuv grabbing > 3GB of memory now. The process still fails, producing empty output and the following errors:

avs2yuv "input.avs" -raw - | x264 --crf 20 --output "output.mkv" - 4256x2832
raw [error]: raw input requires a resolution.
x264 [error]: could not open input file '-'
error: wrote only 17399278 of 18079488 bytes

AFAICT this syntax works for others. What am I missing?
flyvholm is offline   Reply With Quote
Old 10th February 2015, 11:42   #15  |  Link
Groucho2004
 
Join Date: Mar 2006
Location: Barcelona
Posts: 5,034
Quote:
Originally Posted by flyvholm View Post
That helped - I see avs2yuv grabbing > 3GB of memory now. The process still fails, producing empty output and the following errors:

avs2yuv "input.avs" -raw - | x264 --crf 20 --output "output.mkv" - 4256x2832
raw [error]: raw input requires a resolution.
x264 [error]: could not open input file '-'
error: wrote only 17399278 of 18079488 bytes

AFAICT this syntax works for others. What am I missing?
I'm using something like this:
Code:
avs2yuv "script.avs" -o - | x264 - --crf 20 --frames 1000 --output "output.mkv" --demuxer y4m
Before you feed the script to the encoder you could run it through AVSMeter to check the memory usage and if it runs through without crashing.

Last edited by Groucho2004; 10th February 2015 at 11:47.
Groucho2004 is offline   Reply With Quote
Old 10th February 2015, 13:45   #16  |  Link
Stereodude
Registered User
 
Join Date: Dec 2002
Location: Region 0
Posts: 1,436
Post your script.avs file.
Stereodude is offline   Reply With Quote
Old 14th February 2015, 03:41   #17  |  Link
flyvholm
Semper Tiro
 
flyvholm's Avatar
 
Join Date: Jan 2015
Location: Denmark
Posts: 29
The sample script in the first post (minus the RGB conversion) would fail. However, with the --demuxer option set instead of resolution (as suggested by Groucho2004) the process completed. So that is potentially one way to work around the memory issue.

Admittedly, this topic is of much less interest to me after I was pointed to Neat Video. Getting that as a plugin for After Effects means that I can easily integrate it in my project files (i.e. no need to render intermediate, denoised footage), I get live previews as I tweak settings and I avoid color space conversions. On top of that it seems to work extremely well. I think I'd be hard pressed to produce as good results with Avisynth plugins, so for me Neat Video was the perfect solution and well worth the price.

But. I am really grateful for the help I received here, and in particular I think the script posted by raffriff42 is pretty cool, so I would like to make that work because it could come in handy for others. I did manage to open a 12MP image sequence in VirtualDub, but the slices were garbled. And now somehow MCTD can't find FFT3DFilter anymore. I'm off for the weekend, but will try to work out the kinks when I get back. :-)
flyvholm is offline   Reply With Quote
Old 14th February 2015, 19:56   #18  |  Link
raffriff42
Retried Guesser
 
raffriff42's Avatar
 
Join Date: Jun 2012
Posts: 1,371
Quote:
Originally Posted by flyvholm View Post
I think the script posted by raffriff42 is pretty cool, so I would like to make that work because it could come in handy for others. I did manage to open a 12MP image sequence in VirtualDub, but the slices were garbled.
Thanks, I hope it works for you.
Try removing the Reverse calls; they require perfect frame accuracy when decoding in reverse, which some codecs have trouble doing. These calls are probably overkill anyway...
Code:
<...>
#T = C7.Trim(0, 29).Reverse + C7 + C7.Trim(count-30, 0).Reverse
#\ + C8.Trim(0, 29).Reverse + C8 + C8.Trim(count-30, 0).Reverse
#\ + C9.Trim(0, 29).Reverse + C9 + C9.Trim(count-30, 0).Reverse
#\ + C4.Trim(0, 29).Reverse + C4 + C4.Trim(count-30, 0).Reverse
#\ + C5.Trim(0, 29).Reverse + C5 + C5.Trim(count-30, 0).Reverse
#\ + C6.Trim(0, 29).Reverse + C6 + C6.Trim(count-30, 0).Reverse
#\ + C1.Trim(0, 29).Reverse + C1 + C1.Trim(count-30, 0).Reverse
#\ + C2.Trim(0, 29).Reverse + C2 + C2.Trim(count-30, 0).Reverse
#\ + C3.Trim(0, 29).Reverse + C3 + C3.Trim(count-30, 0).Reverse
T = C7 + C8 + C9 + C4 + C5 + C6 + C1 + C2 + C3
<...>
#count2=framecount+60
#P7=T.Trim(30,          -framecount)
#P8=T.Trim(30+count2,   -framecount)
#P9=T.Trim(30+2*count2, -framecount)
#
#P4=T.Trim(30+3*count2, -framecount)
#P5=T.Trim(30+4*count2, -framecount)
#P6=T.Trim(30+5*count2, -framecount)
#
#P1=T.Trim(30+6*count2, -framecount)
#P2=T.Trim(30+7*count2, -framecount)
#P3=T.Trim(30+8*count2, -framecount)
#
P7=T.Trim(0 -framecount)
P8=T.Trim(framecount    -framecount)
P9=T.Trim(2*framecount, -framecount)

P4=T.Trim(3*framecount, -framecount)
P5=T.Trim(4*framecount, -framecount)
P6=T.Trim(5*framecount, -framecount)

P1=T.Trim(6*framecount, -framecount)
P2=T.Trim(7*framecount, -framecount)
P3=T.Trim(8*framecount, -framecount)

Last edited by raffriff42; 15th February 2015 at 04:35. Reason: missing /code tag
raffriff42 is offline   Reply With Quote
Old 18th February 2015, 03:03   #19  |  Link
flyvholm
Semper Tiro
 
flyvholm's Avatar
 
Join Date: Jan 2015
Location: Denmark
Posts: 29
That did the trick. There were a few additional tweaks to do. MCTD requires mod-4, and the input must initially be padded to be mod-12 to create a 3x3 grid with equal mod-4 slices. Also, the MirrorBorderLTRB() function was always adding padding on all sides, which doesn't appear to be what you intended. With that fixed the output did not need additional cropping. Below is a modified script that gave me "correct" results. One caveat is that we had to remove the filler frames at the start and end to avoid garbled output, but for a temporal filter like MCTD they ought to be included. It wasn't a problem for the footage I tested on, but in other cases it probably would be.

Code:
Assert(IsClip(Last) && IsYV12(Last), 
\ "YV12 source required for noise filter")
Assert(Last.Width>48 && Last.Height>48, 
\ "source resolution too low")

#The clip will be split into 9 slices (3x3 grid). Slices will be joined temporally,
#then fed to a filter for processing. In this case the filter is MCTD and requires
#input to be mod-4. First task is then to add padding to the clip so it can be split
#into 9 equal slices that are mod-4.
mod = 4
FrmPadTp = 3*mod - (Height % (3*mod))
FrmPadRt = 3*mod - (Width % (3*mod))
MirrorBorderLTRB(0, FrmPadTp, FrmPadRt, 0)

pad=8 ## size of mirror border / overlapped area as rq'd
pad2=2*pad

wid=Width
hgt=Height
wid3 = Round(wid/3.0)
hgt3 = Round(hgt/3.0)
new_wid = wid3 - (wid3 % mod)
new_hgt = hgt3 - (hgt3 % mod)

## create the 9 slices
##   (slice numbers refer to position in 'numeric keypad' aka Subtitle notation)
C7=Crop(0, 0, new_wid+pad, new_hgt+pad)
\ .MirrorBorderLTRB(pad, pad, 0, 0, mod)

C8=Crop(new_wid-pad, 0, new_wid+pad2, new_hgt+pad)
\ .MirrorBorderLTRB(0, pad, 0, 0, mod)

C9=Crop(2*new_wid-pad, 0, wid-2*new_wid+pad, new_hgt+pad)
\ .MirrorBorderLTRB(0, pad, pad, 0, mod)


C4=Crop(0, new_hgt-pad, new_wid+pad, new_hgt+pad2)
\ .MirrorBorderLTRB(pad, 0, 0, 0, mod)

C5=Crop(new_wid-pad, new_hgt-pad, new_wid+pad2, new_hgt+pad2)
\ .MirrorBorderLTRB(0, 0, 0, 0, mod)

C6=Crop(2*new_wid-pad, new_hgt-pad, wid-2*new_wid+pad, new_hgt+pad2)
\ .MirrorBorderLTRB(0, 0, pad, 0, mod)


C1=Crop(0, 2*new_hgt-pad, new_wid+pad, hgt-2*new_hgt+pad)
\ .MirrorBorderLTRB(pad, 0, 0, pad, mod)

C2=Crop(new_wid-pad, 2*new_hgt-pad, new_wid+pad2, hgt-2*new_hgt+pad)
\ .MirrorBorderLTRB(0, 0, 0, pad, mod)

C3=Crop(2*new_wid-pad, 2*new_hgt-pad, wid-2*new_wid+pad, hgt-2*new_hgt+pad)
\ .MirrorBorderLTRB(0, 0, pad, pad, mod)

## Join the 9 slices temporally. This may cause problems with filters
## that mix data from adjacent frames unless filler frames are added
## at start and end.
T = C7 + C8 + C9 + C4 + C5 + C6 + C1 + C2 + C3
#return T 

## x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x 
## NOTE: if memory is still a problem, split the script at this point:
## create a lossless dub of the above video, then continue
## with the rest of this script using the dub.
#T = AviSource("lossless.avi")

## do noise processing etc
T = T.MCTemporalDenoise(settings="medium")

## extract the slices from the processed video:
P7=T.Trim(0,		-framecount)
P8=T.Trim(framecount,	-framecount)
P9=T.Trim(2*framecount, -framecount)

P4=T.Trim(3*framecount, -framecount)
P5=T.Trim(4*framecount, -framecount)
P6=T.Trim(5*framecount, -framecount)

P1=T.Trim(6*framecount, -framecount)
P2=T.Trim(7*framecount, -framecount)
P3=T.Trim(8*framecount, -framecount)

## crop off the padding
P7=P7.Crop(pad, pad, new_wid,       new_hgt)
P8=P8.Crop(pad, pad, new_wid,       new_hgt)
P9=P9.Crop(pad, pad, wid-2*new_wid, new_hgt)

P4=P4.Crop(pad, pad, new_wid,       new_hgt)
P5=P5.Crop(pad, pad, new_wid,       new_hgt)
P6=P6.Crop(pad, pad, wid-2*new_wid, new_hgt)

P1=P1.Crop(pad, pad, new_wid,       hgt-2*new_hgt)
P2=P2.Crop(pad, pad, new_wid,       hgt-2*new_hgt)
P3=P3.Crop(pad, pad, wid-2*new_wid, hgt-2*new_hgt)

## reconstruct the frame from slices
StackVertical(
\  StackHorizontal(P7, P8, P9),
\  StackHorizontal(P4, P5, P6),
\  StackHorizontal(P1, P2, P3)
\ )

#Finally, remove the padding that was added before making slices
Crop(0, FrmPadTp, -FrmPadRt, 0)

return Last


##################################
#
function MirrorBorderLTRB(clip C, 
\   int "bdrLt", int "bdrTp", int "bdrRt", int "bdrBt", int "mod")
{

    Defined(mod) ? Eval("""

      bdrLt = ((bdrLt % mod) > 0) ? bdrLt + mod - (bdrLt % mod) : bdrLt
      bdrTp = ((bdrTp % mod) > 0) ? bdrTp + mod - (bdrTp % mod) : bdrTp
      bdrRt = ((bdrRt % mod) > 0) ? bdrRt + mod - (bdrRt % mod) : bdrRt
      bdrBt = ((bdrBt % mod) > 0) ? bdrBt + mod - (bdrBt % mod) : bdrBt

    """) : NOP

    bdrLt > 0 ? Eval("""CL = C.Crop(0, 0, bdrLt, 0)""") : NOP
    bdrRt > 0 ? Eval("""CR = C.Crop(C.Width-bdrRt, 0, bdrRt, 0)""") : NOP

    C2 = (bdrLt==0) 
    \  ? (bdrRt==0) 
    \     ? C
    \     : StackHorizontal(C, CR.FlipHorizontal)
    \  : (bdrRt==0)
    \     ? StackHorizontal(CL.FlipHorizontal, C)
    \     : StackHorizontal(CL.FlipHorizontal, C, CR.FlipHorizontal)

    bdrTp > 0 ? Eval("""CT = C2.Crop(0, 0, 0, bdrTp)""") : NOP
    bdrBt > 0 ? Eval("""CB = C2.Crop(0, C2.Height-bdrBt, 0, bdrBt)""") : NOP

    C3 = (bdrTp==0) 
    \  ? (bdrBt==0) 
    \     ? C2
    \     : StackVertical(C2, CB.FlipVertical)
    \  : (bdrBt==0)
    \     ? StackVertical(CT.FlipVertical, C2)
    \     : StackVertical(CT.FlipVertical, C2, CB.FlipVertical)

    return C3
}

__END__
Unfortunately, in practice I can't use it myself. MCTD on 12MP+ images is so slow that it just isn't plausible. But maybe some others will be able to use this neat little trick as a workaround for memory problems.
flyvholm is offline   Reply With Quote
Reply

Tags
avisynth, mctd, memory management

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT +1. The time now is 06:51.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2024, vBulletin Solutions Inc.