컴굥일지

[모션 인식] Teachable Machine으로 자세 추정하기 본문

프로젝트/졸프 - 참여형 동화 서비스

[모션 인식] Teachable Machine으로 자세 추정하기

gyong 2022. 5. 6. 17:30
반응형

1. 모션 인식 - Teachable Machine

모션 인식을 위해 사용해 본 기술들은 아래와 같습니다.

1. Teachable Machine
2. OpenPose (OpenCV) with Python
3. PoseNet with javascript

위의 3가지 중에 가장 쉬운 것은 Teachable Machine이었습니다.

유튜브에서 Teachable Machine을 사용하여 자세 추정을 하는 동영상을 찾았습니다.
이걸 보고 따라 하며 TM 사용법을 알게 되었습니다.

깃허브나 기술 블로그들을 읽는 것도 좋지만, 동영상으로 설명해주는 것이 가장 이해하기 쉬운 것 같아서 아래에 첨부합니다.

https://youtu.be/9SwdGFzFb5Y

(세상에서 가장 쉬운 인공지능 만들기 2탄 | Teachable Machine으로 AI 헬스 트레이너 만들기)

 


2. Teachable Machine 사용 방법

위의 동영상에서 친절하게 다 설명해주지만, 아무래도 글로 적혀있는 것이 정보를 빠르게 훑기에 더 좋겠죠.
아래에 Teachable Machine 사용 방법을 기술해보겠습니다.

 

일단 Teachable Machine을 사용하기 위해 아래 링크로 들어갑니다.

https://teachablemachine.withgoogle.com/

Teachable Machine

그럼 위와 같은 페이지가 보이는데, 시작하기 버튼을 누릅니다.

 

Teachable Machine

우리가 하려는 것은 자세 추정(Pose Estimation)이므로 포즈 프로젝트를 선택합니다.

 

Teachable Machine

위에 보이는 화면에서 분류하고 싶은 자세를 입력하면 됩니다.

Class 1, Class 2의 이름을 우리가 원하는 자세의 이름으로 바꾸고, 사진을 올리면 됩니다.
웹캠으로 바로 사진을 찍을 수도 있고, 이미 있는 사진을 업로드할 수도 있습니다.

업로드가 완료되면 모델 학습하기를 눌러 학습을 진행합니다.

학습이 끝나면 아래와 같은 장면이 나타납니다.

Teachable Machine

모델 내보내기를 누르면 아래와 같은 창이 뜹니다.

 

Teachable Machine

모델 다운로드를 누르고 javascript 코드를 복사해둡니다.

 

이제 학습된 모델을 사용해봅시다.

파일 구조

 

좌측과 같이 index.html 위에서 복사한 javascript 내용을 추가할 겁니다.
그리고 my_model이라는 파일 안에 우리가 받은 모델들을 추가하면 됩니다.

 

아래는 js 내용을 추가한 index.html 파일입니다.

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>motion test1</title>
    </head>
    <body>
        <div>Teachable Machine Pose Model</div>
        <button type="button" onclick="init()">Start</button>
        <div><canvas id="canvas"></canvas></div>
        <div id="label-container"></div>
        <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.3.1/dist/tf.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/@teachablemachine/pose@0.8/dist/teachablemachine-pose.min.js"></script>
        <script type="text/javascript">
            // More API functions here:
            // https://github.com/googlecreativelab/teachablemachine-community/tree/master/libraries/pose

            const URL = "./my_model/"; //모델이 들어있는 파일 이름
            let model, webcam, ctx, labelContainer, maxPredictions;

            async function init() {
                const modelURL = URL + "model.json";
                const metadataURL = URL + "metadata.json";

                model = await tmPose.load(modelURL, metadataURL); //모델 불러오기
                maxPredictions = model.getTotalClasses(); //클래스 이름 받아오기

                // 웹캠 조정하기
                const size = 200;
                const flip = true; // whether to flip the webcam
                webcam = new tmPose.Webcam(size, size, flip); // width, height, flip
                await webcam.setup(); // 웹캠에 접근하기
                await webcam.play(); // 웹캠 play하기
                window.requestAnimationFrame(loop); //계속해서 프레임을 송출하기 위함

                // append/get elements to the DOM
                const canvas = document.getElementById("canvas");
                canvas.width = size;
                canvas.height = size;
                ctx = canvas.getContext("2d");
                labelContainer = document.getElementById("label-container");
                for (let i = 0; i < maxPredictions; i++) {
                    labelContainer.appendChild(document.createElement("div"));
                }
            }

            async function loop(timestamp) {
                webcam.update(); // update the webcam frame
                await predict();
                window.requestAnimationFrame(loop);
            }

            async function predict() {
                //자세 추정하기
                const {pose, posenetOutput} = await model.estimatePose(webcam.canvas);
                const prediction = await model.predict(posenetOutput);

                for (let i = 0; i < maxPredictions; i++) {
                    //추정한 자세와 정확도 나타내기
                    const classPrediction = prediction[i].className + ": " + prediction[i].probability.toFixed(2);
                    labelContainer.childNodes[i].innerHTML = classPrediction;
                }

                drawPose(pose); //웹캠에 자세 skeleton 그리기
            }

            function drawPose(pose) {
                if (webcam.canvas) {
                    ctx.drawImage(webcam.canvas, 0, 0);
                    // draw the keypoints and skeleton
                    if (pose) {
                        const minPartConfidence = 0.5;
                        tmPose.drawKeypoints(pose.keypoints, minPartConfidence, ctx);
                        tmPose.drawSkeleton(pose.keypoints, minPartConfidence, ctx);
                    }
                }
            }
        </script>
    </body>
</html>

 

위의 코드를 쉽게 돌리기 위해 VScode에서 확장 프로그램 Live Server를 다운로드하겠습니다.

Live Server

 

이것을 다운로드하고, 우측 하단의 Go Live 버튼을 누릅니다. 

Live Server - Go Live

 

실행을 하면 아래와 같은 화면이 나타납니다.

Teachable Machine

 

Start 버튼을 누르면 실시간으로 탐지를 해줍니다.
(보니까 아래 화면에서는 클래스가 3개인 모델로 돌렸네요.)

Teachable Machine

 


3. Teachable Machine의 장단점

먼저 Teachable Machine의 장점은 사용하기 쉽다는 것입니다.

학습 데이터를 모으는 것도, 학습을 시키는 것도, 모델을 사용하는 것도 모두 간단합니다.

 

그러나, 사용이 쉬운만큼 단점이 크다고 생각됩니다.

Teachable Machine은 자세가 무조건 미리 만들어진 class들 중에 어디에 가까운지를 판단합니다.
class가 O와 X 단 두 개만 있으면 Teachable Machine에서는 사용자의 자세를 반드시 O와 X 단 두 개로만 판단합니다.
즉, 사용자의 자세가 차렷 자세이더라도 O 또는 X로 판단하는 것입니다.

또한 웹캠으로 사진을 찍어서 업로드를 하는데, 생각보다 조명에 영향을 많이 받는 것 같았습니다.

 


4. 결론

Teachable Machine이 정말 사용하기 간단했지만, 이를 졸업 프로젝트에 사용하기는 어려웠습니다.

그래서 저는 실시간으로 자세를 예측하기 위해 OpenPose를 사용하기로 했습니다.

이와 관련해서 다음 포스트에 적도록 하겠습니다.

반응형
Comments