Log in

View Full Version : Minimize the effect of "old" line on a cartoon


Darkkurama
29th July 2009, 16:49
Hi, I encoded a DVD of an old cartoon to x264 (with megui an it's tools [d2v, etc]). The quality is excellent, but unfortunately, the DVD source has a white "line" or a line with artifacts every time the frames change to another scene (for example, a character is moving to the kitchen, and a few seconds later the video scene goes to outside the house. The frame between those scenes, have a line with artifacts)

I'd want to minimize the effect in those frames (that garbage line appears only in 1 frame), but not deleting the damaged frame because my audio can get unsynchronized with the video.

I link here the frames which have that line:

http://img21.imageshack.us/img21/5420/snapshot20090729173820.jpg

http://img21.imageshack.us/img21/5145/snapshot20090729173834.jpg

http://img43.imageshack.us/img43/8164/snapshot20090729173906.jpg

that thing is in every frame that is between two scenes, and so, they are a lot.

Is there a solution for my problem?

thanks!

JohannesL
29th July 2009, 17:19
Letterbox() the bottom pixels.

Darkkurama
29th July 2009, 18:02
But I don't want to add a black line to the bottom... Should I crop that part?

I cropped my video, and it's 696x568 (AR 1:1). Is there any problem if I crop the VHS line? I've read that if you get a unusual resolution, some players could present error, is this true?

thanks.

Keiyakusha
29th July 2009, 18:07
But I don't want to add a black line to the bottom... Should I crop that part?

I cropped my video, and it's 696x568 (AR 1:1). Is there any problem if I crop the VHS line? I've read that if you get a unusual resolution, some players could present error, is this true?

thanks.

This is depends on what do you mean by "unusual resolution". I don't see why your current resolution is usual... If you crop 8 pixels from the bottom, it will be even more usual because it will be mod16 ^_^

Darkkurama
29th July 2009, 18:24
Ok then, I'll crop 8 px from the bottom. thank you very much ^^

PD: If you know other ways to achieve this "fix" to this video, let me know ^^

Lyris
29th July 2009, 18:29
Hi, I encoded a DVD of an old cartoon to x264 (with megui an it's tools [d2v, etc]). The quality is excellent, but unfortunately, the DVD source has a white "line" or a line with artifacts every time the frames change to another scene (for example, a character is moving to the kitchen, and a few seconds later the video scene goes to outside the house. The frame between those scenes, have a line with artifacts)
The reason for this: your source is hand-edited. The gunk you see at the top of a new scene is probably film cement. Japan seemed to persist with this technique for TV shows for longer than Western countries.

Perhaps someone could write a filter that uses data from the previous frame (or the next frame, if the visible splice is at the start of a scene) to cover over this.

The splices look like the least of that source's worries, though...

Darkkurama
29th July 2009, 18:51
The reason for this: your source is hand-edited. The gunk you see at the top of a new scene is probably film cement. Japan seemed to persist with this technique for TV shows for longer than Western countries.

Perhaps someone could write a filter that uses data from the previous frame (or the next frame, if the visible splice is at the start of a scene) to cover over this.

The splices look like the least of that source's worries, though...

Thanks for the info!

But is really annoying for the eye to see this thing flashing all the time =P

Darkkurama

m3mbran3
30th July 2009, 07:14
Cropping it out is probably the best solution. It's not as if the most critical information is going to be at the bottom of the frame so you are not really losing anything.

You could try playing around with MVTools to see if you can use the information from previous frames, I use something similar to remove dirt from film transfers based on the RemoveGrain and RemoveDirt plugins. My code probably wont work for your situation but you may be able to adapt it.


function dedirt(clip, int limit)
{
super = clip.MSuper(pel=2)
backward_vec2 = MAnalyse(super, isb = true, delta = 2, overlap=4)
backward_vec1 = MAnalyse(super, isb = true, delta = 1, overlap=4)
forward_vec1 = MAnalyse(super, isb = false, delta = 1, overlap=4)
forward_vec2 = MAnalyse(super, isb = false, delta = 2, overlap=4)
backward_motion2 = MFlow(clip, super, backward_vec2)
backward_motion1 = MFlow(clip, super, backward_vec1)
forward_motion1 = MFlow(clip, super, forward_vec1)
forward_motion2 = MFlow(clip, super, forward_vec2)
clp=interleave(forward_motion2, forward_motion1, clip, backward_motion1, backward_motion2)
#remove dirt here
clp=clp.RemoveDirt(limit)
#clp=clp.despot()
clp=clp.SelectEvery(5,2)
return clp
}

function RemoveDirt(clip input, int limit)
{
clensed=Clense(input)
alt=input.RemoveGrain(mode=2)
return RestoreMotionBlocks(clensed,input,alternative=alt,pthreshold=4,cthreshold=6, gmthreshold=40,dist=1,dmode=2,debug=false,noise=limit,noisy=16)
}

TheRyuu
30th July 2009, 08:23
freezeframe() ?

Darkkurama
30th July 2009, 15:21
Cropping it out is probably the best solution. It's not as if the most critical information is going to be at the bottom of the frame so you are not really losing anything.

You could try playing around with MVTools to see if you can use the information from previous frames, I use something similar to remove dirt from film transfers based on the RemoveGrain and RemoveDirt plugins. My code probably wont work for your situation but you may be able to adapt it.


function dedirt(clip, int limit)
{
super = clip.MSuper(pel=2)
backward_vec2 = MAnalyse(super, isb = true, delta = 2, overlap=4)
backward_vec1 = MAnalyse(super, isb = true, delta = 1, overlap=4)
forward_vec1 = MAnalyse(super, isb = false, delta = 1, overlap=4)
forward_vec2 = MAnalyse(super, isb = false, delta = 2, overlap=4)
backward_motion2 = MFlow(clip, super, backward_vec2)
backward_motion1 = MFlow(clip, super, backward_vec1)
forward_motion1 = MFlow(clip, super, forward_vec1)
forward_motion2 = MFlow(clip, super, forward_vec2)
clp=interleave(forward_motion2, forward_motion1, clip, backward_motion1, backward_motion2)
#remove dirt here
clp=clp.RemoveDirt(limit)
#clp=clp.despot()
clp=clp.SelectEvery(5,2)
return clp
}

function RemoveDirt(clip input, int limit)
{
clensed=Clense(input)
alt=input.RemoveGrain(mode=2)
return RestoreMotionBlocks(clensed,input,alternative=alt,pthreshold=4,cthreshold=6, gmthreshold=40,dist=1,dmode=2,debug=false,noise=limit,noisy=16)
}


Thanks for sharing your code! but I'm sure I can't modify or adapt it at the moment: I don't understand anything (sorry xD) of the code. But I would want to understand it, is there any guide or anything that clarify the understanding of those codes and the use of them?. I'm a newbie, sorry :(

freezeframe() ?

Thanks, but that would be a hard work, because there are many glitched frames.

:thanks::thanks:, and sorry for my english

m3mbran3
30th July 2009, 16:47
I don't really understand it either, it's basically just the demo from the RemoveGrain website updated to use mvtools2. As far as I can tell it takes the data from 5 frames of video and if it finds an area affected by dirt then it replaces that data with the data from another frame. If your problem only occurs on 1 frame every so often then it should work, otherwise I would just crop it out.

Didée
30th July 2009, 17:12
Have a look at "SCSelect" from RemoveDirt.dll.

See here (http://forum.doom9.org/showthread.php?p=1140719#post1140719) / here (http://forum.doom9.org/showthread.php?p=1206869#post1206869)

Darkkurama
30th July 2009, 19:16
Wow! It's really amazing that .dll!

I applied it with a dfactor of 4.0, and it's almost perfect (the effect got "minimized", but not eliminated at all.)

My avs:


LoadPlugin("C:\Program Files (x86)\AviSynth 2.5\plugins\warpsharp.dll")
Load_Stdcall_Plugin("C:\Program Files (x86)\megui\tools\yadif\yadif.dll")
LoadPlugin("C:\Program Files (x86)\AviSynth 2.5\plugins\RemoveDirtSSE2.dll")

source = DGDecode_mpeg2source("D:\New\DVD.d2v", info=3).ColorMatrix(hints=true, interlaced=true, threads=0).Yadif(order=1).WarpSharp(depth=135, blur=4, bump=128)
prev = source.selectevery(1,-1)
next = source.selectevery(1,1)
source.SCSelect(next,prev,source,dfactor=4.0)
mergechroma(blur(1.3))


With this and a little crop, I think I'm done with it. By the way, I've read that there's a "change" for "motion-compensated" sources. Can anyone explain what's that for?

I've detected a "frameskip" when the dfactor is 2.0, but with 4.0 It's OK, What causes that frameskip (It's like the FPS have changed or something like that)?

Thanks :)

Lyris
26th April 2013, 17:16
Sorry to bump this guys, I have a source that has visible splices at the bottom of the last frame in a scene, and at the top of the first frame in the next.

Fortunately, the splices are not so high, and the motion content of the film is quite... serene. One thing I would like to do is replace only the affected portions of the frame, rather than removing the entire frame.

So I wrote this script which will only replace a portion of the frame. Can anyone suggest how I could add edge-feathering to this? Better yet would be edge feathering and some sort of motion compensation, but that's tricky... anyway, right now the replaced portions are quite obvious.

#Replace the top 150px of the first frame in each scene with a duplicate of frame 2 in that scene.
#Also replace the bottom 150px of the last frame in a scene with a duplicate of the frame before it.
#needs edge feathering

source=last

prev = source.selectevery(1,-1) #Select the last frame before a scene-cut.
prevSourceKeep = source.crop(0,0,-0,-150) #Keep the previous image but cut only the bottom 150px.
prevCrop = prev.crop(0,930,-0,-0) #The portion with the splicemarks to be replaced.
#
#The "930" refers to cropping a 1080p height image: 1080 - the 150 we cropped = 930.
#
prevCombine = stackVertical(prevSourceKeep, prevCrop)

next = source.selectevery(1,1) #select the first frame of a scene.
nextSourceKeep = source.crop(0,160,-0,-0) #Keep the next image but cut only the top 160px.
nextCrop = next.crop(0,0,-0,-920) #The portion with the splicemarks to be replaced.
nextCombine = stackVertical(nextCrop, nextSourceKeep)

source.SCSelect(nextCombine,prevCombine,source,dfactor=2.0)

Unfortunately I can't provide a sample (I know, I know!)

Lyris
26th April 2013, 18:09
Here's an alternative: can anyone provide me with a script which will output only the frames surrounding the scenecuts? I could then output them as TIFFs with ImageWriter and do some work on them with Photoshop macros.

StainlessS
27th April 2013, 23:55
@Lyris


# Script to create command files for FrameSelect/FrameReplace, Last frame before scene change & 1st frame after.
# Can examine metrics going backwards/forwards but output command files will be rubbish.
# Making command files, Reload AVS if was jumping about, MUST play all the way through, NO JUMPING ABOUT, FORWARD ONLY.
AVISource("D:\avs\test.avi").Killaudio()
#
SCThresh=80.0 # Scene change Threshold (about 80.0 seems very good for high/low motion).
SHOW=True # Show metrics
FAST=True # AssumeFPS 250.0
EXTRA=True # Create Extra command files for frame before PRE and frame after POST (for fixing PRE and POST in eg PhotoShop)
#
Top=32 # Crud (edges ignored in differencing)
Bot=32
Lft=32
Rgt=32
#
fn_Pre = "Pre.Txt" # FrameSelect/FrameReplace Command file for Last frame before scene change
fn_Post = "Post.Txt" # FrameSelect/FrameReplace Command file for 1st frame after scene change
fn_PrePre = "PrePre.Txt" # FrameSelect/FrameReplace Command file for frame BEFORE Last frame before scene change
fn_PostPost = "PostPost.Txt"# FrameSelect/FrameReplace Command file for frame AFTER 1st frame after scene change
(Exist(fn_Pre)) ? RT_FileDelete(fn_Pre) : NOP
(Exist(fn_Post)) ? RT_FileDelete(fn_Post) : NOP
(Exist(fn_PrePre)) ? RT_FileDelete(fn_PrePre) : NOP
(Exist(fn_PostPost))? RT_FileDelete(fn_PostPost) : NOP

B=0.0 C=0.0 sc=False Prev=-2 # Init vars

CondS="""
# If jumped about, get values for Previous frame, else keep same.
A=(current_frame!=Prev+1) ? RT_LumaSceneChange(Last,Last,n=current_frame-2,n2=current_frame-1,x=Lft,y=Top,w=-Rgt,h=-Bot) : A
B=(current_frame!=Prev+1) ? RT_LumaSceneChange(Last,Last,n=current_frame-1,n2=current_frame,x=Lft,y=Top,w=-Rgt,h=-Bot) : B
C=(current_frame!=Prev+1) ? RT_LumaSceneChange(Last,Last,n=current_frame,n2=current_frame+1,x=Lft,y=Top,w=-Rgt,h=-Bot) : C
psc=(current_frame!=Prev+1) ? (B>=SCThresh && A<SCThresh && C<SCThresh) : sc
# Pass the parcel
A=B
B=C
C=RT_LumaSceneChange(Last,Last,n=current_frame+1,n2=current_frame+2,x=Lft,y=Top,w=-Rgt,h=-Bot) # diff(next,next+1)
sc=(B>=SCThresh && A<SCThresh && C<SCThresh)
(SHOW) ? Subtitle(String(current_frame)+"] "+String(A,"%6.2f")+" "+String(B,"%6.2f")+" "+String(C,"%6.2f")) :NOP
(sc) ? RT_TxtWriteFile(String(current_frame),fn_Pre ,append=true) : NOP
(sc&&EXTRA) ? RT_TxtWriteFile(String(current_frame-1),fn_PrePre ,append=true) : NOP
(sc&&SHOW) ? Subtitle("END OF SCENE",align=1,size=30) : NOP
(psc) ? RT_TxtWriteFile(String(current_frame),fn_Post,append=true) : NOP
(psc&&EXTRA)? RT_TxtWriteFile(String(current_frame+1),fn_PostPost,append=true) : NOP
(psc&&SHOW) ? Subtitle("START OF SCENE",align=3,size=30) : NOP
Prev=current_frame
Return Last
"""
ScriptClip(CondS)
(FAST) ? AssumeFPS(250.0) : NOP
return Last.ConvertToRGB32()



# Script to Extract Last frame before scene change
AVISource("D:\avs\test.avi")
fn_Pre = "Pre.Txt"
SHOW=False
FrameSelect(cmd=Fn_Pre,show=SHOW)
ConvertToRGB24()
ImageWriter("PRE_",type="BMP")



# Script to Extract 1st frame after scene change
AVISource("D:\avs\test.avi")
fn_Post = "Post.Txt"
SHOW=False
FrameSelect(cmd=Fn_Post,show=SHOW)
ConvertToRGB24()
ImageWriter("POST_",type="BMP")



# Script to Extract the frame BEFORE the Last frame before scene change
AVISource("D:\avs\test.avi")
fn_PrePre = "PrePre.Txt"
SHOW=False
FrameSelect(cmd=Fn_PrePre,show=SHOW)
ConvertToRGB24()
ImageWriter("PREPRE_",type="BMP")



# Script to Extract the frame AFTER the 1st frame after scene change
AVISource("D:\avs\test.avi")
fn_PostPost = "PostPost.Txt"
SHOW=False
FrameSelect(cmd=Fn_PostPost,show=SHOW)
ConvertToRGB24()
ImageWriter("POSTPOST_",type="BMP")



# Script to replace frames back into original clip.
C=AVISource("D:\avs\test.avi")
SHOW=True
PRE_N =RT_WriteFileList("PRE_*.BMP","TMP.LIST") # Pre Frames to get
POST_N =RT_WriteFileList("POST_*.BMP","TMP.LIST") # Post Frames to get
RT_FileDelete("TMP.LIST")
Assert(PRE_N==POST_N,"pre-post frame count mismatch")
PRE=ImageSource("PRE_%06d.BMP",start=0,end=PRE_N-1).ConvertToYV12()
POST=ImageSource("POST_%06d.BMP",start=0,end=POST_N-1).ConvertToYV12()
C=FrameReplace(C,PRE,CMD="PRE.TXT",show=SHOW) # Replace Pre frames
FrameReplace(C,POST,CMD="POST.TXT",show=SHOW) # Replace Post frames
return Last


Requires RT_Stats v1.16, FrameSelect v1.02 Plugins.
FrameSelect v1.02, added FrameReplace filter for above scripts.
RT_LumaSceneChange added to RT_Stats v1.16.

Lyris
28th April 2013, 04:49
Brilliant, thanks a ton!

Just one problem I'm running into. In the last script, the one which re-seats the modified frames into the file, I sometimes get black frames with this error:

"ImageReader: raster sizes must be identical"

Which is strange, because the resolution of the source clip and all the BMP files is 1920x1080. Any ideas?

StainlessS
28th April 2013, 04:55
No idea here. Works fine on my test clip (only 640x400).

Does it work OK without editing the frames, ie scripts 1 through 4 in sequence without modding in Photoshop.

Which version Avisynth you using ?

Lyris
28th April 2013, 05:07
2.5 - and yes, this is even before any modifications are made. Seems to be working at the moment though. Fingers crossed!

Even if I did have to resort to manually replacing some frames, your script is a huge help, so many thanks.

StainlessS
28th April 2013, 05:09
Think I once had a problem if Dots Per Inch were not all same (perhaps PhotoShop changes them).
(think it was DPI, changed by MS Office Picture Editor).

EDIT: Above cross posted.

EDIT: Think you can import series of Bitmaps into VDub current, perhaps can save as clip and hack script 4.
EDIT: Perhaps BMP save/load broken, maybe try another format.

EDIT: Would it be useful to have the frames BEFORE PRE and AFTER POST as well, for fixing damage ?

StainlessS
28th April 2013, 22:39
Post #16 updated, uses new function RT_LumaSceneChange() instead of mt_lutxy/Averageluma (all colorspaces).
Also added optional extra frames either side of pre and post frames, also can jump about now viewing metrics.

2Bdecided
29th April 2013, 09:58
Some people would think you were removing part of the charm of something that was originated and edited on film.

I wouldn't - I find those edits immensely distracting - but people were used to them and ignored them back in the day. Depending on the telecine and quality of the splice, there's often a slight vertical jump at the edit too. This was just "how things are" in the good old days. ;)

Cheers,
David.

GMJCZP
20th June 2013, 14:37
With Didée we have developed a function called DeCelluloid that deals with this defect that occurs in old videos (at least it's a try):

http://forum.doom9.org/showthread.php?p=1567932#post1567932

Good Luck.