View Full Version : DCTune Custom Matrix Discussion (thread-split)
SoonUDie
26th April 2004, 10:57
I have decided not to continue work on matrices at the moment, because I think I have a better strategy: calculate a new matrix for every encode by using DCTune on about 200+ frames of the source and averaging the results. Tests have been encouraging.
dimzon
26th April 2004, 11:04
Originally posted by SoonUDie
calculate a new matrix for every encode by using DCTune on about 200+ frames of the source and averaging the results
please, write small guide for beginners!
iradic
26th April 2004, 11:05
@SoonUDie
Could you post your usage of DCTune... (like some little guide)?
Thanks
EDIT: dimzon was faster...
dimzon
26th April 2004, 11:40
calculate a new matrix for every encode by using DCTune on about 200+ frames of the source and averaging the results
Hmm. Anybody knows DCTune algorythm? Maybe best way is AVS2QMATRIX automation tool?
SoonUDie
26th April 2004, 15:56
It would be awesome if the process could be automated, but I don't really have a clue how to do it at the moment. It's already automated for the most part (but in different steps).
My chain of processing goes like this:
1. Use Avisynth to create frames in native DCTune format (.ppm).
Example script:
SelectEvery(last, 1000, 1)
ConvertToRGB()
ImageWriter(last, file = "C:\dctune_raw\yoursource", start = 0, end = 0, type = "ppm")
This will output every thousandth frame in the form of yoursource000000.ppm, yoursource000001.ppm, etc.
2. Use BathEncoder to call DCTune on all of the images. Simply drag and drop the files into it, set your encoding switches, and hit "go". BathEncoder creates a batchfile which calls DCTune on every image. You can get it here (http://members.home.nl/w.speek/batchenc.htm). Be sure to put DCTune (http://vision.arc.nasa.gov/dctune/) in the same folder.
The switches I normally use for DCTune are:
dctune2.0 -f <infile> -p 1 -inches 8 -dpi 133 -o <outfile>_quants_p1.txt -j <outfile>_p1.jpg
Note the -p value. This is basically your quality setting. -p 1 is normally perceptually lossless. For a high-bitrate encode, I normally use this to create my intra-matrix; then I run it a second time with -p 2 and change the outputs accordingly, and use those to create my inter-matrix.
In general, I use the following p-values:
High bitrate: 1, 2
Medium bitrat: 2, 3
Low bitrate: 3, 4
The high bitrate matrices also look good at low bitrate, but you have a higher average quantizer (so it looks a little ragged).
3. Average the results to get a good quantization matrix. I'm currently using a pretty simplistic program I wrote in Java to do this. I'm not really a programmer, so I have no clue how to export it at the moment. I *might* be able to turn it into an applet.
dimzon
26th April 2004, 16:20
Originally posted by SoonUDie
It would be awesome if the process could be automated
Seems like I can write simple avs2qmatrix.bat to automate it :)
===================
Done!
Create such directory structure:
c:\dctune\
c:\dctune\frames\
c:\dctune\trash\
c:\dctune\inter\
c:\dctune\intra\
place avs2avi.exe and dctune2.0.exe into c:\dctune\ folder
place extract.bat into c:\dctune\ folder
@echo off
del /Q c:\dctune\frames\*.ppm > NUL
echo Import("%1") > temp.avs
echo SelectEvery(last, %2, %2/2) >> temp.avs
echo ConvertToRGB24() >> temp.avs
echo ImageWriter(last, file="c:\dctune\frames\x", start=0, end=0, type="ppm") >> temp.avs
echo crop(0,0,8,8) >> temp.avs
c:\dctune\avs2avi temp.avs -o n -c DIV3
place calculate.bat into c:\dctune\ folder
@echo off
del /Q c:\dctune\intra\*.* > NUL
del /Q c:\dctune\inter\*.* > NUL
FOR %%i IN (c:\dctune\frames\*.ppm) DO c:\dctune\dctune2.0.exe -f %%i -p %1 -inches 8 -dpi 133 -o c:\dctune\intra\%%~ni.txt -j c:\dctune\trash\last.jpg
FOR %%i IN (c:\dctune\frames\*.ppm) DO c:\dctune\dctune2.0.exe -f %%i -p %2 -inches 8 -dpi 133 -o c:\dctune\inter\%%~ni.txt -j c:\dctune\trash\last.jpg
cscript c:\dctune\calculate.vbs
place calculate.vbs into c:\dctune\ folder
Option Explicit
dim g_oFS ' FileSystem Object
set g_oFS = CreateObject("Scripting.FileSystemObject")
function ReadMatrixFromFile(sFileName)
dim aResult
dim aLine
dim oFile
dim s
dim i,j
redim aResult(63) ' 8X8, zero based
set oFile = g_oFS.OpenTextFile(sFileName, 1)
' Skip file header ;)
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
for i=0 to 7 ' 8 lines total
s = oFile.ReadLine
s = replace( trim(s), CHR(32) & CHR(32), CHR(32))
s = replace( trim(s), CHR(32) & CHR(32), CHR(32))
s = replace( trim(s), CHR(32) & CHR(32), CHR(32))
s = replace( trim(s), CHR(32) & CHR(32), CHR(32))
s = replace( trim(s), CHR(32) & CHR(32), CHR(32))
s = replace( trim(s), CHR(32) & CHR(32), CHR(32))
aLine = Split(s,CHR(32))
for j=0 to 7
aResult(i*8+j)=CLng(aLine(j))
next
next
oFile.Close
ReadMatrixFromFile = aResult
end function
function CalculateAverageMatrix(sDirectory)
dim oFile
dim aResult
dim aSubMatrix
dim nCount
dim i
redim aResult(63) ' 8X8, zero based
for i=0 to 63
aResult(i)=CDbl(0)
next
nCount = 0
for each oFile in g_oFS.getFolder(sDirectory).files
aSubMatrix = ReadMatrixFromFile(oFile.Path)
nCount = nCount + 1
for i=0 to 63
aResult(i)=aResult(i) + CDbl(aSubMatrix(i))
next
next
if nCount>0 then
for i=0 to 63
aResult(i)=CDbl( aResult(i) /nCount)
if aResult(i) > 255 then aResult(i)=255
next
end if
CalculateAverageMatrix = aResult
end function
sub main
dim aIntraMatrix
dim aInterMatrix
dim aTotal
dim rMultiplier
dim oXml
dim oStream
dim i
redim aTotal(127)
aIntraMatrix = CalculateAverageMatrix("c:\dctune\intra")
aInterMatrix = CalculateAverageMatrix("c:\dctune\inter")
for i=0 to 63
aTotal(i)=aIntraMatrix(i)
next
for i=0 to 63
aTotal(i+64)=aInterMatrix(i)
next
'Note: The top left value (0, 0) must always be 8
' (may be defined so in the MPEG standard), and other values shall not be below.
rMultiplier = 8/aTotal(0)
for i=0 to 63
aTotal(i)=CLng( rMultiplier * CDbl(aTotal(i)))
if aTotal(i) > 255 then
aTotal(i) = 255
elseif aTotal(i) < 8 then
aTotal(i) = 8
end if
next
'Note: The top left value (0, 0) must always be 16
' (may be defined so in the MPEG standard), and other values shall not be below.
rMultiplier = 16/aTotal(64)
for i=64 to 127
aTotal(i)=CLng( rMultiplier * CDbl(aTotal(i)))
if aTotal(i) > 255 then
aTotal(i) = 255
elseif aTotal(i) < 16 then
aTotal(i) = 16
end if
next
for i=0 to 127
if aTotal(i)>15 then
aTotal(i) = HEX(aTotal(i))
else
aTotal(i) = "0" & HEX(aTotal(i))
end if
next
set oXml = CreateObject("MSXML2.DOMDocument.3.0").createElement("dummy")
oXml.dataType="bin.hex"
oXml.text=join(aTotal,"")
set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type=1
oStream.Write oXml.nodeTypedValue
oStream.SaveToFile "c:\dctune\result.qmatrix", 2
oStream.Close
MsgBox "Done!"
end sub
CALL Main()
USAGE
1-st - extract frames
extract.bat <source_avs_file_name_and_path> <frame_denominator>
example: extract c:\dvdrip\gigli\gigli.avs 1000
2-nd - calculate qmatrix
calculate.bat <intra_quality>, <inter_quality>
example: calculate 2 3
3-td - got Your matrix c:\dctune\result.qmatrix
SoonUDie
26th April 2004, 18:59
I bow before your skills. :goodpost:
Another note: you should probably go through and manually check all the frames, and delete any ones that you don't want to use. You should definately delete blank frames (all black or all white), and you may want to cut out any credits as well.
vaxis
26th April 2004, 20:22
This is really cool. I am in the middle of testing it on Iron Maiden - Rock In Rio, which is the hardiest dvd to encode I have ever seen.
I did have to change a couple of lines in the calculate.vbs to get it to work. In the function ReadMatrixFromFile, where the double for loop is, your way of dividing the numbers into the array aLine did not work, some post in it where just blanks and the CLng then returned an error. instead I simply made aLine to a string and implemented the inner for loop a little different and removed the lines with replace calls in the outer for loop.
So here is the loop solution that worked for me:
for i=0 to 7 ' 8 lines total
s = oFile.ReadLine
for j=0 to 7
aLine = trim(mid(s,j*4+1,4))
aResult(i*8+j)=CLng(aLine)
next
next
You should update your script with that.
Again, thanks for this much easier automatic solution.
SoonUDie
27th April 2004, 00:41
I hope it works out for you. In general, I've found that it seems to produce a very good amount of detail - more than HVS Best is most cases. The main plus side, in my mind, is that the matrix is totally adapted to the source. I think the only way you could improve upon this general method would be if XviD automatically calculated and used a different (optimized) quant matrix for each individual scene.
SoonUDie
27th April 2004, 00:45
Oh, I should mention that DCTune produces matrices with a lowest possible value of 2. You may want to implement a way to multiply all the other values accordingly, so that you always get 8 in the upperp left corner. If not, you can use excel and a little bit of math once you have the final matrix.
ObiKenobi
27th April 2004, 01:26
Just to make sure I'm doing this right, when DCTune outputs the txt file like the one below, I use the top matrix right?
# Quantization Matrices for G:\000000.PPM
# Using DCTune Version 2.0
# Quantization Table Calculated Using Perceptual Optimization
# Target Perceptual Error 2.000000
# Mean Luminance: 33.532667 Candelas/meter^2
# Peak Luminance: 67.162400 Candelas/meter^2
# Number Gray Steps: 256
# Pixels/Degree X: 18.666667
# Pixels/Degree Y: 18.666667
# Size of DCT: 8
4 4 4 4 4 6 255 255
4 2 4 2 4 4 255 255
4 4 6 4 4 6 255 255
4 4 4 6 10 255 255 255
4 4 4 10 255 255 255 255
6 4 255 255 255 255 255 255
8 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255
# Quantization Table Calculated Using Perceptual Optimization
# Target Perceptual Error 2.000000
# Mean Luminance: 33.532667 Candelas/meter^2
# Peak Luminance: 67.162400 Candelas/meter^2
# Number Gray Steps: 256
# Pixels/Degree X: 9.333333
# Pixels/Degree Y: 9.333333
# Size of DCT: 8
18 255 255 255 255 255 255 255
24 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255
# Quantization Table Calculated Using Perceptual Optimization
# Target Perceptual Error 2.000000
# Mean Luminance: 33.532667 Candelas/meter^2
# Peak Luminance: 67.162400 Candelas/meter^2
# Number Gray Steps: 256
# Pixels/Degree X: 9.333333
# Pixels/Degree Y: 9.333333
# Size of DCT: 8
8 255 255 255 255 255 255 255
8 255 255 255 255 255 255 255
8 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255
255 255 255 255 255 255 255 255
iradic
27th April 2004, 02:10
hi...
for me -o c:\dctune\inter\%%~ni.txt doesnt work... only -o %%i.txt
using winme
any help...
EDIT: problem solved
SoonUDie
27th April 2004, 02:53
Originally posted by ObiKenobi
Just to make sure I'm doing this right, when DCTune outputs the txt file like the one below, I use the top matrix right?Yes. I believe the bottom ones are for chroma (not an option with XviD... and even if it was, DCTune tends to suck at chroma except at -p1 or higher quality)
ObiKenobi
27th April 2004, 02:55
Is it just me or does that matrix seem a bit odd though? Compared to other matrices I've looked at it just looks so much different.
SoonUDie
27th April 2004, 08:10
Originally posted by ObiKenobi
Is it just me or does that matrix seem a bit odd though? Compared to other matrices I've looked at it just looks so much different. If I understand quant matrices correctly, each entry covers a specified frequency range. Since humans don't perceive these frequencies equally, an optimized matrix will increase the quantization of those frequencies. I believe that the MPEG quant works this way (but uses an older percptual model?), and I know that the HVS matrices (HVS = Human Visual System) work that way, too.
The difference between using a generalized matrix like HVS-best and calculating an average matrix using DCTune is that, theoretically, the averaging method will create a perceptual matrix adapted to the source's quality, and therefore better for purposes of compression, retaining the same amount of quality with less bits. Of course, this assumes that DCTune's alogrithms for creating an optimized matrix are valid.
As an example of the DCTune method, here is the average matrix I got for the SeaBisucit R1 (widescreen) DVD at p=1 (~400 frames sampled, using my program to calculate the matrix):
8 8 8 10 11 16 86 255
8 8 9 9 10 28 106 255
8 9 16 21 35 77 255 255
8 9 20 60 87 174 255 255
10 10 23 86 149 255 255 255
15 16 57 118 255 255 255 255
26 22 92 185 255 255 255 255
41 59 166 255 255 255 255 255
dimzon
27th April 2004, 09:31
Originally posted by vaxis
I did have to change a couple of lines in the calculate.vbs to get it to work. In the function ReadMatrixFromFile, where the double for loop is, your way of dividing the numbers into the array aLine did not work, some post in it where just blanks and the CLng then returned an error. instead I simply made aLine to a string and implemented the inner for loop a little different and removed the lines with replace calls in the outer for loop.
It's bcz forum engine changed my source string:
s = replace( trim(s), "<SPACE><SPACE>", "<SPACE>")
to
s = replace( trim(s), "<SPACE>", "<SPACE>")
so i will change this string into
s = replace( trim(s), CHR(32) & CHR(32), CHR(32))
:)
anywhere Your solution works fine too (but i'm too lazy to analyze quantizers position into source string)
and some user nickname=Shade PM-ed me such info about DCTune (i have no idea why he PM-ed to me but not to post this to this thread so I repost it):
DCTune can only calculate intra matrix. It's designed for still image(JPEG), not for motion pictures.
The second matrix generated by DCTune is for chroma. JPEG can use different matrix for luma and chroma, and both matrix are intra matrix. You must design inter matrix(for inter block in P/B-frame) by youself.
Intra matrix quantize intra-block, the coefficients in intra-block are "texture".
Inter matrix quantize inter-block, the coefficients in inter-block are "residual data after ME".
The properties of intra/inter matrix are different.
:)
SoonUDie
27th April 2004, 10:42
"DCTune can only calculate intra matrix. It's designed for still image(JPEG), not for motion pictures."True. I don't really know as much about quantization as I want to, yet, but I've just assumed that inter-frames in general use a "lower-quality" matrix (which is where my use of 1 lower p value comes from).
Guys, can you remember me? I'm the one who started this thread :DYea, sorry about that :D. I've somewhat hijacked the thread in developing my own method for creating matrices.
Also, you can stop using the Evil Matrix now - it's served its purpose as a test, and I think my current method far outstripes it in creating a quality encode. I would appreciate it if you try my new method :)
On another point, I went through the forums using search, and DCTune has been discussed in relation to XviD a few times before (though not in this capacity or detail), and some people came to the same conclusion I have - it would be awesome if we could use use DCTune to optimize individual scenes, or even frames. For example: call DCTune on each i-frame, so that each scene gets the most appropriate matrix. I know that XviD supports (or at least, used to support) changing quantizations like this, but I think it's not mpeg4 compliant.
dimzon
27th April 2004, 10:58
Originally posted by SoonUDie
Oh, I should mention that DCTune produces matrices with a lowest possible value of 2. You may want to implement a way to multiply all the other values accordingly, so that you always get 8 in the upperp left corner. If not, you can use excel and a little bit of math once you have the final matrix.
How does You thik what is the best:
1) multiply all the other values on (8/top_left_intra_value)
OR
2) increase all the other values on (8-top_left_intra_value)
OR
3) set values=8 where values is < 8
dimzon
27th April 2004, 12:34
I have just updated calculate.vbs in my post to follow MPEG specs.
That's my quantizer matrix for "KNOCKIN' ON HEAVEN'S DOOR" movie
8,8,8,8,11,16,30,114
8,8,8,8,10,14,25,73
8,8,13,14,20,26,45,151
8,8,14,24,43,63,123,255
12,10,19,38,114,200,255,255
16,12,25,56,208,255,255,255
27,23,44,125,255,255,255,255
85,61,140,255,255,255,255,255
16,16,16,17,29,53,152,255
16,16,18,17,29,48,128,255
16,18,32,39,61,108,255,255
17,17,39,80,181,255,255,255
30,28,57,178,255,255,255,255
48,42,100,255,255,255,255,255
143,117,255,255,255,255,255,255
255,255,255,255,255,255,255,255
now I'm encoding...
springl
27th April 2004, 14:08
@dimzon
How do I have to modify the bat files to make them work flawlessly under WIN98SE,'cause I get a "not valid option /Q" when I run extract.bat and calculate.bat. Moreover,due to calculate.vbs, I get
a runtime error of M$ Vbscript : "activeX is not able to create the
object 'MSXML2.DOMDocument.3.0'".And of course, result.qmatrix is not created.
Thanks.
dimzon
27th April 2004, 14:17
@springl
you need Microsoft XML Parser 3.0 SP4 to run calculate.vbs
get it here:
http://msdn.microsoft.com/XML/XMLDownloads/default.aspx
about bat files you can try such workaround:
1) create such yes.txt into c:\dctune\ folder:
Y
Y
Y
Y
Y
Y
Y
Y
Y
Y
Y
Y
2) REPLACE
DEL /Q {something} >NUL
WITH
DEL {something} < c:\dctune\yes.txt >NUL
Good luck
springl
27th April 2004, 15:07
The old problems are gone thanks to XML Parser and your workaround but now there's a new runtime error of M$ VBScript :activeX is not able to create object 'ADODB.stream'.
Result.qmatrix is not created.:confused:
dimzon
27th April 2004, 15:26
Originally posted by springl
new runtime error of M$ VBScript :activeX is not able to create object 'ADODB.stream'.
You need Microsoft Data Access Components to. Sorry, it is my mistake, download it here:
http://www.microsoft.com/downloads/details.aspx?familyid=9ad000f2-cae7-493d-b0f3-ae36c570ade8&languageid=f49e8428-7071-4979-8a67-3cffcb0c2524&displaylang=en
Explanations
I used MSXML Parser to convert matrix data into raw bytearray (VBScript can't work with bytearray directly so there are some programming trick )
I used ADODB.Stream (part of MDAC) to store raw bytearray as result.qmatrix (VBScript can't work with files directly and Scripting.FileSystemObject can't work with binary files to so there are some another programming trick)
springl
27th April 2004, 16:09
@dimzon
OK,finally I've got the matrix.
Thank you very much for your help.
:)
SoonUDie
27th April 2004, 16:20
Hey guys - I've something interesting in my testing. For 1-CD encodes, a p 2/3 or p 3/4 mix works well... but I seem to be getting even better results by averaging a p 1 matrix with HVS-best. This version isn't a clear winner in detail, but it absolutely kills artifacts, and in general the "structure" of the image is preserved better.
dimzon
27th April 2004, 16:47
Originally posted by SoonUDie
Hey guys - I've something interesting in my testing. For 1-CD encodes, a p 2/3 or p 3/4 mix works well... but I seem to be getting even better results by averaging a p 1 matrix with HVS-best. This version isn't a clear winner in detail, but it absolutely kills artifacts, and in general the "structure" of the image is preserved better.
I have updated calculate.vbs so it produce now 2 files - result.qmatrix and result-mix-with-hvs-best.qmatrix
calculate.vbs
Option Explicit
dim g_oFS ' FileSystem Object
set g_oFS = CreateObject("Scripting.FileSystemObject")
function ReadMatrixFromFile(sFileName)
dim aResult
dim aLine
dim oFile
dim s
dim i,j
redim aResult(63) ' 8X8, zero based
set oFile = g_oFS.OpenTextFile(sFileName, 1)
' Skip file header ;)
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
oFile.ReadLine
for i=0 to 7 ' 8 lines total
s = oFile.ReadLine
s = replace( trim(s), CHR(32) & CHR(32), CHR(32))
s = replace( trim(s), CHR(32) & CHR(32), CHR(32))
s = replace( trim(s), CHR(32) & CHR(32), CHR(32))
s = replace( trim(s), CHR(32) & CHR(32), CHR(32))
s = replace( trim(s), CHR(32) & CHR(32), CHR(32))
s = replace( trim(s), CHR(32) & CHR(32), CHR(32))
aLine = Split(s,CHR(32))
for j=0 to 7
aResult(i*8+j)=CLng(aLine(j))
next
next
oFile.Close
ReadMatrixFromFile = aResult
end function
function CalculateAverageMatrix(sDirectory)
dim oFile
dim aResult
dim aSubMatrix
dim nCount
dim i
redim aResult(63) ' 8X8, zero based
for i=0 to 63
aResult(i)=CDbl(0)
next
nCount = 0
for each oFile in g_oFS.getFolder(sDirectory).files
aSubMatrix = ReadMatrixFromFile(oFile.Path)
nCount = nCount + 1
for i=0 to 63
aResult(i)=aResult(i) + CDbl(aSubMatrix(i))
next
next
if nCount>0 then
for i=0 to 63
aResult(i)=CDbl( aResult(i) /nCount)
if aResult(i) > 255 then aResult(i)=255
next
end if
CalculateAverageMatrix = aResult
end function
Sub SaveMatriX(aMatrix, sFileName)
dim aTotal
dim oXml
dim oStream
dim i
redim aTotal(127)
for i=0 to 127
if aMatrix(i)>15 then
aTotal(i) = HEX(aMatrix(i))
else
aTotal(i) = "0" & HEX(aMatrix(i))
end if
next
set oXml = CreateObject("MSXML2.DOMDocument.3.0").createElement("dummy")
oXml.dataType="bin.hex"
oXml.text=join(aTotal,"")
set oStream = CreateObject("ADODB.Stream")
oStream.Open
oStream.Type=1
oStream.Write oXml.nodeTypedValue
oStream.SaveToFile sFileName, 2
oStream.Close
End Sub
function NormalizeMatrix(aMatrix)
dim aTotal, i
dim rMultiplier
aTotal = Split(Join(aMatrix,"???") ,"???")
'Note: The top left value (0, 0) must always be 8
' (may be defined so in the MPEG standard), and other values shall not be below.
rMultiplier = 8/aTotal(0)
for i=0 to 63
aTotal(i)=CLng( rMultiplier * CDbl(aTotal(i)))
if aTotal(i) > 255 then
aTotal(i) = 255
elseif aTotal(i) < 8 then
aTotal(i) = 8
end if
next
'Note: The top left value (0, 0) must always be 16
' (may be defined so in the MPEG standard), and other values shall not be below.
rMultiplier = 16/aTotal(64)
for i=64 to 127
aTotal(i)=CLng( rMultiplier * CDbl(aTotal(i)))
if aTotal(i) > 255 then
aTotal(i) = 255
elseif aTotal(i) < 16 then
aTotal(i) = 16
end if
next
NormalizeMatrix = aTotal
end function
sub main
const HVS_BEST="8,16,16,16,17,18,21,24,16,16,16,16,17,19,22,25,16,16,17,18,20,22,25,29,16,16,18,21,24,27,31,36,17,17,20,24,30,35,41,47,18,19,22,27,35,44,54,65,21,22,25,31,41,54,70,88,24,25,29,36,47,65,88,115,18,18,18,18,19,21,23,27,18,18,18,18,19,21,24,29,18,18,19,20,22,24,28,32,18,18,20,24,27,30,35,40,19,19,22,27,33,39,46,53,21,21,24,30,39,50,61,73,23,24,28,35,46,61,79,98,27,29,32,40,53,73,98,129"
dim aIntraMatrix
dim aInterMatrix
dim aTotal
dim i
redim aTotal(127)
aIntraMatrix = CalculateAverageMatrix("c:\dctune\intra")
aInterMatrix = CalculateAverageMatrix("c:\dctune\inter")
for i=0 to 63
aTotal(i)=aIntraMatrix(i)
next
for i=0 to 63
aTotal(i+64)=aInterMatrix(i)
next
SaveMatriX NormalizeMatrix(aTotal), "c:\dctune\result.qmatrix"
' Mix with hvs-best
aIntraMatrix = Split(HVS_BEST, ",")
for i=0 to 127
aTotal(i) = (aTotal(i)+aIntraMatrix(i))/2
next
SaveMatriX NormalizeMatrix(aTotal), "c:\dctune\result-mix-with-hvs-best.qmatrix"
MsgBox "Done!"
end sub
CALL Main()
dimzon
28th April 2004, 10:49
"KNOCKIN' ON HEAVEN'S DOOR" movie
http://img10.imageshack.us/img10/3295/frm-000114.png
http://img10.imageshack.us/img10/958/frm-000006.png
most of my frames is more than 600k :(
So I converted them to JPEG @ Q=100%
http://img9.imageshack.us/img9/3395/frm-000088.JPG
http://img7.imageshack.us/img7/1536/frm-000021.JPG
http://img9.imageshack.us/img9/4343/frm-000044.JPG
http://img7.imageshack.us/img7/6242/frm-000169.JPG
http://img10.imageshack.us/img10/1310/frm-000018.JPG
http://img7.imageshack.us/img7/6890/frm-000102.JPG
http://img8.imageshack.us/img8/308/frm-000152.JPG
SoonUDie
28th April 2004, 12:11
Originally posted by dimzon
most of my frames is more than 600k :( In general, jpeg with a very high quality setting will look almost visually identical even at close inspection. PNG is unnecessary unless the differences between frames are extremely close.
dimzon
29th April 2004, 10:41
@All
I can't see difference between Jawor matrix and DCTune matrix (but quantizer values are different):
it's DCTune(1,2)
8,8,8,8,11,16,30,114
8,8,8,8,10,14,25,73
8,8,13,14,20,26,45,151
8,8,14,24,43,63,123,255
12,10,19,38,114,200,255,255
16,12,25,56,208,255,255,255
27,23,44,125,255,255,255,255
85,61,140,255,255,255,255,255
16,16,16,17,29,53,152,255
16,16,18,17,29,48,128,255
16,18,32,39,61,108,255,255
17,17,39,80,181,255,255,255
30,28,57,178,255,255,255,255
48,42,100,255,255,255,255,255
143,117,255,255,255,255,255,255
255,255,255,255,255,255,255,255
It's DCTune(1,2) averaged with HVS-Best-Picture
8,14,14,14,15,18,23,48
14,13,14,14,15,18,23,38
14,14,16,17,20,23,30,61
14,14,17,22,29,36,55,120
16,15,20,28,52,79,135,197
17,17,23,35,81,130,188,231
23,22,30,56,135,190,231,252
40,35,58,114,192,227,251,255
16,16,16,16,20,27,53,138
16,16,16,16,20,26,48,131
16,16,21,23,30,43,84,164
16,16,23,36,62,93,148,193
20,20,29,62,133,166,195,206
26,24,41,95,167,196,212,220
51,45,85,148,195,211,224,237
119,115,157,190,206,220,237,255
It's source.avs
Mpeg2Source("ddn.d2v")
trim(20*25+1,0)
CROP(8,58,-8,-58)
Tweak(sat=1.5, coring=false)
Undot()
LanczosResize(640,384)
removeDirt(show=0)
Undot()
Deen()
VagueDenoiser(threshold=0.8,method=1,nsteps=6,chroma=true)
It's compare.avs
vOriginal =import("c:\dctune\1\source.avs").Subtitle("ORIGINAL").trim(0,-100000)
vHvsGood = aviSource("c:\dctune\1\d640.avi").Subtitle("Jawor_1CD_Matrix").trim(1,-100000)
vDCTune12 = aviSource("c:\dctune\1\d_dctune_12.avi").Subtitle("DCTune(1,2)").trim(1,-100000)
vDCTune12Mix = aviSource("c:\dctune\1\d_dctune_12_mix_hvs_best.avi").Subtitle("DCTune(1,2)+HvsBest").trim(1,-100000)
StackVertical(vOriginal,vHvsGood,vDCTune12,vDCTune12Mix)
SelectEvery(last, 500, 250)
ConvertToRGB24()
ImageWriter(last, file="c:\dctune\1\frm-", start=0, end=0, type="png")
crop(0,0,8,8)
May be anyone can point me on visual diff?
there are frames (jpeg q=100%)
http://img7.imageshack.us/img7/8044/frm-000190.JPG
http://img8.imageshack.us/img8/6242/frm-000169.JPG
http://img9.imageshack.us/img9/4816/frm-000162.JPG
http://img7.imageshack.us/img7/3923/frm-103.JPG
http://img8.imageshack.us/img8/4284/frm-000082.JPG
Maybe I need encode at higher resolution?
it's "KNOCKIN' ON HEAVEN'S DOOR" movie 1hr28m 640x384@1000kbps encode
SoonUDie
29th April 2004, 12:28
How exactly did you combine HVS with your matrices? I was assuming you'd use a standard average, producing a matrix like this (from your numbers):8,12,12,12,14,17,26,69
12,12,12,12,14,17,24,49
12,12,15,16,20,24,35,90
12,12,16,23,34,45,77,146
15,14,20,31,72,118,148,151
17,16,24,42,122,150,155,160
24,23,35,78,148,155,163,172
55,43,85,146,151,160,172,185
17,17,17,18,24,37,88,141
17,17,18,18,24,35,76,142
17,18,26,30,42,66,142,144
18,18,30,52,104,143,145,148
25,24,40,103,144,147,151,154
35,32,62,143,147,153,158,164
83,71,142,145,151,158,167,177
141,142,144,148,154,164,177,192
Which you can see is very different...
Also, when you do your conversion to make the DCTune matrix have 8 in the upper left corner, do you use adding or multiplying? I've been using multiplication.
dimzon
29th April 2004, 12:35
for i=0 to 127
aTotal(i) = (aTotal(i)+aHvsBestatrix(i))/2
next
'Note: The top left value (0, 0) must always be 8
' (may be defined so in the MPEG standard), and other values shall not be below.
rMultiplier = 8/aTotal(0)
for i=0 to 63
aTotal(i)=CLng( rMultiplier * CDbl(aTotal(i)))
if aTotal(i) > 255 then
aTotal(i) = 255
elseif aTotal(i) < 8 then
aTotal(i) = 8
end if
next
'Note: The top left value (0, 0) must always be 16
' (may be defined so in the MPEG standard), and other values shall not be below.
rMultiplier = 16/aTotal(64)
for i=64 to 127
aTotal(i)=CLng( rMultiplier * CDbl(aTotal(i)))
if aTotal(i) > 255 then
aTotal(i) = 255
elseif aTotal(i) < 16 then
aTotal(i) = 16
end if
next
maybe i have incorrect hvs-best-matrix?
8,16,16,16,17,18,21,24
16,16,16,16,17,19,22,25
16,16,17,18,20,22,25,29
16,16,18,21,24,27,31,36
17,17,20,24,30,35,41,47
18,19,22,27,35,44,54,65
21,22,25,31,41,54,70,88
24,25,29,36,47,65,88,115
18,18,18,18,19,21,23,27
18,18,18,18,19,21,24,29
18,18,19,20,22,24,28,32
18,18,20,24,27,30,35,40
19,19,22,27,33,39,46,53
21,21,24,30,39,50,61,73
23,24,28,35,46,61,79,98
27,29,32,40,53,73,98,129
Oh, I know!
My algorythm is
OBTAIN_AVERAGE_DCTUNE
AVERAGE_IT_WITH_HVS_BEST
NORMALIZE_IT
Your algorythm is
OBTAIN_AVERAGE_DCTUNE
NORMALIZE_IT
AVERAGE_IT_WITH_HVS_BEST
Colyptic
29th April 2004, 14:01
Interesting about the DCTune method, I'm one to believe that there is no perfect matrix for every movie out there and this may be a step towards finding the right matrix or at least right kind of matrix for each movie.
However, I ran into an error with calculate.vbs gives me 'Microsoft VBScript error: division by zero line:99 column:1
which I believe is this line:
rMultiplier = 8/aTotal(0)
any help would be appreciated.
dimzon
29th April 2004, 14:05
Originally posted by Colyptic
However, I ran into an error with calculate.vbs gives me 'Microsoft VBScript error: division by zero line:99 column:1
which I believe is this line:
rMultiplier = 8/aTotal(0)
any help would be appreciated.
I think you forgot generate quantizer matrixes by DCTune (c:\dctune\intra or/and c:\dctune\inter is empty)
Read full process cafely (bottom link in my signature)
Colyptic
29th April 2004, 14:13
wow that was a quick reply, I figured out what I was doing wrong. Wasn't entering an integer for extract.bat so avs2avi didn't output any .ppm frames. I was testing with a 15 second clip and assumed leaving out the frame interval would encode the whole thing. But need to use at least 1 there.
dimzon
29th April 2004, 14:15
Originally posted by Colyptic
But need to use at least 1 there.
suggest at least 2.
bill_baroud
29th April 2004, 15:44
interesting thread about DCTune... i'm reading the papers atm, but i didn't find any source code, too bad :/
now i am dreaming of a new first pass in xvid outputting the "best" matrix for the movie :D
SoonUDie
29th April 2004, 15:56
Originally posted by dimzon
Your algorythm is
OBTAIN_AVERAGE_DCTUNE
NORMALIZE_IT
AVERAGE_IT_WITH_HVS_BEST
Correct, because HVS-Best is already "normalized", and if you averaged them before normalizing the DCTune matrix, you wouldn't be "weighing" them equally. You can maintain precision by not rounding off the values until you have the final blended matrix :)
About the 16 in the interframes: I don't know what values are mpeg4 and standalone compliant, but the XviD decoder hasn't had any problems decoding non-16 matrices.
DarkWave
29th April 2004, 16:51
@dimzon & SoonUDie
is it right then to change dimzon´s script like this:
sub main
...
SaveMatriX NormalizeMatrix(aTotal), "c:\dctune\result.qmatrix"
' Mix with hvs-best
aIntraMatrix = Split(HVS_BEST, ",")
aTotal = NormalizeMatrix(aTotal)
for i=0 to 127
aTotal(i) = (aTotal(i)+aIntraMatrix(i))/2
next
SaveMatriX aTotal, "c:\dctune\result-mix-with-hvs-best.qmatrix"
MsgBox "Done!"
end sub
greetz
DarkWave
dimzon
29th April 2004, 16:57
Originally posted by DarkWave
@dimzon & SoonUDie
is it right then to change dimzon´s script like this:
sub main
...
SaveMatriX NormalizeMatrix(aTotal), "c:\dctune\result.qmatrix"
' Mix with hvs-best
aIntraMatrix = Split(HVS_BEST, ",")
aTotal = NormalizeMatrix(aTotal)
for i=0 to 127
aTotal(i) = (aTotal(i)+aIntraMatrix(i))/2
next
SaveMatriX aTotal, "c:\dctune\result-mix-with-hvs-best.qmatrix"
MsgBox "Done!"
end sub
greetz
DarkWave
correct
echo-kk
29th April 2004, 23:43
@dimzon
What would you consider a good 'frame_denominator' value for the resulting matrice to be representative of the movie?
I'm asking because yesterday I encoded a short 3.5min test clip with the following matrices: MPEG, HVS-Best, DCTune(1,1), DCTune(1,2).
The DCTune matrices were calculated for the full movie (without credits) with a frame denominator of 250 (every 10sec - PAL source).
My results: Although the DCTune matrices also did a good job I preferred the MPEG/HVS-Best test clips.
Maybe a frame denominator of 250 simply was to high for this movie (a mixture of quite a lot of still scenes and action mostly taking place in smoke/fog)?
Right now I have set up a new test for a different movie. I'm calculating the matrices with a frame denominator of 50 (every 2sec!) and am planing to encode longer test clips.
I sure hope this test will yield a different result (which I'll post when ready)!
SoonUDie
30th April 2004, 02:57
@echo-kk
Have you tried mixing DCTune(1,1) with HVS-Best? I have found that this seems to produce a high-detailed result with little to no artifacts; in fact it seems to look better than either HVS-Best or DCTune by themselves.
Also, I do not believe DCTune will benefit significantly from increasing the number of shots so much, but I could be wrong... I just don't have the will power to wait for the creation and analysis of >3000 frames :eek:
kilg0r3
30th April 2004, 07:30
The young and wild at work. go Go GO!
CruNcher
30th April 2004, 09:52
The young and wild at work. go Go GO!
yeah but the question is is this scripting marathon worth the effort without one of the Nasa guys Help or the source of dctune somehow i doubt it.
SoonUDie
30th April 2004, 10:09
I have found it useful personally - in 90% of cases where I've tested it, a DCTune(1,1)/HVS matrix will beat out all others at medium to low bitrates.
Tweaking a quantization matrix only provides a small amount of improvement in quality compared to the other steps in making a good encode (filters, other encoding settings, etc.), but maximum quality is my goal, so naturally trying new methods to find better quantizers is important to me :)
echo-kk
1st May 2004, 13:12
Here are the results of my 2nd test with DCTune...
Setup:
704x432 (anamorphic); no Filters; 1000kbps -> 0.138 Bits/(Pixel*Frame).
XviD: Defaults with Adapt. Quant, no packed bitstream, VHQ 4, Chroma Motion & optimizer, 250 max I-frame, Trellis.
Resulting test clips: length 5min (-> 'SelectRangeEvery' with random 10sec long scenes).
DCTune matrices were calculated for the whole movie (except credits) with frame denominators of 50 and 1500. HVS_old refers to dimzon's standard DCTune/HVS-mix calculation; HVS_new to DarkWave's/SoonUDie's proposed script change.
I normally only trust my eyes, so I was quite astonished that the different quality metrics seemed to confirm my (subjective) visual impressions...
avg. overall avg.
SSIM PSNR VQM
MPEG 84.69 46.7491 0.459957
HVS-Best 84.76 46.7466 0.461762
DCTune(1,1)/HVS_old;1500 84.70 46.7375 0.460504
DCTune(1,1)/HVS_old;50 84.69 46.7293 0.461257
DCTune(1,1)/HVS_new;50 84.65 46.6949 0.461896
DCTune(1,1)/HVS_new;1500 84.63 46.6875 0.462485
DCTune(1,1);1500 84.33 46.5404 0.469354
DCTune(1,1);50 84.33 46.5370 0.469403
SSIM, PSNR -> higher is better
VQM -> lower is better
You'll notice that the 'more' DCTune in the matrice the more inferior the result (both visual and mathematical)!
To my surprise DCTune also did not benefit from increasing the number of frames at all. :confused:
In both my tests I preferred the MPEG/HVS-Best clips to the DCTune ones (although the actual perceived quality difference was very small - I had to look very close). This whole idea of generating a special matrice with DCTune sounded very promising but after testing I'll just stick to MPEG or HVS-Best for the time being! :(
@SoonUDiein 90% of cases where I've tested it, a DCTune(1,1)/HVS matrix will beat out all others at medium to low bitratesBeat out all others? What matrices did you compare DCTune(1,1)/HVS to?
I suspect the 'HVS' in your 'DCTune(1,1)/HVS' actually did the job. :D
I just don't have the will power to wait for the creation and analysis of >3000 frames3000 frames? Thats only a single frame every 2 minutes of your source! I wouldn't call a matrice generated from this small amount of data very representative of the specific movie.
Now I 'know' that the 'HVS' in your 'DCTune(1,1)/HVS' actually did the job. ;)
What a pity, this seemed so promising...
Teegedeck
1st May 2004, 14:03
Thanks for your impressive test! Discarding the DCTune concept altogether though seems premature.
echo-kk
1st May 2004, 14:40
Discarding the DCTune concept altogether though seems prematureOf course you're right! Maybe my post sounds to harsh.
I also do believe there still is room for improvement (maybe in the way the original DCTune data is 'averaged', 'weighed' or 'upscaled' to be Xvid conform etc.).
I just meant that I personally won't be using a DCTune generated matrice in its current development state.
Of course I'd be willing to test if someone comes up with some new ideas. :D
Thanks for splitting the thread, I would not have discovered this interesting topic :)
A few remarks first :
- computing an inter matrix with DCTunes is useless. It can only be used to compute an intra matrix.
- So, no need to take sequences of 10 seconds randomly in the movie, it would be better to choose only keyframes.
- dimzon : posting very big pictures is interesting ( though it takes a long time to download ), but it would be even better if you said what was the quantizer used, and if it was I / P or B frames ( I can't see any differences, that's why I ask ). It would be great also if you splitted the pictures, in order us not to have to.
- SoonUDie : don't be so optimistic towards this method. The fact that you need to merge an existing matrix with the one output by DCTunes is a rather disappointing fact.
Now, a few questions, to echo-kk : what was the movie, what was the quant distribution ? Because your results may be simply explained if the bitrate was high for the movie ( since coefficients for the HVS-Best / MPEG matrix are lower than those of the other matrices ).
echo-kk
1st May 2004, 16:52
The fact that you need to merge an existing matrix with the one output by DCTunes is a rather disappointing fact.I completely agree!
a few questions, to echo-kk : what was the movie, what was the quant distribution ? Because your results may be simply explained if the bitrate was high for the movie
Master&Commander (Pal)
480x416 (wanted to test horizontal resizing only) @ 710kbps
-> rather low bitrate, but as you can see from a previous post the results did not substantially differ from my last test, the DCTune clips were inferior!
(Cannot post quant distribution because I didn't take notes and don't have the clips anymore)
Reservoir Dogs (Pal)
704x432 @ 1025kbps -> Bits per Pixel: 0.138
I wouldn't exactly call this a 'high' bitrate for this resolution, but the movie seems to compress very well.
Quant Distribution etc.
MPEG HVS-Best DCTune(1,1)50
I Frames: 1.22% 1.22% 1.22%
P Frames: 37.84% 37.82% 37.88%
B Frames: 60.95% 60.96% 60.90%
Q1&2: 1167 17.3% 1174 17.4% 934 13.9%
Q3: 1225 18.2% 1327 19.7% 1308 19.4%
Q4: 3458 51.3% 3444 51.1% 3209 47.6%
Q5: 891 13.2% 796 11.8% 1239 18.4%
Q6: 48 0.7%
Q7: 3 ~0%
AverageKeyQ: 2.52 2.55 2.95
AverageQ: 3.59 3.56 3.72
This is what DCTune delivered after several hours :D of computing...
DCTune(1,1)50 Matrix
8 8 8 8 8 10 17 162
8 8 8 8 8 8 15 157
8 8 10 10 10 13 38 255
8 8 10 15 25 41 232 255
8 8 12 37 99 255 255 255
13 11 42 181 255 255 255 255
98 116 255 255 255 255 255 255
255 255 255 255 255 255 255 255
16 16 16 16 16 19 35 255
16 16 16 16 16 16 29 255
16 16 19 19 20 27 76 255
16 16 20 30 50 82 255 255
17 16 23 75 199 255 255 255
26 22 84 255 255 255 255 255
196 231 255 255 255 255 255 255
255 255 255 255 255 255 255 255
For me the specially computed matrices produced inferior results in both medium and low bitrate scenarios.
iradic
1st May 2004, 21:33
HI
i dont think these quant stats really show the video quality when we are talking about dctune matrices... beacouse they are optimized - so one (stupid) conclusion is that dctune matrix quants should be higher than ordinary ones - producing visually the same quality at higher quants... this again leave us to our eyes to believe what is better
well opposite opinion is - dctune quants should be lower - and yes this is also true (they can also be the same) - tired of explaining ... but i think you can figure out why... :)
there is a pdf document about dctune algo - http://vision.arc.nasa.gov/publications/icip94.pdf
bye...
vBulletin® v3.8.11, Copyright ©2000-2026, vBulletin Solutions Inc.