본문 바로가기
블로그 이미지

방문해 주셔서 감사합니다! 항상 행복하세요!

  
   - 문의사항은 메일 또는 댓글로 언제든 연락주세요.
   - "해줘","답 내놔" 같은 질문은 답변드리지 않습니다.
   - 메일주소 : lts06069@naver.com


Html 캔버스/Html 캔버스 에니메이션

HTML Canvas video webcam(캔버스 비디오 웹캠)

야근없는 행복한 삶을 위해 ~
by 마샤와 곰 2022. 4. 15.


캔버스(canvas)를 활용하여 웹캠 정보를 재생하는 내용 입니다.
웹에서의 웹캡 비디오 스트림은 navigator 객체에서 useMedia 함수를 사용하면 가져올 수 있습니다.

navigator.mediaDevices.getUserMedia({ video: true })


이렇게 getUserMedia를 통하여 콜백으로 받은 스트림 객체는 비디오(vedio) 엘리먼트의 srcObject의 값으로 대입할 수 있습니다.
getUserMedia 함수가 프로미스(Promise) 형식으로 되어 있어 then 함수를 호출하여 만나볼 수 있습니다.

navigator.mediaDevices.getUserMedia({ video: true }).then( stream=>{
    //비디오 스트림 : stream
})


여기까지 실행하고나면 웹캠의 영상이 비디오 테그에 표출되는 것을 볼 수 있습니다.
그런데 굳이 비디오 테그에 잘 나오는 동영상을 캔버스(canvas)에서 나오게 하려는 이유는 무엇 일까요?
우리는 핸드폰 앱에서 동영상 촬영시 얼굴을 꾸며주고 바꾸어주는 앱을 사용하거나 들어본적이 있습니다.
또한 배경을 바꾼다던지 동영상 안에 그림을 넣는다는지 등의 기능을 보고는 합니다.

이러한 앱의 기능을 만약 웹에서 구현한다면 그때 필요한 것이 바로 웹캠의 정보를 캔버스로 가져오는 것 입니다.
웹캠의 스트림을 video 테그에 전달해 주면 이제 캔버스(canvas)에서 사용 가능한 형태로 만들어지게 됩니다.
아래 코드를 살펴봅니다.

let video = document.getElementById('video') as HTMLVideoElement;
let canvas = document.getElementById('canvas') as HTMLCanvasElement;
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D ;

navigator.mediaDevices.getUserMedia({ video: true })
.then( (stream) => {
    video.srcObject  = stream  //비디오 테그에 웹캠 스트림을 넣습니다.
    video.play()  //비디오 테그 실행
    video.addEventListener('play', ()=>{
        setInterval(()=>{
            ctx.save();
            ctx.drawImage(video, 0, 0, canvas.width, canvas.height); //putImage 함수
            ctx.restore();
        },1)
    }, false);
})
.catch( (error)=>{
      console.log(error);
});


웹캠을 통해서 가져온 객체는 video변수에 담겨있습니다.
이 변수 자체를 캔버스의 drawImage 함수를 통하여 그대로 대입하여 그려주면 웹캠의 동영상의 이미지 정보가 캔버스로 전달되게 되는데, 이때 setInterval 함수를 통하여 계속해서 그려주면 이미지가 계속해서 바뀌는 효과에 따라 마치 동영상이 재생되는 것 처럼 보이게 됩니다.
그렇다면 만약에 이러한 기능에 순서를 통하여 선을 그리고 점을 찍는 기능을 넣어주면 어떻게 될까요?

아하~!


웹캠에서 가져온 이미지를 가장 처음 그려주고, 사용자가 하는 행위를 정의한 내용을 그려주면 동영상 위에 각종 그림을 그리는 효과를 만들 수 있게 됩니다.

let video = document.getElementById('video') as HTMLVideoElement;
let canvas = document.getElementById('canvas') as HTMLCanvasElement;
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D ;

if (navigator.mediaDevices.getUserMedia) {
    navigator.mediaDevices.getUserMedia({ video: true })
    .then( (stream) => { 

        //마우스 움직임 정보를 담아두는 구간 입니다.
        const moveArray : Array<any> = [];
        canvas.addEventListener('mousemove', function (event) {
            var x = event.clientX - canvas.offsetLeft;
            var y = event.clientY - canvas.offsetTop;
            moveArray.push({x, y});
        }); 

        //비디오에 스트림을 넣습니다.
        video.srcObject  = stream
        video.play()
        
        //동영상이 재생되면 인터벌함수를 통해 캔버스에 putImage를 해 줍니다.
        video.addEventListener('play', ()=>{

           setInterval(()=>{
               //초기화
               ctx.clearRect(0,0,canvas.width, canvas.height);
               ctx.save();
               ctx.beginPath();
               ctx.strokeStyle = 'red';
               ctx.lineWidth = 4;
                    
               //비디오 이미지 먼저 그려줍니다.
               ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
               
               //4각형을 한번 그려 봅니다.
               ctx.strokeRect(canvas.width/4, canvas.height/4,canvas.width/2, canvas.height/2);
               ctx.stroke();
               ctx.closePath();
               ctx.restore();

               //마우스가 움직인 정보값을 점 찍어 봅니다.
               moveArray.forEach( (data : any )=> {
                   ctx.save();
                   ctx.beginPath();
                   ctx.arc(data.x, data.y, 10, (Math.PI / 180) * 0,  (Math.PI / 180) * 360, false);
                   ctx.fillStyle = 'blue';
                   ctx.fill();
                   ctx.closePath();
                   ctx.restore();                        
               });

            },1)

        }, false);
    })
    .catch( (error)=>{
          console.log(error);
    });
};


이러한 방식으로 동영상에 각종 효과를 주는 기능을 만들 수 있게 됩니다.
위 방식을 좀더 구체적이고 다양한 효과를 만날 수 있는 기능이 바로 Opencv.js 입니다.
영상처리의 대명사인 오픈CV를 자바스크립트에서도 사용 할 수 있습니다.

와...이걸 Javascript로 만드냐;;;


Opencv에 대한 공부가 어느정도 되고 나면 아마 위코드도 쉽게 접근 할 수 있지 않을 까 합니다. ^^;
위 내용에 사용된 샘플 코드는 아래 제 깃허브에서 받아볼 수 있습니다.
https://github.com/TaeSeungRyu/sample/tree/main/캔버스 비디오 플레이어

GitHub - TaeSeungRyu/sample

Contribute to TaeSeungRyu/sample development by creating an account on GitHub.

github.com


실제 동작하는 코드도 아래 제 깃허브에서 확인할 수 있습니다.
https://taeseungryu.github.io/sample/sampleView/canvasVideo/index.html

index

taeseungryu.github.io


위 모든 내용이 웹(web)에서 동작하는 캔버스(canvas)로 이루어진 내용 입니다.
* 플래쉬, 액션스크립트, 유니티 같은 응용 프로그램이 아닙니다~
이상으로 HTML Canvas video webcam(캔버스 비디오 웹캠)에 대해서 살펴보았습니다.
문의사항이나 궁금한 점은 언제든 댓글 또는 메일로 연락주세요~ 👻

반응형
* 위 에니메이션은 Html의 캔버스(canvas)기반으로 동작하는 기능 입니다. Html 캔버스 튜토리얼 도 한번 살펴보세요~ :)
* 직접 만든 Html 캔버스 애니메이션 도 한번 살펴보세요~ :)

댓글