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

 
 
Thread Tools Search this Thread Display Modes
Prev Previous Post   Next Post Next
Old 9th October 2011, 03:56   #1  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,867
New Script: Software TBC 0.6 & Sample (was Fast Line Shifter 0.53)

Hi,
This is a software "line" TBC. There is a new version, but it doesn't have more quality, just fast enough to be practical (in those cases where it can be used.)

Yes, it has worked for some people's real clips, which had severe "wobbly lines", but don't expect much. I still need to do some basic research here.

Update: New plugin version 0.61
http://www.sendspace.com/file/s78pp4
Installation note:
Please extract the included plugins and place into your plugins directory.
jitter02.zip -> jitter.dll -> plugins\jitter.dll
findpos01.zip -> findpos.dll -> plugins\findpos.dll
You may also need the VC2008 runtime.

If you get an error when trying to load the plugin, try these versions. They are called "static builds", a programmer's term, which means they are fully self contained. The only disadvantage is a bigger download. They are no different in functionality.

jdejitter03_static
http://www.sendspace.com/file/qk1ifv

findpos02_static
http://www.sendspace.com/file/e3jblt


The following applies to the old 0.53, and the theory in general can be used with the new version
----------------------------------

This script is in development and is only for the following cases:
-#1 Video was captured with HSYNC area (via driver tweaks)
-#2 Video contains easily distinguishable black borders on both sides (again, probably needing tweaks).
-If you have a hardware TBC there's no point, but case #2 in a digital file with the original analog source unavailable might be useful
-It's not necessarily any better than existing plugins for case #2
-If you have a supported card, it's possible to have the equivalent effect of a hardware TBC (they work very similar), at least for the "wobbly" function.

How to get the capture
The capture section has moved to "How to Capture with HSYNC" in the capture forum. That topic is unrelated to script usage.
http://forum.doom9.org/showthread.php?t=162832

Results (this only worked so well because I have HSYNC)
http://screenshotcomparison.com/comparison/88810

Results for case#2 from a user supplied video:
http://screenshotcomparison.com/comparison/91853

Theory of Operation
Before I get into usage, it would help to know what we're trying to accomplish. An analog video signal starts and ends each line with a pulse called an HSYNC. On a VCR, the timing is not stable. The capture card starts with the first HSYNC and reads in the video for a set time-period, then waits for the next HSYNC. The result is that the video can appear shifted by a different amount on each line. A hardware TBC probably works by reading the full line and re-adjusting it's timing to the standard amount, thus when captured, you get the entire video line.
With Case #1 we are capturing the HSYNC (the right half of it) and a large window of the video line - thus including all of it, regardless of it's timing. Now it's simply an image that needs lining-up. The script looks for the HSYNC line at the left, then a black area at the right, and resizes the line to a standard size (exactly equivalent to how a hardware TBC re-times). The HSYNC is very easy to find and is a one-pixel or so line. The right edge relies on a short black area which is 'blacker' than anything the video could be, so it's also reliable.

With Case #2 we're relying on black borders being in the video and the video being relatively bright. We simply line-up the black borders to the same spot. Dark scenes in the video could confuse the border detection so it's not as reliable, and that is the case with any other plugin (which is why I say mine is not necessarily any better in this case).

Usage
Quite simple, there is an autothresh which looks for black pixels in the left border. A small amount is added to this to form the real thresh. Adjust the added amount to tweak, until the picture lines up. I used AvsPmod to look at the raw video, and moving my cursor over the black area, I saw it was a noisy 15-25 (in a user test clip). I decided to just set 32. Values slightly lower would leave a few lines wrong, seen as little black stripes at the left edge of the video. For that particular video, only the bright scenes worked correctly. Having it work for dark scenes is being experimented with.

Advanced Usage
The script first makes a mask, in this case every pixel at thresh or above is marked to luma=255 in the mask or 0 elsewhere.
Next I pass my mask to findpos_h which searches for the first 255 value on each line, within the searchwindow. It also simultaneously searches from right to left by searchwindow pixels. It saves the results in a special clip, which records the number of pixels before the mask was found. For example if the HSYNC line occurs at x=4, the luma of the shift clip contains luma=4 for that line, at the left hand side. The right hand side contains the offset from the right of where the video ended, for example if it ended at x=710 and the video is 720 pixels wide, the luma of shift is 10 on the right hand side.
alignbyluma now reads the original video and the shift video and resizes to a standard size. Hopefully this is enough information to do anything else you want here.

What about the aspect ratio?
I still need to calibrate to return the correct aspect ratio. Currently the fixed video is probably wider than it should be.

Limitations
Check the history. Currently searchwindow is not working correctly, but it's enough to work. Also I need to add subpixel detection/shifting to get a really stable result. Currently the result looks like a little noise because of subpixel jitter.

Code:
#Fast line shifter Ver 0.53 by jmac698
#Lines up either or both edges of a video.  Can also be used as displacement for 3d scripts.
#Requires Masktools v2a45+ (mt_lutspa mode), GRunT, GScript
#MinMax http://forum.doom9.org/showthread.php?p=1532124#post1532124
#Limitations: still no subpixel shifting
#0.53: Avoid possible "ScriptClip: Function did not return a video clip of the same colorspace as the source clip!"
#0.52: Less blurry resize
#0.51: Autothresh (uses 2 pixels of left border as a starting point, then adds a small amount to avoid noise)
#0.5: Slow, but using a completely new approach, and can resize whole lines
#0.4: Fast, can detect and line up on left or right edges
#note: sample was frame 167, http://screenshotcomparison.com/comparison/88810

#Modified to work with wide-window sample capture, which includes hsync

src=AVISource("D:\project001a\tbc2\vhs hysnc sample.avi").converttoyuy2
#crop(8,0,0,0)#Uncomment and adjust to remove extra black left border
thresh=int(findthresh(src))+3#This may not always work, try to manually set to 32 for example.  Pick the lowest value which lines up picture.
ScriptClip(src, """
#Mark video edges
converttoyv12
m=mt_binarize(thresh)
#Line up video
findpos_h(m, searchwidth=22)
alignbyluma(src,last)
""")
addborders(56,0,0,0)

function findpos_h(clip m, int "searchwidth", int "x1", int "x2"){
    #Searches m from left to right in the range x1 to x1+searchwidth-1 and right to left in the range width-1-x2 to x2-searchwidth-1
    #for the first luma=255 pixel, then colors the output line with the offset from x
    #for example m is 0 0 255 255 255 0 0 0, width=8, x1=0, x2=0, searchwidth=4 becomes 4 4 2 3 3 4 4 4, then 2 2 2 2 3 3 3 3 
    #Can only search for 255 pixels (as the luma output is only 8 bit)
    #c and m should have the same clip properties (same size)
    #searchwidth should be <=width/2
    searchwidth=default(searchwidth,32)
    x1=default(x1,0)
    x2=default(x2,0)
    rampexpr="x "+string(m.width/2)+" < x "+string(m.width-1)+" x - ?"#x w/2 < x w-1 x - ?
    ramp=mt_lutspa(m, mode="absolute",expr=rampexpr)
    notfound=searchwidth#Value to return if no mask on this line, should be >=searchwidth or you'll find the wrong minimum later
    maskmarker=255#The luma value in the mask which indicates a detected pixel
    #(if m=maskmarker return ramp else notfound), 255 means x>=255, x<searchwidth or notfound
    mt_lutxy(m,ramp,yexpr="x "+string(maskmarker)+" = y "+string(notfound)+" ?")
    #now make solid lines based on min luma found in each line
    l=crop(0,0,-width/2,0)
    r=crop(width/2,0,0,0)
    l=l.minmax(0,0)
    r=r.minmax(0,0)
    StackHorizontal(l,r)
}

function alignbyluma(clip src, clip shift, int "mode"){
    #Shift/scale each line of clip src by the x offset defined by the luma of shift
    #for example if shift were all luma=8, the entire src clip would move 8 pixels to the (dir)
    #This works on a pixel basis, so solid horizontal lines in shift can shift src by variable amounts per line
    #It uses a simple replacement strategy, where each pixel in shift is tested and replaced by the same pixel in a shifted copy
    #Currently handles only 0-15 shifts
    #Magnify everything to get full color resolution
    mode=default(mode, 2)
    shiftuv=shift
    shift=shift.pointresize(shift.width*2,shift.height*2)
    shift=ytouv(shiftuv,shiftuv,shift)
    src=src.pointresize(src.width*2,src.height*2)#We double here to preserve chroma rez
    GScript("
        for (y=0, src.height/2-1, 1) {
            l=int(getpixel(shift,0,y).YPlaneMin)
            r=int(getpixel(shift,shift.width/2-2,y).YPlaneMin)
            getline(src, y*2)
            align(l*2, r*2, 4, 4)
            out=y==0?last:stackvertical(out,last)
        }#for y
    ")#GScript
    out
    converttoyuy2
    bilinearresize(src.width/2,src.height/2)
}

function align(clip v, int xl, int xr, int lb, int rb, int "mode") {
    v#shift an image, x>0 shifts left, xl is amount to shift left, xr is amount to shift right
    #mode 0 is shift left only, 1 shift right, 2 scale to shift left and right
    mode=default(mode, 2)
    offx=mode==0?xl:-xr
    mode<2?pointresize(last.width, last.height, offx, 0, last.width, last.height):crop(xl,0,-xr,0).addborders(lb, 0, rb, 0).Spline36Resize(last.width,last.height)
}

function getpixel(clip v, int x, int y) {
    #get color of a single pixel and return as a fat 2x2 yv12 pixel
    v
    #pointresize(last.width*2,last.height*2)
    crop(x>0?x*2:0,y>0?y*2:0,-(last.width-x*2-2),-(last.height-y*2-2))
}

function getline(clip v, int y) {
    v#return a line of height 2 from y to y+1
    crop(0,y,0,-(last.height-y-2))
}

function findthresh(clip v){
    #Find a resonable starting point for thresh by searching border
    current_frame=0
    v.converttoyv12
    crop(0,16,-last.width+2,-16)
    AverageLuma
}

Last edited by jmac698; 14th July 2012 at 06:16. Reason: Updated
jmac698 is offline   Reply With Quote
 

Tags
tbc

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 04:29.


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