Он обнаруживается при отладке с помощью функции debug (). Предположим, вы хотите увидеть базовый код в функции транспонирования t (). Просто набрав «t», не обнаруживается много.
>t
function (x)
UseMethod("t")
<bytecode: 0x000000003085c010>
<environment: namespace:base>
Но, используя «debug (functionName)», он показывает базовый код, без внутренних элементов.
> debug(t)
> t(co2)
debugging in: t(co2)
debug: UseMethod("t")
Browse[2]>
debugging in: t.ts(co2)
debug: {
cl <- oldClass(x)
other <- !(cl %in% c("ts", "mts"))
class(x) <- if (any(other))
cl[other]
attr(x, "tsp") <- NULL
t(x)
}
Browse[3]>
debug: cl <- oldClass(x)
Browse[3]>
debug: other <- !(cl %in% c("ts", "mts"))
Browse[3]>
debug: class(x) <- if (any(other)) cl[other]
Browse[3]>
debug: attr(x, "tsp") <- NULL
Browse[3]>
debug: t(x)
EDIT: debugonce () выполняет то же самое без использования undebug ()
Вероятно, вам нужен только лучший алгоритм. [1]
В принципе вам просто понадобится colorpicker и выберите самый легкий и самые темные значения из видео (помещая значения RGB в переменные l_ и d_ соответственно). Вы можете отрегулировать допуск немного, если вам нужно, но получение значений l_ и r_ сразу же путем выбора разных областей с помощью выбора цвета даст вам лучший ключ.
let l_r = 131,
l_g = 190,
l_b = 137,
d_r = 74,
d_g = 148,
d_b = 100;
let tolerance = 0.05;
let processor = {
timerCallback: function() {
if (this.video.paused || this.video.ended) {
return;
}
this.computeFrame();
let self = this;
setTimeout(function () {
self.timerCallback();
}, 0);
},
doLoad: function() {
this.video = document.getElementById("video");
this.c1 = document.getElementById("c1");
this.ctx1 = this.c1.getContext("2d");
this.c2 = document.getElementById("c2");
this.ctx2 = this.c2.getContext("2d");
let self = this;
this.video.addEventListener("play", function() {
self.width = self.video.videoWidth;
self.height = self.video.videoHeight;
self.timerCallback();
}, false);
},
calculateDistance: function(c, min, max) {
if(c < min) return min - c;
if(c > max) return c - max;
return 0;
},
computeFrame: function() {
this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
let frame = this.ctx1.getImageData(0, 0, this.width, this.height);
let l = frame.data.length / 4;
for (let i = 0; i < l; i++) {
let _r = frame.data[i * 4 + 0];
let _g = frame.data[i * 4 + 1];
let _b = frame.data[i * 4 + 2];
let difference = this.calculateDistance(_r, d_r, l_r) +
this.calculateDistance(_g, d_g, l_g) +
this.calculateDistance(_b, d_b, l_b);
difference /= (255 * 3); // convert to percent
if (difference < tolerance)
frame.data[i * 4 + 3] = 0;
}
this.ctx2.putImageData(frame, 0, 0);
return;
}
};
// :/
Если производительность не имеет значения, вы можете работать в другом цветовом пространстве, например. HSV. Вы можете использовать левый верхний пиксель в качестве ссылки.
Вы сравниваете значение цветового тона контрольной точки со значением цветового тона других пикселями, и исключить все пиксели, которые превышают определенный порог и темные и светлые области, используя насыщенность и значение .
Это, как никогда не полностью избавляется от цветного кровотечения, вам может потребоваться некорректное / десатурация цвета.
function rgb2hsv () {
var rr, gg, bb,
r = arguments[0] / 255,
g = arguments[1] / 255,
b = arguments[2] / 255,
h, s,
v = Math.max(r, g, b),
diff = v - Math.min(r, g, b),
diffc = function(c){
return (v - c) / 6 / diff + 1 / 2;
};
if (diff == 0) {
h = s = 0;
} else {
s = diff / v;
rr = diffc(r);
gg = diffc(g);
bb = diffc(b);
if (r === v) {
h = bb - gg;
}else if (g === v) {
h = (1 / 3) + rr - bb;
}else if (b === v) {
h = (2 / 3) + gg - rr;
}
if (h < 0) {
h += 1;
}else if (h > 1) {
h -= 1;
}
}
return {
h: Math.round(h * 360),
s: Math.round(s * 100),
v: Math.round(v * 100)
};
}
let processor = {
timerCallback: function() {
if (this.video.paused || this.video.ended) {
return;
}
this.computeFrame();
let self = this;
setTimeout(function () {
self.timerCallback();
}, 0);
},
doLoad: function() {
this.video = document.getElementById("video");
this.c1 = document.getElementById("c1");
this.ctx1 = this.c1.getContext("2d");
this.c2 = document.getElementById("c2");
this.ctx2 = this.c2.getContext("2d");
let self = this;
this.video.addEventListener("play", function() {
self.width = self.video.videoWidth / 2;
self.height = self.video.videoHeight / 2;
self.timerCallback();
}, false);
},
computeFrame: function() {
this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
let frame = this.ctx1.getImageData(0, 0, this.width, this.height);
let l = frame.data.length / 4;
let reference = rgb2hsv(frame.data[0], frame.data[1], frame.data[2]);
for (let i = 0; i < l; i++) {
let r = frame.data[i * 4 + 0];
let g = frame.data[i * 4 + 1];
let b = frame.data[i * 4 + 2];
let hsv = rgb2hsv(r, g, b);
let hueDifference = Math.abs(hsv.h - reference.h);
if( hueDifference < 20 && hsv.v > 50 && hsv.s > 50 ) {
frame.data[i * 4 + 3] = 0;
}
}
this.ctx2.putImageData(frame, 0, 0);
return;
}
};