Private
Public Access
Release 0.12.0
This commit is contained in:
1 parent
f74a658097
commit
7f6eeab39e
48 files changed
+3617
-1266
No files matched your search
+78
-32
@@ -1,35 +1,81 @@
|
||||
/* Pure measurement processing; the video uses 32 clockwise edge patches. */
|
||||
function calibrationFit(baseline,patches,model){
|
||||
if(!model || baseline.length!==16 || patches.length!==32)throw new Error('Incomplete calibration measurements.');
|
||||
var candidates=[],edges=[0,0,0,0];
|
||||
for(var region=0;region<16;region++){
|
||||
var responses=patches.map(function(p){if(!p || p.length!==16)throw new Error('Missing video measurements.');return Math.max(0,p[region]-baseline[region]);});
|
||||
var peak=Math.max.apply(Math,responses),best=responses.indexOf(peak);
|
||||
if(peak<8)continue;
|
||||
// Reject regions responding equally around the screen (global histograms).
|
||||
var strong=responses.filter(function(v){return v>=peak*.65;}).length;
|
||||
if(strong>10)continue;
|
||||
var distant=responses.some(function(v,i){var d=Math.min(Math.abs(i-best),32-Math.abs(i-best));return v>=peak*.65 && d>6;});
|
||||
if(distant)continue;
|
||||
var sum=0,weighted=0;
|
||||
for(var offset=-3;offset<=3;offset++){
|
||||
var index=(best+offset+32)%32,weight=Math.max(0,responses[index]-peak*.35);
|
||||
weighted+=offset*weight;sum+=weight;
|
||||
}
|
||||
var position=((best+.5+weighted/sum)/8+4)%4;
|
||||
candidates.push({position:position,region:region,score:peak/strong});
|
||||
}
|
||||
// Nested LG regions can measure the same edge position. Keep the most
|
||||
// localized response rather than making duplicate interpolation anchors.
|
||||
candidates.sort(function(a,b){return b.score-a.score || a.region-b.region;});
|
||||
var points=[];
|
||||
candidates.forEach(function(p){if(points.some(function(q){var d=Math.abs(p.position-q.position);return Math.min(d,4-d)<.06;}))return;points.push({position:p.position,region:p.region});edges[Math.floor(p.position)]++;});
|
||||
points.sort(function(a,b){return a.position-b.position;});
|
||||
if(points.length<4 || edges.some(function(n){return !n;}))throw new Error('No reliable spatial response on every edge. Keep the video full-screen; this TV may not expose local histogram regions. Your saved profile is unchanged.');
|
||||
return {model:model,points:points};
|
||||
function calibrationFit(baseline, patches, model) {
|
||||
if (!model || baseline.length !== 16 || patches.length !== 32) throw new Error('Incomplete calibration measurements.');
|
||||
var candidates = [],
|
||||
edges = [0, 0, 0, 0];
|
||||
for (var region = 0; region < 16; region++) {
|
||||
var responses = patches.map(function(p) {
|
||||
if (!p || p.length !== 16) throw new Error('Missing video measurements.');
|
||||
return Math.max(0, p[region] - baseline[region]);
|
||||
});
|
||||
var peak = Math.max.apply(Math, responses),
|
||||
best = responses.indexOf(peak);
|
||||
if (peak < 8) continue;
|
||||
// Reject regions responding equally around the screen (global histograms).
|
||||
var strong = responses.filter(function(v) {
|
||||
return v >= peak * .65;
|
||||
}).length;
|
||||
if (strong > 10) continue;
|
||||
var distant = responses.some(function(v, i) {
|
||||
var d = Math.min(Math.abs(i - best), 32 - Math.abs(i - best));
|
||||
return v >= peak * .65 && d > 6;
|
||||
});
|
||||
if (distant) continue;
|
||||
var sum = 0,
|
||||
weighted = 0;
|
||||
for (var offset = -3; offset <= 3; offset++) {
|
||||
var index = (best + offset + 32) % 32,
|
||||
weight = Math.max(0, responses[index] - peak * .35);
|
||||
weighted += offset * weight;
|
||||
sum += weight;
|
||||
}
|
||||
var position = ((best + .5 + weighted / sum) / 8 + 4) % 4;
|
||||
candidates.push({
|
||||
position: position,
|
||||
region: region,
|
||||
score: peak / strong
|
||||
});
|
||||
}
|
||||
// Nested LG regions can measure the same edge position. Keep the most
|
||||
// localized response rather than making duplicate interpolation anchors.
|
||||
candidates.sort(function(a, b) {
|
||||
return b.score - a.score || a.region - b.region;
|
||||
});
|
||||
var points = [];
|
||||
candidates.forEach(function(p) {
|
||||
if (points.some(function(q) {
|
||||
var d = Math.abs(p.position - q.position);
|
||||
return Math.min(d, 4 - d) < .06;
|
||||
})) return;
|
||||
points.push({
|
||||
position: p.position,
|
||||
region: p.region
|
||||
});
|
||||
edges[Math.floor(p.position)]++;
|
||||
});
|
||||
points.sort(function(a, b) {
|
||||
return a.position - b.position;
|
||||
});
|
||||
if (points.length < 4 || edges.some(function(n) {
|
||||
return !n;
|
||||
})) throw new Error('No reliable spatial response on every edge. Keep the video full-screen; this TV may not expose local histogram regions. Your saved profile is unchanged.');
|
||||
return {
|
||||
model: model,
|
||||
points: points
|
||||
};
|
||||
}
|
||||
function calibrationLuma(regions){return regions.map(function(c){return (c[0]+c[1]+c[2])/3;});}
|
||||
function calibrationAverage(samples){
|
||||
if(samples.length<3)throw new Error('Not enough fresh histogram samples. Keep the app visible and repeat calibration.');
|
||||
return samples[0].map(function(_,r){return samples.reduce(function(sum,s){return sum+s[r];},0)/samples.length;});
|
||||
|
||||
function calibrationLuma(regions) {
|
||||
return regions.map(function(c) {
|
||||
return (c[0] + c[1] + c[2]) / 3;
|
||||
});
|
||||
}
|
||||
|
||||
function calibrationAverage(samples) {
|
||||
if (samples.length < 3) throw new Error('Not enough fresh histogram samples. Keep the app visible and repeat calibration.');
|
||||
return samples[0].map(function(_, r) {
|
||||
return samples.reduce(function(sum, s) {
|
||||
return sum + s[r];
|
||||
}, 0) / samples.length;
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user