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. |
2nd April 2009, 16:02 | #1 | Link |
Registered User
Join Date: Apr 2005
Posts: 213
|
Demosaic
Lately i was searching for a debayer filter for AviSynth. I only found a demosaic plugin. 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. 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. Code:
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) } Last edited by Archimedes; 21st July 2010 at 16:21. |
4th April 2009, 18:41 | #3 | Link |
x264aholic
Join Date: Jul 2007
Location: New York
Posts: 1,752
|
This script only seems to output a grayscale image, regardless of whether you give it regular YV12 input or grayscale YV12 input.
And it shouldn't matter whether I give it input from a non-debayerized source and a faked source like grayscale YV12, since the two should look identical to your script.
__________________
You can't call your encoding speed slow until you start measuring in seconds per frame. |
7th April 2009, 19:21 | #5 | Link |
brainless
Join Date: Mar 2003
Location: Germany
Posts: 3,653
|
can you show a sample that is near to (or exceeds) the nyquist frequency?
ie, a sample that is prone to aliasing or false colour in highly detailed areas.
__________________
Don't forget the 'c'! Don't PM me for technical support, please. |
7th April 2009, 21:44 | #6 | Link |
Registered User
Join Date: Apr 2005
Posts: 213
|
Here are some examples (without white balance). The original raw file has only 8 bit.
1.1 Demosaic (method=nearest): 1.2 Demosaic (method=bilinear): 1.3 FritzPhotoDemosaic (Mode=1): 1.4 FritzPhotoDemosaic (Mode=2): 2.1 Demosaic (method=nearest): 2.2 Demosaic (method=bilinear): 2.3 FritzPhotoDemosaic (Mode=1): 2.4 FritzPhotoDemosaic (Mode=2): |
6th July 2009, 19:24 | #9 | Link |
Registered User
Join Date: Apr 2005
Posts: 213
|
I've realized, that in mode 2 the image center shift of channel G was not corrected. This is fixed now.
How we can compare? dcraw can handle 16 bit inputs, Demosaic, as a proof of concept, can only work in 8 bit mode. Demosaic filters each channel (R, G1, G2 and B) separately, dcraw works per default an all channels. However, it has an option (-f), to work on each channel separately. In default mode, the results from dcraw looks much sharper (may be more detailed), but you have to deal with aliasing, color artefacts and labyrinth patterns (depending on the sources). One solution against such color artefacts and labyrinth patterns is, to interpolate the RGGB pattern as four colors (option –f). But the results looks less sharpen now (similar to the results of the demosaic function). However, a strong sharpening filter afterwards produces more aliasing on the dcraw source. Last edited by Archimedes; 6th July 2009 at 19:27. |
7th July 2009, 14:05 | #10 | Link |
interlace this!
Join Date: Jun 2003
Location: i'm in ur transfers, addin noise
Posts: 4,555
|
i wonder if at some future point we could see a tritical build of dcraw?
or a nnedi2'ed hack of the redcode codec? that's way too much to put on the poor guy though.
__________________
sucking the life out of your videos since 2004 |
11th July 2009, 13:35 | #11 | Link |
brainless
Join Date: Mar 2003
Location: Germany
Posts: 3,653
|
have you guys tried kolev raw so far?
it seems to implement some kind of edge directed interpolation. I never use it though for other reasons.
__________________
Don't forget the 'c'! Don't PM me for technical support, please. |
14th July 2009, 18:54 | #12 | Link | ||
Registered User
Join Date: Apr 2005
Posts: 213
|
Quote:
Quote:
|
||
19th December 2009, 02:14 | #13 | Link |
Registered User
Join Date: Apr 2006
Posts: 299
|
Dear Archimedes,
I'm intrigued by the NNEDI2 demosiac. I found a thread in the german dslrforum http://www.dslr-forum.de/showthread.php?t=467892&page=9 your script was discussed and you posted a build of dcraw, what was the point of that build(my german is poor). Was it a patch to add 8-bit linear gamma output? Last edited by markanini; 19th December 2009 at 04:46. Reason: forgot dcraw has a manpage... |
21st December 2009, 10:38 | #14 | Link | |||
Registered User
Join Date: Apr 2005
Posts: 213
|
I try to recapitulate it.
There was a problem with a handy photo. The handy supported an 8 bit raw format, but saved it as a non linear grayscale tiff format (with the bayer pattern). Most raw converter interpreted this format as a normal graphic format, but not as a raw. First, i tried the Demosic-Plugin, which works, but the results was not very good. The author of dcraw then make some patches, where the tiff format was interpreted as a raw format. At the same time i have the idea with NNEDI to do the demosaicing. The answers of the author of dcraw regarding the different patches in chronological order: Quote:
Quote:
Quote:
Last edited by Archimedes; 21st December 2009 at 10:54. |
|||
|
|