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

[자바스크립트] Droidscript - 물체추적(Object tracking) 앱 만들기

by 만들오 2021. 1. 23.

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

 

Html/Css/Javascirpt로 구현한 물체추적 프로젝트를 Droidscript로 바꾸어 보았습니다.

 

https://sein-oh.github.io/LK_track/ -> (사용 예제)

 

My LK Tracker

 

sein-oh.github.io

1. 완성 코드

1.1. App이름.html 예) LK_track.html

<!DOCTYPE html>
<html>
<head>
 <meta charset="utf-8">
 <title>My LK Tracker</title>
 <script type="text/javascript" src="jsfeat-min.js"></script>
</head>
<body>
 <p id="mousePos">Mouse :</p>
 <video id="webcam" width="395" height="395" style="display:none;"></video>
 <canvas id="canvas" width="395" height="395"></canvas>
</body>

<script type="text/javascript">
 let w = 395;
 let h = 395;
  var video = document.getElementById("webcam");
  navigator.mediaDevices.getUserMedia({ video: {facingMode: { exact: "environment" },width: {exact: w}, height:{exact:h}}, audio: false }).then(function(stream){
	video.srcObject = stream;
	video.play();
	}).catch(function(err){
		console.log("An error occured! " + err);
  });
  /*
 let video = document.getElementById("webcam");
 navigator.mediaDevices.getUserMedia({ video: true, audio: false }).then(function(stream){
  video.srcObject = stream;
  video.play();
 }).catch(function(err){
  console.log("An error occured! " + err);
 });
 */
 
 let canvas = document.getElementById('canvas');
 let canvasPos = canvas.getBoundingClientRect();
 canvas.addEventListener("mousedown", canvasDown);
 
 let ctx = canvas.getContext("2d");
 ctx.fillStyle = "rgb(0,0,255)";
 ctx.strokeStyle = "rgb(0,0,0)";

 let curr_img_pyr = new jsfeat.pyramid_t(3);
 let prev_img_pyr = new jsfeat.pyramid_t(3);
 curr_img_pyr.allocate(w, h, jsfeat.U8_t|jsfeat.C1_t);
 prev_img_pyr.allocate(w, h, jsfeat.U8_t|jsfeat.C1_t);
 
 let point_count = 0;
 let maxPoints = 50;
 let point_status = new Uint8Array(maxPoints);
 let prev_xy = new Float32Array(maxPoints*2);
 let curr_xy = new Float32Array(maxPoints*2);

 let win_size = 20;
 let max_iterations = 30;
 let epsilon = 0.01;
 let min_eigen = 0.001;

 function processVideo(){
  ctx.drawImage(video, 0, 0, w, h);
  let imageData = ctx.getImageData(0, 0, w, h);

  //swap flow data
  let _pt_xy = prev_xy;
  prev_xy = curr_xy;
  curr_xy = _pt_xy;
  let _pyr = prev_img_pyr;
  prev_img_pyr = curr_img_pyr;
  curr_img_pyr = _pyr;

  jsfeat.imgproc.grayscale(imageData.data, w, h, curr_img_pyr.data[0]);
  curr_img_pyr.build(curr_img_pyr.data[0], true);
  jsfeat.optical_flow_lk.track(
   prev_img_pyr, curr_img_pyr,
   prev_xy, curr_xy,
   point_count,
   win_size, max_iterations, point_status,
   epsilon, min_eigen
  );

  //prune_oflow_points
  let i = 0;
  let j = 0;

  for(i = 0; i < point_count; ++i){
   if(point_status[i] == 1){
    if(j < i){
     curr_xy[j<<1] = curr_xy[i<<1];
     curr_xy[(j<<1)+1] = curr_xy[(i<<1)+1];
    }
    //draw circle
    ctx.beginPath();
    ctx.arc(curr_xy[j<<1], curr_xy[(j<<1)+1], 3, 0, Math.PI*2, true);
    ctx.closePath();
    ctx.fill();
    ++j;
   }
  }
  point_count = j;

  setTimeout(processVideo, 10);
 }
 processVideo();

 let mouseX, mouseY;
 function canvasDown(){
  event.preventDefault();
  mouseX = event.clientX - canvasPos.left;
  mouseY = event.clientY - canvasPos.top;
  document.getElementById("mousePos").innerHTML = "Mouse : " + mouseX + "," + mouseY;
  curr_xy[point_count<<1] = mouseX;
  curr_xy[(point_count<<1)+1] = mouseY;
  point_count++;
 }
</script>
</html>

1.2. jsfeat (외부 라이브러리)

  해당 파일을 Droidscript의 {App이름.html} 과 같은 폴더에 저장

jsfeat-min.js
0.06MB

0.06MB

2. 코드 설명

  이제부터는 외부 라이브러리를 이용해 프로젝트를 구성했습니다.

<script type="text/javascript" src="./jsfeat-min.js"></script>

위 코드는 나의 html파일이 있는 폴더에서 jsfeat-min.js라는 자바스크립트파일을 불러오라는 요청입니다.

 let w = 395;
 let h = 395;

위 코드의 w와 h값을 변경하여 카메라 화면 크기를 바꿀 수 있습니다.

 

3. 마무리

  jsteat 라이브러리를 이용해 물체추적을 구현해보았습니다. 해당 예제는 점을 1개씩 찍어서 추적하는 방식이지만, 적용하실 때에는 여러 점을 찍고 bouncing box 타입으로 개선하실 수 있습니다. 모터를 제어하는 부분을 추가하여 대상을 따라다니는 자동차를 만들수도 있겠습니다 ^^

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

 

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

[].

728x90

댓글