로메오의 블로그

[face-api] face-api.js for Browser 본문

Backend/node

[face-api] face-api.js for Browser

romeoh 2019. 7. 22. 03:27
반응형

node.js의 face-api를 브라우저에서 구현합니다.

프로젝트 설정

$ cd /my/project/path
$ mkdir faceRecognition
$ code ./faceRecognition
$ yarn add face-api.js
$ cp node_modules/face-api.js/dist/face-api.min.js .
$ touch index.html script.js
$ mkdir known unknown

models.zip
9.65MB

첨부된 models.zip 파일을 다운로드해서 프로젝트에 추가합니다.

위와 같이 프로젝트가 구성되었습니다.

 

unknown폴더에 식별할 사진을 추가합니다.

PYH2017063009810001300.jpg

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        body {
            margin:0; padding:0; width:100vw; height:100vh; 
            display:flex; justify-content:center; align-items:center; flex-direction:column;
        }
        canvas {
            position:absolute; top:0; left:0;
        }
    </style>
    <script defer src="face-api.min.js"></script>
    <script defer src="script.js"></script>
</head>
<body>
    <input type="file" id="imageUpload">
</body>
</html>

 

script.js

const imageUpload = document.getElementById('imageUpload')

Promise.all([
    faceapi.nets.faceRecognitionNet.loadFromUri('./models'),
    faceapi.nets.faceLandmark68Net.loadFromUri('./models'),
    faceapi.nets.ssdMobilenetv1.loadFromUri('./models')
]).then(start)

function start() {
    document.body.append('loaded')
    imageUpload.addEventListener('change', async () => {
        // 사진을 화면에 표시함
        const image = await faceapi.bufferToImage(imageUpload.files[0])
        document.body.append(image)

        // 사진에서 얼굴을 식별한다.
        const detections = await faceapi.detectAllFaces(image)
                                .withFaceLandmarks()
                                .withFaceDescriptors()
        document.body.append(detections.length)
    })
}

5명의 얼굴을 감별했습니다.

 

얼굴 좌표표시

script.js

const imageUpload = document.getElementById('imageUpload')

Promise.all([
    faceapi.nets.faceRecognitionNet.loadFromUri('./models'),
    faceapi.nets.faceLandmark68Net.loadFromUri('./models'),
    faceapi.nets.ssdMobilenetv1.loadFromUri('./models')
]).then(start)

function start() {

    // Canvas container 생성
    const container = document.createElement('div')
    container.style.position = 'relative'
    document.body.append(container)
    document.body.append('loaded')

    imageUpload.addEventListener('change', async () => {

        // 사진을 화면에 표시함
        const image = await faceapi.bufferToImage(imageUpload.files[0])
        container.append(image)

        // canvas를 초기화 한다
        const canvas = faceapi.createCanvasFromMedia(image)
        container.append(canvas)
        const displaySize = {width: image.width, height: image.height}
        faceapi.matchDimensions(canvas, displaySize)

        // 사진에서 얼굴을 식별한다.
        const detections = await faceapi.detectAllFaces(image)
                                .withFaceLandmarks()
                                .withFaceDescriptors()
        
        // 사진에서 얼굴 좌표에 box를 그린다.
        const resizedDetections = faceapi.resizeResults(detections, displaySize)
        resizedDetections.forEach(detection => {
            const box = detection.detection.box
            const drawBox = new faceapi.draw.DrawBox(box, {label: 'Face'})
            drawBox.draw(canvas)
        })
    })
}

얼굴인식하기

known 폴더에 얼굴데이터 파일을 추가합니다.

script.js

const imageUpload = document.getElementById('imageUpload')

Promise.all([
    faceapi.nets.faceRecognitionNet.loadFromUri('./models'),
    faceapi.nets.faceLandmark68Net.loadFromUri('./models'),
    faceapi.nets.ssdMobilenetv1.loadFromUri('./models')
]).then(start)

async function start() {

    // Canvas container 생성
    const container = document.createElement('div')
    container.style.position = 'relative'
    document.body.append(container)

    // 얼굴과 라벨을 매칭한다.
    const labeledFaceDescriptors = await loadLabeledImage()
    const faceMatcher = new faceapi.FaceMatcher(labeledFaceDescriptors, 0.6)

    document.body.append('loaded')

    imageUpload.addEventListener('change', async () => {

        // 사진을 화면에 표시함
        const image = await faceapi.bufferToImage(imageUpload.files[0])
        container.append(image)

        // canvas를 초기화 한다
        const canvas = faceapi.createCanvasFromMedia(image)
        container.append(canvas)
        const displaySize = {width: image.width, height: image.height}
        faceapi.matchDimensions(canvas, displaySize)

        // 사진에서 얼굴을 식별한다.
        const detections = await faceapi.detectAllFaces(image)
                                .withFaceLandmarks()
                                .withFaceDescriptors()
        
        // 사진에서 얼굴 좌표에 box를 그린다.
        const resizedDetections = faceapi.resizeResults(detections, displaySize)

        // 얼굴에 라벨을 표시한다.
        const result = resizedDetections.map(d => faceMatcher.findBestMatch(d.descriptor))
        result.forEach((result, i) => {
            const box = resizedDetections[i].detection.box
            const drawBox = new faceapi.draw.DrawBox(box, {label: result.toString()})
            drawBox.draw(canvas)
        })
    })
}

// 얼굴 기초데이터를 초기화 한다.
function loadLabeledImage() {
    const labels = ['Donald Trump', 'Kim Jung sook', 'Melania Trump', 'Moon Jaein']
    return Promise.all(
        labels.map(async label => {
            const description = []
            const img = await faceapi.fetchImage('known/' + label + '.jpg')
            const detections = await faceapi.detectSingleFace(img)
                                .withFaceLandmarks()
                                .withFaceDescriptor()
            description.push(detections.descriptor)
            return new faceapi.LabeledFaceDescriptors(label, description)
        })
    )
}

 

반응형
Comments