Archimedes
2nd April 2009, 17:02
Lately i was searching for a debayer filter for AviSynth. I only found a demosaic plugin ( http://forum.doom9.org/showpost.php?p=1070720). As the interpolation methods are very simple (nearest and bilinear), the quality are not really good (aliasing, color artifacts and so on). May be good enough for previewing.
So i wrote my own debayer function in AviSynth. More precisely, a script for Fritz Photo (http://forum.doom9.org/showthread.php?t=150291). May be, it’s not perfect now and we have to live with the 8 bit limitations, but the results seems to be quite stable. The function needs the NNEDI3 plugin.
Input is a RGB24 or RGB32 clip and output is a RGB32 clip. The function has two modes. Mode 1 is a little bit softer, but gives good results on portraits and so on. Mode 2 keeps the most details, while color artifacts are minimized. As the bayer pattern can be implemented in different ways, the parameters xoffset and yoffset take care about. For the parameters nsize, nns, qual and pscrn, please read the documentation of NNEDI3.
function Demosaic(clip input, int "mode", int "xoffset", int "yoffset", int "nsize", int "nns", int "qual", bool "pscrn") {
mode = Default(mode, 2)
xoffset = Default(xoffset, 0)
yoffset = Default(yoffset, 0)
nsize = Default(nsize, 6)
nns = Default(nns, 1)
qual = Default(qual, 2)
pscrn = Default(pscrn, True)
clip = input.Crop(0, 0, -(input.Width % 4), -(input.Height % 4)).ShowGreen("YV12")
last = clip
yoffset == 0 ? AssumeFrameBased().SeparateFields().SelectOdd() : AssumeFrameBased().SeparateFields().SelectEven()
TurnRight()
xoffset == 0 ? AssumeFrameBased().SeparateFields().SelectEven() : AssumeFrameBased().SeparateFields().SelectOdd()
TurnLeft()
yoffset == 0 ? NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnRight()
xoffset == 0 ? NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnLeft()
R = last
last = clip
yoffset == 0 ? AssumeFrameBased().SeparateFields().SelectEven() : AssumeFrameBased().SeparateFields().SelectOdd()
TurnRight()
xoffset == 0 ? AssumeFrameBased().SeparateFields().SelectEven() : AssumeFrameBased().SeparateFields().SelectOdd()
TurnLeft()
yoffset == 0 ? NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnRight()
xoffset == 0 ? NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnLeft()
G1 = last
last = clip
yoffset == 0 ? AssumeFrameBased().SeparateFields().SelectOdd() : AssumeFrameBased().SeparateFields().SelectEven()
TurnRight()
xoffset == 0 ? AssumeFrameBased().SeparateFields().SelectOdd() : AssumeFrameBased().SeparateFields().SelectEven()
TurnLeft()
yoffset == 0 ? NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnRight()
xoffset == 0 ? NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnLeft()
G2 = last
mode == 1 ? Eval("""
G = G1.MergeLuma(G2, 0.5)
""") : Eval("""
NOP()
""")
mode == 2 ? Eval("""
G1.TurnRight()
g11 = AssumeFrameBased().SeparateFields().SelectEven()
g12 = AssumeFrameBased().SeparateFields().SelectOdd()
G2.TurnRight()
g21 = AssumeFrameBased().SeparateFields().SelectEven()
g22 = AssumeFrameBased().SeparateFields().SelectOdd()
xoffset == 0 ? Interleave(g11, g12.MergeLuma(g22, 0.5)) : Interleave(g11.MergeLuma(g21, 0.5), g12)
AssumeFieldBased()
Weave()
TurnLeft()
G1 = last
xoffset == 0 ? Interleave(g21.MergeLuma(g11, 0.5), g22) : Interleave(g21, g22.MergeLuma(g12, 0.5))
AssumeFieldBased()
Weave()
TurnLeft()
G2 = last
yoffset == 0 ? Interleave(G1.AssumeFrameBased().SeparateFields().SelectEven(), G2.AssumeFrameBased().SeparateFields().SelectOdd()) : Interleave(G2.AssumeFrameBased().SeparateFields().SelectEven(), G1.AssumeFrameBased().SeparateFields().SelectOdd())
AssumeFieldBased()
Weave()
nnedi3_rpow2(rfactor=2, nsize=0, nns=1, qual=2, pscrn=True, cshift="Spline36Resize", fwidth=last.Width, fheight=last.Height)
G = last
""") : Eval("""
NOP()
""")
(mode < 1) || (mode > 2) ? Eval("""
G = G1.MergeLuma(G2, 0.5)
""") : Eval("""
NOP()
""")
last = clip
yoffset == 0 ? AssumeFrameBased().SeparateFields().SelectEven() : AssumeFrameBased().SeparateFields().SelectOdd()
TurnRight()
xoffset == 0 ? AssumeFrameBased().SeparateFields().SelectOdd() : AssumeFrameBased().SeparateFields().SelectEven()
TurnLeft()
yoffset == 0 ? NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnRight()
xoffset == 0 ? NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnLeft()
B = last
MergeRGB(R, G, B)
}
So i wrote my own debayer function in AviSynth. More precisely, a script for Fritz Photo (http://forum.doom9.org/showthread.php?t=150291). May be, it’s not perfect now and we have to live with the 8 bit limitations, but the results seems to be quite stable. The function needs the NNEDI3 plugin.
Input is a RGB24 or RGB32 clip and output is a RGB32 clip. The function has two modes. Mode 1 is a little bit softer, but gives good results on portraits and so on. Mode 2 keeps the most details, while color artifacts are minimized. As the bayer pattern can be implemented in different ways, the parameters xoffset and yoffset take care about. For the parameters nsize, nns, qual and pscrn, please read the documentation of NNEDI3.
function Demosaic(clip input, int "mode", int "xoffset", int "yoffset", int "nsize", int "nns", int "qual", bool "pscrn") {
mode = Default(mode, 2)
xoffset = Default(xoffset, 0)
yoffset = Default(yoffset, 0)
nsize = Default(nsize, 6)
nns = Default(nns, 1)
qual = Default(qual, 2)
pscrn = Default(pscrn, True)
clip = input.Crop(0, 0, -(input.Width % 4), -(input.Height % 4)).ShowGreen("YV12")
last = clip
yoffset == 0 ? AssumeFrameBased().SeparateFields().SelectOdd() : AssumeFrameBased().SeparateFields().SelectEven()
TurnRight()
xoffset == 0 ? AssumeFrameBased().SeparateFields().SelectEven() : AssumeFrameBased().SeparateFields().SelectOdd()
TurnLeft()
yoffset == 0 ? NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnRight()
xoffset == 0 ? NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnLeft()
R = last
last = clip
yoffset == 0 ? AssumeFrameBased().SeparateFields().SelectEven() : AssumeFrameBased().SeparateFields().SelectOdd()
TurnRight()
xoffset == 0 ? AssumeFrameBased().SeparateFields().SelectEven() : AssumeFrameBased().SeparateFields().SelectOdd()
TurnLeft()
yoffset == 0 ? NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnRight()
xoffset == 0 ? NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnLeft()
G1 = last
last = clip
yoffset == 0 ? AssumeFrameBased().SeparateFields().SelectOdd() : AssumeFrameBased().SeparateFields().SelectEven()
TurnRight()
xoffset == 0 ? AssumeFrameBased().SeparateFields().SelectOdd() : AssumeFrameBased().SeparateFields().SelectEven()
TurnLeft()
yoffset == 0 ? NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnRight()
xoffset == 0 ? NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnLeft()
G2 = last
mode == 1 ? Eval("""
G = G1.MergeLuma(G2, 0.5)
""") : Eval("""
NOP()
""")
mode == 2 ? Eval("""
G1.TurnRight()
g11 = AssumeFrameBased().SeparateFields().SelectEven()
g12 = AssumeFrameBased().SeparateFields().SelectOdd()
G2.TurnRight()
g21 = AssumeFrameBased().SeparateFields().SelectEven()
g22 = AssumeFrameBased().SeparateFields().SelectOdd()
xoffset == 0 ? Interleave(g11, g12.MergeLuma(g22, 0.5)) : Interleave(g11.MergeLuma(g21, 0.5), g12)
AssumeFieldBased()
Weave()
TurnLeft()
G1 = last
xoffset == 0 ? Interleave(g21.MergeLuma(g11, 0.5), g22) : Interleave(g21, g22.MergeLuma(g12, 0.5))
AssumeFieldBased()
Weave()
TurnLeft()
G2 = last
yoffset == 0 ? Interleave(G1.AssumeFrameBased().SeparateFields().SelectEven(), G2.AssumeFrameBased().SeparateFields().SelectOdd()) : Interleave(G2.AssumeFrameBased().SeparateFields().SelectEven(), G1.AssumeFrameBased().SeparateFields().SelectOdd())
AssumeFieldBased()
Weave()
nnedi3_rpow2(rfactor=2, nsize=0, nns=1, qual=2, pscrn=True, cshift="Spline36Resize", fwidth=last.Width, fheight=last.Height)
G = last
""") : Eval("""
NOP()
""")
(mode < 1) || (mode > 2) ? Eval("""
G = G1.MergeLuma(G2, 0.5)
""") : Eval("""
NOP()
""")
last = clip
yoffset == 0 ? AssumeFrameBased().SeparateFields().SelectEven() : AssumeFrameBased().SeparateFields().SelectOdd()
TurnRight()
xoffset == 0 ? AssumeFrameBased().SeparateFields().SelectOdd() : AssumeFrameBased().SeparateFields().SelectEven()
TurnLeft()
yoffset == 0 ? NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnRight()
xoffset == 0 ? NNEDI3(dh=True, field=1, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn) : NNEDI3(dh=True, field=0, Y=True, U=False, V=False, nsize=nsize, nns=nns, qual=qual, pscrn=pscrn)
TurnLeft()
B = last
MergeRGB(R, G, B)
}