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 Development

Reply
 
Thread Tools Search this Thread Display Modes
Old 19th July 2011, 08:58   #1  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,862
Findtweak histogram matcher

This script finds the equivalent tweak statement to match two images. It's useful if there's a known transformation which is constant for the whole clips, such as two captures of the same video with different procamp settings.
It currently has a lot of problems and I'm open to comments.
Code:
#findtweak 0.1 by jmac
#Find brightness and contrast transformation
#requires masktools.  Doesn't work on real clips due to clipping. Crashes on monocolored clips.
#Two clips must be geometrically aligned. Will be confused by gamma.
#works by partitioning the clips into dim and bright pixels
#By using two measurements between original and tweaked you can find contrast and brightness
blankclip(length=99,width=64,pixel_type="YV12")
a=mt_lutspa(last,mode="absolute",expr="x 16 +")#ramp 16-79, avg=47.5
b=a.tweak(bright=15,cont=2.0,coring=false)#31-157, avg=94
cont=findtweak(a,b,0)
bright=findtweak(a,b,1)
stackhorizontal(b,a.tweak(bright=bright,cont=cont))
subtitle("Cont="+string(cont))
subtitle(y=20," Bright="+string(bright))

function findtweak(clip a, clip b, int parm){
  current_frame=0
  ma=a.averageluma
  mb=b.averageluma
  x1=trueavg(a,"<=",ma)
  x2=trueavg(a,">",ma)
  y1=trueavg(b,"<=",mb)
  y2=trueavg(b,">",mb)
  #in the test clip, looking for true avg of 31.5 (16-47), but half the pixels are 0 (or 1)
  #upper half is avg=63.5 (48-79)
  #tweaked values gives 62,127
  k=(y2-y1)/(x2-x1)
  b=(y1-16)-(x1-16)*k
  parm==0?k:b
}

function trueavg(clip a, string op, float luma){
#Return average of all pixels op luma *while ignoring others in the calculation*
#Do this by finding avg(x op luma ? x:1)-avg(x op luma ? x:0) etc.
  current_frame=0
  m0=mt_lut(a,expr="x "+string(luma)+" "+op+" x 0 ?").averageluma
  m1=mt_lut(a,expr="x "+string(luma)+" "+op+" x 1 ?").averageluma
  m0/(m1-m0)
}
jmac698 is offline   Reply With Quote
Old 19th July 2011, 10:36   #2  |  Link
Gavino
Avisynth language lover
 
Join Date: Dec 2007
Location: Spain
Posts: 3,423
I think your trueavg function is wrong.
It seems to me it returns (total luma of pixels meeting condition)/(no of pixels not meeting condition).
I think it should be
Code:
function trueavg(clip a, string op, float luma){
  current_frame=0
  m0=mt_lut(a,expr="x "+string(luma)+" "+op+" x 0 ?").averageluma
  m1=mt_lut(a,expr="x "+string(luma)+" "+op+" 1 0 ?").averageluma
  m0/m1
}
__________________
GScript and GRunT - complex Avisynth scripting made easier
Gavino is offline   Reply With Quote
Old 19th July 2011, 17:33   #3  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,862
Good point. I was finding sum/n/maskedcount/n and if half the pixels are masked I get sum/n*2=trueavg so in testing if gives the right answer (in any case the pixels are partitioned in half). You are just finding unmaskedcount/n which is direct (sum/n/unmaskedcount/n=sum/unmaskedcount=trueavg)
e.g. if you have
Quote:
x x x x 0 0 0 0
obviously you always have half the trueavg.
jmac698 is offline   Reply With Quote
Old 2nd February 2017, 03:09   #4  |  Link
StainlessS
HeartlessS Usurer
 
StainlessS's Avatar
 
Join Date: Dec 2009
Location: Over the rainbow
Posts: 10,436
Moved here from this thread:- http://forum.doom9.org/showthread.ph...56#post1795556

JMac698,

Been playing with your FindTweak(), was driving me nuts trying to figure it out, finally twigged that the initial test conversion was done
with Tweak(...,coring=false) and result was for Tweak(...,coring=true) [which accounts for all of the seemingly wrong numbers in comments,
which refer to input Y values after reduction by 16 due to coring].
Was very perplexing having Tweak(bright=15,cont=2.0,coring=false) and Tweak(bright=31,cont=2.0) coming out identical, until I realized was due the default coring=true [I know it looks obvious there, but comparing result clip variable of first with second some distance away kind of obscured it].
Anyways, thought it might be a good idea to point that out in the thread, save someone else going bananas.
Also would need some modification to work (at all) with RGB as suggested in your above post [EDIT: in above linked thread].
EDIT: Not to mention that RGB does not directly work with Tweak anyway, would need conversion to eg Y8 and would then suffer from
the coring stuff.

EDIT: I also tried with Gavino suggested mod and got identical results to your script.

EDIT: Could YPlaneMedian be in some way of use in your script ?
Implemented as YPlaneMin(Threshold=50.0),
Lowest pixel value whose cumulative population (including population of all lower value pixels) is greater than 50.0%.

EDIT: Your script with some debug stuff left in, perhaps of use if you plan to mod the script.
Code:
# findtweak 0.1 by jmac, https://forum.doom9.org/showthread.php?t=161960
# Find brightness and contrast transformation
# requires masktools.  Doesn't work on real clips due to clipping. Crashes on monocolored clips.
# Two clips must be geometrically aligned. Will be confused by gamma.
# works by partitioning the clips into dim and bright pixels
# By using two measurements between original and tweaked you can find contrast and brightness
blankclip(length=99,width=64,pixel_type="YV12")
a=mt_lutspa(last,mode="absolute",expr="x 16 +",chroma="128") #ramp 16-79, avg=47.5
RT_DebugF("A) YMin=%d YMax=%d YAve=%f",a.RT_YPlaneMin(0),a.RT_YPlaneMax(0),a.RT_AverageLuma(0))  # 16,79,47.5
b=a.tweak(bright=15,cont=2.0,coring=false)                   #31-157, avg=94
RT_DebugF("B) YMin=%d YMax=%d YAve=%f",b.RT_YPlaneMin(0),b.RT_YPlaneMax(0),b.RT_AverageLuma(0))  # 47,173,110.0
cont=findtweak(a,b,0)
bright=findtweak(a,b,1)
stackhorizontal(b,a.tweak(bright=bright,cont=cont))
subtitle("Cont="+string(cont))
subtitle(y=20," Bright="+string(bright))

function findtweak(clip a, clip b, int parm){
  current_frame=0
  ma=a.averageluma
  mb=b.averageluma
  x1=trueavg(a,"<=",ma)     
  x2=trueavg(a,">",ma)
  y1=trueavg(b,"<=",mb)
  y2=trueavg(b,">",mb)
  #in the test clip, looking for true avg of 31.5 (16-47), but half the pixels are 0 (or 1)
  #upper half is avg=63.5 (48-79)
  #tweaked values gives 62,127
  k=(y2-y1)/(x2-x1)
  b=(y1-16)-(x1-16)*k
  RT_DebugF("X1=%f X2=%f Y1=%f Y2=%f K=%f B=%f",x1,x2,y1,y2,k,b)
  parm==0?k:b
}

function trueavg(clip a, string op, float luma){
#Return average of all pixels op luma *while ignoring others in the calculation*
#Do this by finding avg(x op luma ? x:1)-avg(x op luma ? x:0) etc.
  current_frame=0
  m0=mt_lut(a,expr="x "+string(luma)+" "+op+" x 0 ?").averageluma
  m1=mt_lut(a,expr="x "+string(luma)+" "+op+" x 1 ?").averageluma
  RT_DebugF("Op='%s' M0=%f M1=%f : m0/(m1-m0)=%f",op,m0,m1, m0/(m1-m0))  m0/(m1-m0)
# Gavino Mod
#  m1=mt_lut(a,expr="x "+string(luma)+" "+op+" 1 0 ?").averageluma
#  RT_DebugF("Op='%s' M0=%f M1=%f : m0/m1=%f",op,m0,m1, m0/m1)  m0/m1
}
And the Debug output
Code:
00000003    0.40231544  [3640] RT_DebugF: A) YMin=16 YMax=79 YAve=47.500000 
00000004    0.40702322  [3640] RT_DebugF: B) YMin=47 YMax=173 YAve=110.000000   
00000005    0.41002613  [3640] RT_DebugF: Op='<=' M0=15.750000 M1=16.250000 : m0/(m1-m0)=31.500000  
00000006    0.41226628  [3640] RT_DebugF: Op='>' M0=31.750000 M1=32.250000 : m0/(m1-m0)=63.500000   
00000007    0.41454145  [3640] RT_DebugF: Op='<=' M0=39.000000 M1=39.500000 : m0/(m1-m0)=78.000000  
00000008    0.41686803  [3640] RT_DebugF: Op='>' M0=71.000000 M1=71.500000 : m0/(m1-m0)=142.000000  
00000009    0.41699862  [3640] RT_DebugF: X1=31.500000 X2=63.500000 Y1=78.000000 Y2=142.000000 K=2.000000 B=31.000000   

REPEATED:
00000005    0.41002613  [3640] RT_DebugF: Op='<=' M0=15.750000 M1=16.250000 : m0/(m1-m0)=31.500000  
00000006    0.41226628  [3640] RT_DebugF: Op='>' M0=31.750000 M1=32.250000 : m0/(m1-m0)=63.500000   
00000007    0.41454145  [3640] RT_DebugF: Op='<=' M0=39.000000 M1=39.500000 : m0/(m1-m0)=78.000000  
00000008    0.41686803  [3640] RT_DebugF: Op='>' M0=71.000000 M1=71.500000 : m0/(m1-m0)=142.000000  
00000009    0.41699862  [3640] RT_DebugF: X1=31.500000 X2=63.500000 Y1=78.000000 Y2=142.000000 K=2.000000 B=31.000000
__________________
I sometimes post sober.
StainlessS@MediaFire ::: AND/OR ::: StainlessS@SendSpace

"Some infinities are bigger than other infinities", but how many of them are infinitely bigger ???

Last edited by StainlessS; 2nd February 2017 at 04:07.
StainlessS is offline   Reply With Quote
Old 2nd February 2017, 12:04   #5  |  Link
vcmohan
Registered User
 
Join Date: Jul 2003
Location: India
Posts: 889
My HistograAdjust plugin for avisynth 2.6 or Histogram function of modPlus plugin for newer avisynth+ has a facility to match with a specified frame of any (other ) clip.
__________________
mohan
my plugins are now hosted here
vcmohan is offline   Reply With Quote
Old 3rd February 2017, 23:32   #6  |  Link
jmac698
Registered User
 
Join Date: Jan 2006
Posts: 1,862
@stainlessS
Thanks for pointing that out. I really need to finish this.
Also I realized I couldn't do this in rgb afterwards, but perhaps it could be done in saturation domain as well.

@vcmohan
I have a specific purpose in mind for this. It's not just for matching, but matching under a particular model, that is the classical analog tint/sat/bright/cont model. A very particular use is matching two recordings with different procamp settings. I looked at the datasheets of some decoder chips and tested this, and found the digital model. Besides matching captures, you can of course find the best constrained match with old video edited sources. I'm assuming the edit equipment of the time used this model. There were some other ones I read about for primitive colour grading at the time. They were based on simple mixing models (multiplies) in certain transformed domains (like y pb pbr, rgb, etc.).
jmac698 is offline   Reply With Quote
Reply

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 20:47.


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