본문 바로가기
소프트웨어/자바스크립트

[자바스크립트] Droidscript - Tensorflow.js를 이용한 사물인식(Object Detection)

by 만들오 2021. 1. 23.

안녕하세요? 만들오 입니다.

 

오늘은~ Tensorflow.js를 이용해 사물인식을 구현했습니다.

 

대표적인 사물인식 신경망은 YOLO(You Only Look Once)가 있습니다.

 

제가 구현한 것은 SSD(Single Shot MultiBox Detector)방식입니다.

 

카메라가 달려있는 환경이라면 데모를 실행해보셔도 좋습니다.

 

https://sein-oh.github.io/coco_ssd/ (demo)

 

설정이 마무리되지 않아 스마트폰에서는 오류가 발생하니 참고해 주세요.

 

1. 완성 코드

<html>

<head>
    <title>Coco SSD</title>
    <script src="./tf.min.js"> </script>
    <script src="./coco-ssd.js"> </script>
</head>

<body>
    <font color="blue">
        <div id="info">...</div>
    </font>
    <video id="videoInput" width="240" height="320" style="position: absolute; left:10; top:30"></video>
    <canvas id="videoOutput" width="240" height="320" style="position: absolute; left:10; top:30"></canvas>
    <script>
        const info = document.getElementById("info");
        const constraints = { audio: false, video: true };
        const video = document.getElementById("videoInput");
        function successCallback(stream) {
            video.srcObject = stream;
            video.play();
        }
        function errorCallback(error) {
            console.log(error);
        }
        navigator.getUserMedia(constraints, successCallback, errorCallback);
        let net;
        async function makeNet() {
            info.innerHTML = "Now loading... Please wait.";
            net = await cocoSsd.load();
            info.innerHTML = "Ready to use!";
            setInterval(detect, 0);
        }
        makeNet();
        let predict;
        const canvas = document.getElementById("videoOutput");
        const ctx = canvas.getContext("2d");
        ctx.strokeStyle = "rgb(0, 255, 0)";
        ctx.fillStyle = "rgb(0, 255, 0)";
        ctx.lineWidth = 2;
        ctx.font = "15px Arial";
        async function detect() {
            predict = await net.detect(video);
            info.innerHTML = "Object No. : " + predict.length;
            if (predict.length > 0) {
                ctx.clearRect(0, 0, canvas.clientWidth, canvas.clientHeight);
                for (let i = 0; i < predict.length; i++) {
                    ctx.fillText(predict[i].class, predict[i].bbox[0] + 5, predict[i].bbox[1] + 15);
                    ctx.strokeRect(predict[i].bbox[0], predict[i].bbox[1], predict[i].bbox[2], predict[i].bbox[3]);
                }
            }
        }
    </script>
</body>

</html>

tf.min.js 파일과 coco-ssd.js 파일은 다음 링크에서 받아 위 코드가 있는 html파일과 같은 경로에 저장해주세요.

https://github.com/Sein-Oh/coco_ssd

 

2. 코드 설명

<script src="./tf.min.js"> </script>
<script src="./coco-ssd.js"> </script>

  위 스크립트 태그는 tensorflow.js와 coco-ssd를 불러오는 코드입니다. 저는 파일로 저장해서 사용했지만 다음과 같이 코드상에서 바로 다운받아 사용할 수도 있습니다.

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"> </script>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/coco-ssd"> </script>

 

보통은 video 화면을 숨기고, video를 복사한 canvas 엘리먼트를 이용해 영상을 보여줍니다.

하지만 노트8이 성능이 나쁜편은 아닌데 뚝뚝 끊기는 느낌이 들더군요...

결국 video 화면과 canvas를 겹쳐두고 canvas에는 사각형만 그리도록 했습니다.

다음 코드는 video와 canvas를 절대위치로 지정하여 겹치도록 설정한 코드입니다.

<video id="videoInput" width="240" height="320" style="position: absolute; left:10; top:30"></video>
<canvas id="videoOutput" width="240" height="320" style="position: absolute; left:10; top:30"></canvas>

사실 Html/Css/Javascript탭에 있는 내용과 99% 동일한 코드입니다. 차이점은 vidoe와 canvas의 width, height값이 다른건데요, 사실은 javascirpt를 이용해 접속 환경에 따라 수정하도록 코드를 수정하면 되지만 아직 수정하지 못했습니다.

 

 

3. 마무리

  머신러닝 라이브러리의 대표인 tensorflow의 javascript 버전인 tensorflow.js는 파이썬의 keras와 유사합니다.

기타 문의사항은 댓글 바랍니다. 감사합니다.

 

* 이 글은 티스토리 카카오계정 연동정책으로 인해 이전 블로그(오코취) 글을 옮겨왔습니다.

[].

728x90

댓글