From 1c6a2d53b8bd4e094f92d89f0386c331b5dd5d5c Mon Sep 17 00:00:00 2001 From: JH Date: Mon, 19 Feb 2024 16:45:47 +0900 Subject: [PATCH 1/7] =?UTF-8?q?feat:=20ml5=20=EC=9E=91=EB=8F=99=ED=99=95?= =?UTF-8?q?=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- index.html | 5 ++ src/App.tsx | 9 +++- src/pages/Home.tsx | 115 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 src/pages/Home.tsx diff --git a/index.html b/index.html index 72429fa..f130495 100644 --- a/index.html +++ b/index.html @@ -5,6 +5,11 @@ 띵똥아 밥먹자 +
diff --git a/src/App.tsx b/src/App.tsx index bad4432..75d7d35 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,10 +1,15 @@ import { app } from './firebase'; import './index.css'; +import { Home } from './pages/Home'; function App() { - console.log(app); + // console.log(app); - return
; + return ( +
+ +
+ ); } export default App; diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx new file mode 100644 index 0000000..459abb7 --- /dev/null +++ b/src/pages/Home.tsx @@ -0,0 +1,115 @@ +import { useEffect, useRef, useState } from 'react'; + +export const Home = () => { + const ref = useRef(null); + const classifier = useRef(null); // classifier 참조 생성 + const [cameraAccess, setCameraAccess] = useState(false); + + const handleGetCamera = () => { + setCameraAccess((prev) => !prev); + }; + + useEffect(() => { + if (cameraAccess) { + getCamera(ref); + + // classifier.current에 값을 할당하기 + const featureExtractor = ml5.featureExtractor('MobileNet', loadReady); + classifier.current = featureExtractor.classification( + ref.current, + videoReady + ); + } else { + if (ref.current && ref.current.srcObject) { + const tracks = (ref.current.srcObject as MediaStream).getTracks(); + tracks.forEach((track) => track.stop()); + ref.current.srcObject = null; + } + } + }, [cameraAccess]); + console.log('classifier', classifier.current); + + const handleAddImage = () => { + // classifier.current를 사용하여 메서드를 호출 + if (classifier.current) { + console.log('이미지 더함', classifier.current); + + classifier.current.addImage('이미지 더함'); + } + }; + + const handleStartTraining = () => { + if (classifier.current) { + classifier.current.train((lossValue) => { + console.log('Loss is', lossValue); + }); + } + }; + + const handleClassify = () => { + if (classifier.current) { + classifier.current.classify((error, result) => { + console.log('result', result); + }); + } + }; + + return ( +
+ + + + + +
+ ); +}; + +const getCamera = async (ref: React.RefObject) => { + const constraints = { video: true }; + try { + const stream = await navigator.mediaDevices.getUserMedia(constraints); + if (ref.current) { + ref.current.srcObject = stream; + } + } catch (error) { + console.error('Error accessing the camera', error); + } +}; + +const startTraining = (classifier) => { + classifier.train((lossValue) => { + if (lossValue) { + console.log('Loss is', lossValue); + } else { + console.log('Training Complete'); + } + }); +}; + +function loadReady() { + console.log('MobileNet ready'); +} +function videoReady() { + console.log('Video ready'); +} From df66b09db7a289a1c5c5cbc42b6121b17a2f19f0 Mon Sep 17 00:00:00 2001 From: JH Date: Tue, 20 Feb 2024 00:23:01 +0900 Subject: [PATCH 2/7] =?UTF-8?q?feat:=20=ED=95=99=EC=8A=B5=20=EA=B0=9C?= =?UTF-8?q?=EC=88=98=20=EC=A0=9C=ED=95=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Home.tsx | 65 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 459abb7..3d794da 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -15,9 +15,10 @@ export const Home = () => { // classifier.current에 값을 할당하기 const featureExtractor = ml5.featureExtractor('MobileNet', loadReady); + const options = { numLabels: 4 }; classifier.current = featureExtractor.classification( ref.current, - videoReady + options ); } else { if (ref.current && ref.current.srcObject) { @@ -27,27 +28,35 @@ export const Home = () => { } } }, [cameraAccess]); - console.log('classifier', classifier.current); - const handleAddImage = () => { + const handleAddImage = (direction: 'left' | 'right' | 'up' | 'down') => { // classifier.current를 사용하여 메서드를 호출 if (classifier.current) { console.log('이미지 더함', classifier.current); - classifier.current.addImage('이미지 더함'); + classifier.current.addImage(direction); } }; const handleStartTraining = () => { if (classifier.current) { + // classifier.current.train((lossValue) => { + // console.log('Loss is', lossValue); + // }); classifier.current.train((lossValue) => { - console.log('Loss is', lossValue); + if (lossValue) { + console.log('Loss is', lossValue); + } else { + console.log('Training Complete'); + } }); } }; const handleClassify = () => { if (classifier.current) { + console.log('Classify', classifier.current); + classifier.current.classify((error, result) => { console.log('result', result); }); @@ -60,13 +69,45 @@ export const Home = () => { - +
+ + + + +
+ @@ -84,7 +191,7 @@ export const Home = () => { onClick={() => { handleAddImage('right'); }} - disabled={!cameraAccess} + disabled={!cameraAccess || !isReadyToCapture} > right @@ -93,7 +200,7 @@ export const Home = () => { onClick={() => { handleAddImage('up'); }} - disabled={!cameraAccess} + disabled={!cameraAccess || !isReadyToCapture} > up @@ -102,55 +209,74 @@ export const Home = () => { onClick={() => { handleAddImage('down'); }} - disabled={!cameraAccess} + disabled={!cameraAccess || !isReadyToCapture} > down +
+ progress {progress} +
+

+ {isCaptured.left && isCaptured.right && isCaptured.up && isCaptured.down + ? '모든 방향을 기억했어요 training 버튼을 눌러주세요' + : '모든 방향을 찍어주세요'} +

+

남은 방향

+

{isCaptured.left ? '' : 'left '}

+

{isCaptured.right ? '' : 'right '}

+

{isCaptured.up ? '' : 'up '}

+

{isCaptured.down ? '' : 'down '}

+

+ {isCaptured.left && isCaptured.right && isCaptured.up && isCaptured.down + ? ' 없음' + : ''} +

+ {/* */} ); }; -const getCamera = async (ref: React.RefObject) => { - const constraints = { video: true }; - try { - const stream = await navigator.mediaDevices.getUserMedia(constraints); - if (ref.current) { - ref.current.srcObject = stream; - } - } catch (error) { - console.error('Error accessing the camera', error); - } -}; - -const startTraining = (classifier) => { - classifier.train((lossValue) => { - if (lossValue) { - console.log('Loss is', lossValue); - } else { - console.log('Training Complete'); - } - }); -}; - -function loadReady() { - console.log('MobileNet ready'); -} -function videoReady() { - console.log('Video ready'); -} +// const getCamera = async (ref: React.RefObject) => { +// const constraints = { video: true }; +// try { +// const stream = await navigator.mediaDevices.getUserMedia(constraints); +// if (ref.current) { +// ref.current.srcObject = stream; +// } +// } catch (error) { +// console.error('Error accessing the camera', error); +// } +// }; From f52d1351b7916a69ff139d64deeb4db74111987b Mon Sep 17 00:00:00 2001 From: JH Date: Mon, 18 Mar 2024 15:01:25 +0900 Subject: [PATCH 4/7] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Home.tsx | 210 +++++++++++++++++++++++---------------------- 1 file changed, 109 insertions(+), 101 deletions(-) diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 71e3dc4..ae4f234 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -1,6 +1,7 @@ import { useEffect, useRef, useState, useCallback } from 'react'; const convertLabelToKeycode = (direction: 'left' | 'right' | 'up' | 'down') => { + // 4. 단순 분류 걍 디렉션 자체를 arrow어쩌구로 바꿔도 될듯 switch (direction) { case 'left': return 'ArrowLeft'; @@ -14,8 +15,10 @@ const convertLabelToKeycode = (direction: 'left' | 'right' | 'up' | 'down') => { return ''; } }; + export const Home = () => { const ref = useRef(null); + const classifyTimeoutRef = useRef(null); const classifier = useRef(null); // classifier 참조 생성 const [isReadyToCapture, setIsReadyToCapture] = useState(false); // 사진을 찍을 수 있는 상태가 되었는지 = loadReady가 준비된 상태 const [cameraAccess, setCameraAccess] = useState(false); @@ -29,7 +32,92 @@ export const Home = () => { const [startClassify, setStartClassify] = useState(false); const [progress, setProgress] = useState(0); + const disableTraining = + !isCaptured.left || !isCaptured.right || !isCaptured.up || !isCaptured.down; + const disableClassify = !isTrained; + const disableClassifyButton = !cameraAccess || !isTrained; + + const handleAddImage = (direction: 'left' | 'right' | 'up' | 'down') => { + // 2. 이미지 등록 + // classifier.current를 사용하여 메서드를 호출 + if (classifier.current) { + console.log('이미지 더함', classifier.current); + setIsCaptured((prev) => ({ ...prev, [direction]: true })); + classifier.current.addImage(direction); + } + }; + + const handleStartTraining = () => { + // 3. 2를 통해 4방향의 이미지 등록이 완료되면 이미지 학습버튼을 누를 수 있음 + if (classifier.current) { + // 푸반: 진행률 눈에 보이는건 어떨까싶어서 걍 지피티한테 수식 만들어달랬더니 이상한 수식 줌 => 학습 진행률 나타내려면 다시 계산해야함ㅋㅋㅋㅋㅋ + const initialLoss = 10; // 학습 시작 시의 초기 loss 값 + const targetLoss = 1; // 목표로 하는 최종 loss 값 + + classifier.current.train((lossValue) => { + if (lossValue) { + console.log('Loss is', lossValue); + // 현재 lossValue를 사용하여 진행률을 계산 + let progress = + ((initialLoss - lossValue) / (initialLoss - targetLoss)) * 100; + progress = Math.min(Math.max(progress, 0), 100); // 진행률이 0과 100 사이의 값이 되도록 조정 + setProgress(progress); + } else { + console.log('Training Complete'); + setProgress(100); // 학습 완료 시 프로그레스를 100%로 설정 + setIsTrained(true); + } + }); + } + }; + + const handleGetCamera = () => { + // 1-1. 카메라 접근 권한 토글 + setCameraAccess((prev) => !prev); + }; + + const loadReady = () => { + //1-3. 카메라 접근 권한 뒤 ml5.featureExtractor('MobileNet', loadReady) 실행 + // MobileNet 모델을 사용하여 featureExtractor를 생성할 수 있는지 확인 + console.log('MobileNet ready'); + setIsReadyToCapture(true); + }; + + const handleToggleClassify = () => { + // 4. 분류기 실행 토글 = 일시중지 버튼 + setStartClassify((prev) => !prev); + }; + + const fireDirection = (direction: 'left' | 'right' | 'up' | 'down') => { + // 4-4. 분류 결과의 레이블을 통해 키보드 이벤트 발생 + const makeKeycode = convertLabelToKeycode(direction); + // 4-5. 키보드 이벤트를 생성하여 document에 디스패치(addEventListener가 아니라 그저 전달중) + document.dispatchEvent(new KeyboardEvent('keydown', { key: makeKeycode })); + }; + + const handleClassify = () => { + // 4-2. 분류기 실행 함수 + if (classifier.current && startClassify) { + classifier.current.classify((error, result) => { + if (error) { + console.error(error); + } else { + console.log('result', result); + // 4-3. 분류 결과를 통해 키보드 이벤트 발생 => + fireDirection(result[0].label); + if (startClassify) { + // 4-7. 일시중지 상태가 아니라면 다시 0.3초 후에 handleClassify 실행 => fireDirection으로 키보드 이벤트 발생 => 반복 + classifyTimeoutRef.current = setTimeout(handleClassify, 300); + // 일단 넘 빨리, 많이 찍혀서 0.3초마다 실행되도록 함 + } + } + }); + } + }; + const getCamera = async (ref: React.RefObject) => { + // 1-2. 카메라 접근 권한 + // 카메라 접근 권한 요청 const constraints = { video: true }; try { const stream = await navigator.mediaDevices.getUserMedia(constraints); @@ -42,10 +130,15 @@ export const Home = () => { }; useEffect(() => { + // 1. 카메라 접근 권한 + // 카메라 접근 버튼 토글마다 실행 if (cameraAccess) { getCamera(ref); const featureExtractor = ml5.featureExtractor('MobileNet', loadReady); + // classifier.current에 featureExtractor.classification() 메서드를 할당 + // numLabels 옵션을 사용하여 분류기가 예측할 레이블 수를 지정 + // 우리는 4개의 방향을 예측하므로 numLabels를 4로 설정 const options = { numLabels: 4 }; classifier.current = featureExtractor.classification( ref.current, @@ -53,6 +146,7 @@ export const Home = () => { ); } else { if (ref.current && ref.current.srcObject) { + // 카메라 접근 권한 해제 시 카메라 스트림 해제 const tracks = (ref.current.srcObject as MediaStream).getTracks(); tracks.forEach((track) => track.stop()); ref.current.srcObject = null; @@ -61,7 +155,20 @@ export const Home = () => { }, [cameraAccess]); useEffect(() => { - // 키보드 이벤트 처리 함수 + // 4-1. 일시중지 상태가 아니라면 handleClassify 분류기 실행 + if (startClassify && isTrained) { + handleClassify(); + } else { + // 분류기 중지, = setTimeout 으로 실행된 handleClassify 함수 중지 + if (classifyTimeoutRef.current !== null) { + clearTimeout(classifyTimeoutRef.current); + classifyTimeoutRef.current = null; + } + } + }, [startClassify, isTrained, handleClassify]); + + useEffect(() => { + // 4-6. addEventListener하여 디스패치된 키보드 이벤트를 처리 const handleKeyPress = (event: KeyboardEvent) => { switch (event.key) { case 'ArrowLeft': @@ -92,84 +199,6 @@ export const Home = () => { }; }, []); - const handleGetCamera = () => { - setCameraAccess((prev) => !prev); - }; - - const handleAddImage = (direction: 'left' | 'right' | 'up' | 'down') => { - // classifier.current를 사용하여 메서드를 호출 - if (classifier.current) { - console.log('이미지 더함', classifier.current); - setIsCaptured((prev) => ({ ...prev, [direction]: true })); - classifier.current.addImage(direction); - } - }; - - const handleStartTraining = () => { - if (classifier.current) { - // 푸반: 진행률 눈에 보이는건 어떨까싶어서 걍 지피티한테 수식 만들어달랬더니 이상한 수식 줌 => 학습 진행률 나타내려면 다시 계산해야함ㅋㅋㅋㅋㅋ - const initialLoss = 10; // 학습 시작 시의 초기 loss 값 - const targetLoss = 1; // 목표로 하는 최종 loss 값 - - classifier.current.train((lossValue) => { - if (lossValue) { - console.log('Loss is', lossValue); - // 현재 lossValue를 사용하여 진행률을 계산 - let progress = - ((initialLoss - lossValue) / (initialLoss - targetLoss)) * 100; - progress = Math.min(Math.max(progress, 0), 100); // 진행률이 0과 100 사이의 값이 되도록 조정 - setProgress(progress); - } else { - console.log('Training Complete'); - setProgress(100); // 학습 완료 시 프로그레스를 100%로 설정 - setIsTrained(true); - } - }); - } - }; - - const handleClassify = () => { - if (classifier.current && isTrained) { - classifier.current.classify((error, result) => { - if (error) { - console.error(error); - } else { - console.log('result', result); - fireDirection(result[0].label); - setTimeout(handleClassify, 300); - } - }); - } - }; - - useEffect(() => { - if (!startClassify) { - console.log('toggle handleClassify'); - handleClassify(); - } - }, [startClassify]); - - const fireDirection = (direction: 'left' | 'right' | 'up' | 'down') => { - console.log('fired!!!!', direction); - const makeKeycode = convertLabelToKeycode(direction); - document.dispatchEvent(new KeyboardEvent('keydown', { key: makeKeycode })); - }; - - const loadReady = () => { - console.log('MobileNet ready'); - setIsReadyToCapture(true); - }; - - const handleToggleClassify = () => { - setStartClassify((prev) => !prev); - }; - - const disableTraining = - !isCaptured.left || !isCaptured.right || !isCaptured.up || !isCaptured.down; - const disableClassify = !isTrained; - - const disableClassifyButton = !cameraAccess || !isTrained; - return (
@@ -254,29 +283,8 @@ export const Home = () => { onClick={handleToggleClassify} disabled={disableClassifyButton} > - Toggle 카메라 인식 + Toggle 일시중지 - {/* */}
); }; - -// const getCamera = async (ref: React.RefObject) => { -// const constraints = { video: true }; -// try { -// const stream = await navigator.mediaDevices.getUserMedia(constraints); -// if (ref.current) { -// ref.current.srcObject = stream; -// } -// } catch (error) { -// console.error('Error accessing the camera', error); -// } -// }; From adffdf7ce904dd455682a968cfd665c8bd52b1dc Mon Sep 17 00:00:00 2001 From: JH Date: Mon, 18 Mar 2024 15:04:04 +0900 Subject: [PATCH 5/7] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=ED=9D=90?= =?UTF-8?q?=EB=A6=84=EC=97=90=20=EB=94=B0=EB=9D=BC=20=ED=95=A8=EC=88=98=20?= =?UTF-8?q?=EC=88=9C=EC=84=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Home.tsx | 115 ++++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 58 deletions(-) diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index ae4f234..d48550a 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -37,6 +37,56 @@ export const Home = () => { const disableClassify = !isTrained; const disableClassifyButton = !cameraAccess || !isTrained; + useEffect(() => { + // 1. 카메라 접근 권한 + // 카메라 접근 버튼 토글마다 실행 + if (cameraAccess) { + getCamera(ref); + + const featureExtractor = ml5.featureExtractor('MobileNet', loadReady); + // classifier.current에 featureExtractor.classification() 메서드를 할당 + // numLabels 옵션을 사용하여 분류기가 예측할 레이블 수를 지정 + // 우리는 4개의 방향을 예측하므로 numLabels를 4로 설정 + const options = { numLabels: 4 }; + classifier.current = featureExtractor.classification( + ref.current, + options + ); + } else { + if (ref.current && ref.current.srcObject) { + // 카메라 접근 권한 해제 시 카메라 스트림 해제 + const tracks = (ref.current.srcObject as MediaStream).getTracks(); + tracks.forEach((track) => track.stop()); + ref.current.srcObject = null; + } + } + }, [cameraAccess]); + const handleGetCamera = () => { + // 1-1. 카메라 접근 권한 토글 + setCameraAccess((prev) => !prev); + }; + + const getCamera = async (ref: React.RefObject) => { + // 1-2. 카메라 접근 권한 + // 카메라 접근 권한 요청 + const constraints = { video: true }; + try { + const stream = await navigator.mediaDevices.getUserMedia(constraints); + if (ref.current) { + ref.current.srcObject = stream; + } + } catch (error) { + console.error('Error accessing the camera', error); + } + }; + + const loadReady = () => { + //1-3. 카메라 접근 권한 뒤 ml5.featureExtractor('MobileNet', loadReady) 실행 + // MobileNet 모델을 사용하여 featureExtractor를 생성할 수 있는지 확인 + console.log('MobileNet ready'); + setIsReadyToCapture(true); + }; + const handleAddImage = (direction: 'left' | 'right' | 'up' | 'down') => { // 2. 이미지 등록 // classifier.current를 사용하여 메서드를 호출 @@ -71,30 +121,11 @@ export const Home = () => { } }; - const handleGetCamera = () => { - // 1-1. 카메라 접근 권한 토글 - setCameraAccess((prev) => !prev); - }; - - const loadReady = () => { - //1-3. 카메라 접근 권한 뒤 ml5.featureExtractor('MobileNet', loadReady) 실행 - // MobileNet 모델을 사용하여 featureExtractor를 생성할 수 있는지 확인 - console.log('MobileNet ready'); - setIsReadyToCapture(true); - }; - const handleToggleClassify = () => { // 4. 분류기 실행 토글 = 일시중지 버튼 setStartClassify((prev) => !prev); }; - const fireDirection = (direction: 'left' | 'right' | 'up' | 'down') => { - // 4-4. 분류 결과의 레이블을 통해 키보드 이벤트 발생 - const makeKeycode = convertLabelToKeycode(direction); - // 4-5. 키보드 이벤트를 생성하여 document에 디스패치(addEventListener가 아니라 그저 전달중) - document.dispatchEvent(new KeyboardEvent('keydown', { key: makeKeycode })); - }; - const handleClassify = () => { // 4-2. 분류기 실행 함수 if (classifier.current && startClassify) { @@ -115,45 +146,6 @@ export const Home = () => { } }; - const getCamera = async (ref: React.RefObject) => { - // 1-2. 카메라 접근 권한 - // 카메라 접근 권한 요청 - const constraints = { video: true }; - try { - const stream = await navigator.mediaDevices.getUserMedia(constraints); - if (ref.current) { - ref.current.srcObject = stream; - } - } catch (error) { - console.error('Error accessing the camera', error); - } - }; - - useEffect(() => { - // 1. 카메라 접근 권한 - // 카메라 접근 버튼 토글마다 실행 - if (cameraAccess) { - getCamera(ref); - - const featureExtractor = ml5.featureExtractor('MobileNet', loadReady); - // classifier.current에 featureExtractor.classification() 메서드를 할당 - // numLabels 옵션을 사용하여 분류기가 예측할 레이블 수를 지정 - // 우리는 4개의 방향을 예측하므로 numLabels를 4로 설정 - const options = { numLabels: 4 }; - classifier.current = featureExtractor.classification( - ref.current, - options - ); - } else { - if (ref.current && ref.current.srcObject) { - // 카메라 접근 권한 해제 시 카메라 스트림 해제 - const tracks = (ref.current.srcObject as MediaStream).getTracks(); - tracks.forEach((track) => track.stop()); - ref.current.srcObject = null; - } - } - }, [cameraAccess]); - useEffect(() => { // 4-1. 일시중지 상태가 아니라면 handleClassify 분류기 실행 if (startClassify && isTrained) { @@ -167,6 +159,13 @@ export const Home = () => { } }, [startClassify, isTrained, handleClassify]); + const fireDirection = (direction: 'left' | 'right' | 'up' | 'down') => { + // 4-4. 분류 결과의 레이블을 통해 키보드 이벤트 발생 + const makeKeycode = convertLabelToKeycode(direction); + // 4-5. 키보드 이벤트를 생성하여 document에 디스패치(addEventListener가 아니라 그저 전달중) + document.dispatchEvent(new KeyboardEvent('keydown', { key: makeKeycode })); + }; + useEffect(() => { // 4-6. addEventListener하여 디스패치된 키보드 이벤트를 처리 const handleKeyPress = (event: KeyboardEvent) => { From 4b7a1fa599bb8fce6a4b78bf0bf11de81ff80e0d Mon Sep 17 00:00:00 2001 From: JH Date: Mon, 18 Mar 2024 15:05:12 +0900 Subject: [PATCH 6/7] =?UTF-8?q?chore:=20=EB=B2=84=ED=8A=BC=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Home.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index d48550a..d72f389 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -273,7 +273,7 @@ export const Home = () => { onClick={handleStartTraining} disabled={!cameraAccess || disableTraining} > - Start Training 트레이닝먼저~ + 1. Start Training 트레이닝먼저~ ); From 4ff14bc1e63cbf17a8dbddce13ed648cf4c615e3 Mon Sep 17 00:00:00 2001 From: JH Date: Mon, 18 Mar 2024 15:13:54 +0900 Subject: [PATCH 7/7] =?UTF-8?q?chore:=20=EC=A3=BC=EC=84=9D=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Home.tsx | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index d72f389..ce3ccdb 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -98,9 +98,10 @@ export const Home = () => { }; const handleStartTraining = () => { - // 3. 2를 통해 4방향의 이미지 등록이 완료되면 이미지 학습버튼을 누를 수 있음 + // 3. 2를 통해 4방향의 이미지 등록이 완료되면 이미지 학습버튼을 누를 수 있음 = 버튼 disabled 속성으로 4개 다 눌러야만 하도록 제한 if (classifier.current) { // 푸반: 진행률 눈에 보이는건 어떨까싶어서 걍 지피티한테 수식 만들어달랬더니 이상한 수식 줌 => 학습 진행률 나타내려면 다시 계산해야함ㅋㅋㅋㅋㅋ + // 여기서부터 const initialLoss = 10; // 학습 시작 시의 초기 loss 값 const targetLoss = 1; // 목표로 하는 최종 loss 값 @@ -118,11 +119,15 @@ export const Home = () => { setIsTrained(true); } }); + // 여기까지가 지피티의 주석 및 계산 코드 } }; const handleToggleClassify = () => { // 4. 분류기 실행 토글 = 일시중지 버튼 + // + // result값이 나옴 => result의 label을 통해 키보드 이벤트 발생시킬 것 + // (지금 화면에 비치는 방향이 어디방향인지, 학습해둔 값을 토대로 result의 label로 분류해줌) setStartClassify((prev) => !prev); }; @@ -134,7 +139,7 @@ export const Home = () => { console.error(error); } else { console.log('result', result); - // 4-3. 분류 결과를 통해 키보드 이벤트 발생 => + // 4-3. 분류 결과를 통해 키보드 이벤트 발생 fireDirection(result[0].label); if (startClassify) { // 4-7. 일시중지 상태가 아니라면 다시 0.3초 후에 handleClassify 실행 => fireDirection으로 키보드 이벤트 발생 => 반복 @@ -160,9 +165,9 @@ export const Home = () => { }, [startClassify, isTrained, handleClassify]); const fireDirection = (direction: 'left' | 'right' | 'up' | 'down') => { - // 4-4. 분류 결과의 레이블을 통해 키보드 이벤트 발생 + // 4-4. 분류 결과의 label을 통해 키보드 이벤트 발생 const makeKeycode = convertLabelToKeycode(direction); - // 4-5. 키보드 이벤트를 생성하여 document에 디스패치(addEventListener가 아니라 그저 전달중) + // 4-5. 키보드 이벤트를 생성하여 document에 디스패치 document.dispatchEvent(new KeyboardEvent('keydown', { key: makeKeycode })); };