[英]infinite requestAnimationFrame Loop in next.js
I am trying to recreate this app in next.js https://codelabs.developers.google.com/tensorflowjs-transfer-learning-teachable-machine#0我正在尝试在next.js https://codelabs.developers.google.com/tensorflowjs-transfer-learning-teachable-machine#0中重新创建此应用程序
To start the data collection, I added a onMouseDown
MouseEvent
on the button which, triggers this code:为了开始数据收集,我在按钮上添加了一个
onMouseDown
MouseEvent
,触发以下代码:
const handleGatherDataForClass: MouseEventHandler = (e) => {
let classNumber = parseInt(e.target.getAttribute('data-1hot'));
console.log('inside EventHandler:', { classNumber });
let state = gatherDataState === STOP_DATA_GATHER ? classNumber : STOP_DATA_GATHER;
console.log({ state });
setGatherDataState(state);
};
Where在哪里
classNumber
= positive integer classNumber
= 正 integer
STOP_DATA_GATHER
= -1
STOP_DATA_GATHER
= -1
gatherDataState
= -1
(default) gatherDataState
= -1
(默认)
Here is the original code snippet from the working app: https://codelabs.developers.google.com/tensorflowjs-transfer-learning-teachable-machine#11这是工作应用程序的原始代码片段: https://codelabs.developers.google.com/tensorflowjs-transfer-learning-teachable-machine#11
After the state of the gatherDataState
variable changes, the useEffect
hook should run the dataGatherLoop
function, which takes frames from the video stream and converts it into tensors:在
gatherDataState
变量的state改变后, useEffect
钩子应该运行dataGatherLoop
function,它从视频ZF7B44CFAFD5C52223D5498196C8A2E7B中取帧并转换成张量:
useEffect(() => {
dataGatherLoop();
}, [gatherDataState]);
function dataGatherLoop() {
console.log('inside Loop: ', {
gatherDataState
});
if (videoPlaying && gatherDataState !== STOP_DATA_GATHER) {
let imageFeatures = tf.tidy(function() {
let videoFrameAsTensor = tf.browser.fromPixels(VIDEO);
let resizedTensorFrame = tf.image.resizeBilinear(
videoFrameAsTensor, [MOBILE_NET_INPUT_HEIGHT, MOBILE_NET_INPUT_WIDTH],
true
);
let normalizedTensorFrame = resizedTensorFrame.div(255);
return mobilenet.predict(normalizedTensorFrame.expandDims()).squeeze();
});
imageFeatures.print();
setTrainData((prev) => ({
trainX: [...prev.trainX, imageFeatures],
trainY: [...prev.trainY, gatherDataState],
}));
// Intialize array index element if currently undefined.
let newCount = [...examplesCount];
if (examplesCount[gatherDataState] === undefined) {
newCount[gatherDataState] = 1;
setExamplesCount(newCount);
} else {
newCount[gatherDataState]++;
setExamplesCount(newCount);
}
window.requestAnimationFrame(dataGatherLoop);
}
}
This loop runs, as long as the gatherDataState
variable is a positive integer (not equal to -1
) After the mouse button is released, an onMouseUp
event is triggered which runs the same handleGatherDataForClass
function as the onMouseDown
event.只要
gatherDataState
变量是正数integer(不等于-1
),此循环就会运行。释放鼠标按钮后,将触发一个onMouseUp
事件,该事件运行与onMouseDown
事件相同的handleGatherDataForClass
function。 This should change the state back to -1
and therefore stop the Loop.这应该将 state 改回
-1
并因此停止循环。
Problem:问题:
Even though the state is changing to -1
after the onMouseUp
event is triggered, the gatherDataState
ends up being a positive integer every time.. Therefore the loop is not stopping.即使在触发
onMouseUp
事件后 state 变为-1
, gatherDataState
最终每次都是正 integer ..因此循环不会停止。 (there is NO setGatherDataState
function anywhere else in the code) (代码中的其他任何地方都没有
setGatherDataState
function)
I tried:我试过了:
gatherDataLoop
function inside the handleGatherDataForClass
event handler and passing the gatherDataState
variable as an argumenthandleGatherDataForClass
事件处理程序中编写gatherDataLoop
function并将gatherDataState
变量作为参数传递gatherDataState
instead of a react state to save the current gatherDataState
gatherDataState
的全局变量而不是反应state来保存当前的gatherDataState
requestAnimationFrame
loop with the cancelAnimationFrame
function (saving the id globally and as state)cancelAnimationFrame
function 取消requestAnimationFrame
循环(全局保存 id 并保存为状态)I am not exactly sure why, but我不确定为什么,但是
worked for me.为我工作。 Here is the code:
这是代码:
const handleGatherDataForClass: MouseEventHandler = (e) => {
let classNumber = parseInt(e.target.getAttribute('data-1hot'));
gatherDataStateRef.current = classNumber;
isCollectingRef.current = !isCollectingRef.current;
if (isCollectingRef.current) {
collectRequestRef.current = requestAnimationFrame(dataGatherLoop);
} else {
cancelAnimationFrame(collectRequestRef.current);
}
};
function dataGatherLoop() {
console.log('inside Loop: ', gatherDataStateRef.current);
let imageFeatures = tf.tidy(function () {
let videoFrameAsTensor = tf.browser.fromPixels(VIDEO);
let resizedTensorFrame = tf.image.resizeBilinear(
videoFrameAsTensor,
[MOBILE_NET_INPUT_HEIGHT, MOBILE_NET_INPUT_WIDTH],
true
);
let normalizedTensorFrame = resizedTensorFrame.div(255);
return mobilenet.predict(normalizedTensorFrame.expandDims()).squeeze();
});
imageFeatures.print();
setTrainData((prev) => ({
trainX: [...prev.trainX, imageFeatures],
trainY: [...prev.trainY, gatherDataStateRef.current],
}));
if (examplesCountRef.current[gatherDataStateRef.current] === undefined) {
examplesCountRef.current[gatherDataStateRef.current] = 1;
} else {
examplesCountRef.current[gatherDataStateRef.current] += 1;
}
collectRequestRef.current = requestAnimationFrame(dataGatherLoop);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.