face (얼굴 감지)

얼굴 감지 API

입력받은 이미지로부터 얼굴을 감지하고 입력된 이미지에서 얼마나 많은 얼굴이 감지되었고 각 얼굴이 어디에 어떤 크기로 위치하며 어떤 모습을 하고 있는지 반환하는 REST API입니다. 이미지에서 다음과 같은 정보를 분석합니다.

  • 감지된 얼굴의 수
  • 감지된 각 얼굴을 분석한 정보
    • 감지된 각 얼굴의 좌표 및 크기
    • 감지된 각 얼굴의 눈, 코, 입의 좌표
    • 감지된 얼굴의 추정 성별 및 추정치
    • 감지된 얼굴의 추정 나이 및 추정치
    • 감지된 얼굴에서 분석된 감정
    • 감지된 얼굴의 방향

요청

POST https://naveropenapi.apigw.ntruss.com/vision/v1/face

요청 헤더

헤더명 설명
X-NCP-APIGW-API-KEY-ID 앱 등록 시 발급받은 Client ID
X-NCP-APIGW-API-KEY-ID:{Client ID}
X-NCP-APIGW-API-KEY 앱 등록 시 발급 받은 Client Secret
X-NCP-APIGW-API-KEY:{Client Secret}
Content-Type 바이너리 전송 형식
Content-Type: multipart/form-data

요청 바디

필드명 필수 여부 타입 제약 사항 설명
image Yes Binary 최대 2MB 이미지 데이터 지원 분석할 이미지

응답

응답 바디

얼굴 감지 API는 분석한 결과를 JSON 형식의 데이터로 반환합니다. JSON 응답의 각 필드에 대한 설명은 다음과 같습니다.

필드 이름 데이터 타입 설명
info object 입력된 이미지 크기와 인식된 얼굴의 개수 정보를 가지는 객체
info.size place object 입력된 이미지의 크기 정보를 가지는 객체
info.faceCount number 감지된 얼굴의 수
faces[] object array 감지된 얼굴의 개별 분석 결과를 가지는 객체 배열
faces[].roi place object 감지된 특정 얼굴의 좌표 및 크기 정보를 가지는 객체
faces[].landmark object 감지된 얼굴의 눈, 코, 입의 위치를 가지는 객체
faces[].landmark.leftEye place object 왼쪽 눈의 위치
faces[].landmark.rightEye place object 오른쪽 눈의 위치
faces[].landmark.nose place object 코의 위치
faces[].landmark.leftMouth place object 왼쪽 입 꼬리의 위치
faces[].landmark.rightMouth place object 오른 쪽 입 꼬리의 위치
faces[].gender object 감지된 얼굴의 성별을 추정한 정보를 가지는 객체
faces[].gender.value string 인식된 성별. “male” 또는 “female” 값을 가집니다.
faces[].gender.confidence number 인식된 성별을 확신하는 정도. 0에서 1 사이의 실수로 표현됩니다. 1에 가까울수록 높은 확신을 나타냅니다.
faces[].age object 감지된 얼굴의 나이를 추정한 정보를 가지는 객체
faces[].age.value string 인식된 나이. “22~26”와 같이 나이의 범위가 표현된 문자열입니다.
faces[].age.confidence number 인식된 나이를 확신하는 정도. 0에서 1 사이의 실수로 표현됩니다. 1에 가까울수록 높은 확신을 나타냅니다.
faces[].emotion object 감지된 얼굴의 감정을 추천한 정보를 가지는 객체
faces[].emotion.value string 인식된 감정. “smile”과 같이 얼굴의 표정이나 감정을 나타내는 문자열입니다. 다음과 같은 값을 가집니다.
  • angry
  • disgust
  • fear
  • laugh
  • neutral
  • sad
  • suprise
  • smile
  • talking
faces[].emotion.confidence number 인식된 감정을 확신하는 정도. 0에서 1 사이의 실수로 표현됩니다. 1에 가까울수록 높은 확신을 나타냅니다.
faces[].pose object 감지된 얼굴이 어떤 포즈인지 추정한 정보를 가지는 객체
faces[].pose.value string 인식된 얼굴의 포즈. “frontal_face”와 같이 얼굴의 방향을 나타내는 문자열입니다. 다음과 같은 값을 가집니다.
  • part_face
  • false_face
  • sunglasses
  • frontal_face
  • left_face
  • right_face
  • rotate_face
faces[].pose.confidence number 인식된 얼굴의 방향을 확신하는 정도. 0에서 1 사이의 실수로 표현됩니다. 1에 가까울수록 높은 확신을 나타냅니다.

속성

Place object

CFR API는 HTTP 응답의 JSON 데이터에 감지한 얼굴 및 얼굴의 부위를 표시하기 위해 다음과 같이 place 객체를 공유하여 사용합니다. 각 필드는 선택적이며, 크기 정보를 나타낼 때와 위치 정보를 나타낼 때 선택적으로 사용될 수 있습니다.

필드 이름 데이터 타입 설명 필수 여부
width number 입력된 이미지, 인식된 얼굴의 너비 정보(px) 선택
height number 입력된 이미지, 인식된 얼굴의 높이 정보(px) 선택
x number 인식된 얼굴 및 얼굴 부위의 위치 정보를 나타내기 위한 x 좌표(px). 기준점은 이미지의 좌상단 모서리입니다. 선택
y number 인식된 얼굴 및 얼굴 부위의 위치 정보를 나타내기 위한 y 좌표(px). 기준점은 이미지의 좌상단 모서리입니다. 선택

예시

요청 예시

[HTTP Request Header]
POST /vision/v1/face HTTP/1.1
Host: naveropenapi.apigw.ntruss.com
Content-Type: multipart/form-data; boundary={boundary-text}
X-NCP-APIGW-API-KEY-ID: {앱 등록 시 발급받은 Client ID}
X-NCP-APIGW-API-KEY: {앱 등록 시 발급 받은 Client Secret}
Content-Length: 96703

--{boundary-text}
Content-Disposition: form-data; name="image"; filename="test.jpg"
Content-Type: image/jpeg

{image binary data}
--{boundary-text}--

응답 예시

// 1개의 얼굴을 감지한 경우
{
 "info": {
   "size": {
     "width": 900,
     "height": 1349
   },
   "faceCount": 1
 },
 "faces": [{
   "roi": {
     "x": 235,
     "y": 227,
     "width": 326,
     "height": 326
   },
   "landmark": {
     "leftEye": {
       "x": 311,
       "y": 289
     },
     "rightEye": {
       "x": 425,
       "y": 287
     },
     "nose": {
       "x": 308,
       "y": 346
     },
     "leftMouth": {
       "x": 306,
       "y": 425
     },
     "rightMouth": {
       "x": 383,
       "y": 429
     }
   },
   "gender": {
     "value": "male",
     "confidence": 0.91465
   },
   "age": {
     "value": "22~26",
     "confidence": 0.742265
   },
   "emotion": {
     "value": "simile",
     "confidence": 0.460465
   },
   "pose": {
     "value": "frontal_face",
     "confidence": 0.937789
   }
 }]
}

// 감지한 얼굴이 없을 경우
{
 	"info": {
 		"size": {
 			"width": 700,
 			"height": 800
 		},
 		"faceCount": 0
 	},
 	"faces": []
 }

API 예제

다음은 각 언어별 CFR API 구현 예제입니다.

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;

// 네이버 얼굴인식 API 예제
public class APIExamFace {

    public static void main(String[] args) {

        StringBuffer reqStr = new StringBuffer();
        String clientId = "YOUR_CLIENT_ID";//애플리케이션 클라이언트 아이디값";
        String clientSecret = "YOUR_CLIENT_SECRET";//애플리케이션 클라이언트 시크릿값";

        try {
            String paramName = "image"; // 파라미터명은 image로 지정
            String imgFile = "이미지 파일 경로 ";
            File uploadFile = new File(imgFile);
            String apiURL = "https://naveropenapi.apigw.ntruss.com/vision/v1/face"; // 얼굴 감지
            URL url = new URL(apiURL);
            HttpURLConnection con = (HttpURLConnection)url.openConnection();
            con.setUseCaches(false);
            con.setDoOutput(true);
            con.setDoInput(true);
            // multipart request
            String boundary = "---" + System.currentTimeMillis() + "---";
            con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
            con.setRequestProperty("X-NCP-APIGW-API-KEY-ID", clientId);
            con.setRequestProperty("X-NCP-APIGW-API-KEY", clientSecret);
            OutputStream outputStream = con.getOutputStream();
            PrintWriter writer = new PrintWriter(new OutputStreamWriter(outputStream, "UTF-8"), true);
            String LINE_FEED = "\r\n";
            // file 추가
            String fileName = uploadFile.getName();
            writer.append("--" + boundary).append(LINE_FEED);
            writer.append("Content-Disposition: form-data; name=\"" + paramName + "\"; filename=\"" + fileName + "\"").append(LINE_FEED);
            writer.append("Content-Type: "  + URLConnection.guessContentTypeFromName(fileName)).append(LINE_FEED);
            writer.append(LINE_FEED);
            writer.flush();
            FileInputStream inputStream = new FileInputStream(uploadFile);
            byte[] buffer = new byte[4096];
            int bytesRead = -1;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }
            outputStream.flush();
            inputStream.close();
            writer.append(LINE_FEED).flush();
            writer.append("--" + boundary + "--").append(LINE_FEED);
            writer.close();
            BufferedReader br = null;
            int responseCode = con.getResponseCode();
            if(responseCode==200) { // 정상 호출
                br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            } else {  // 오류 발생
                System.out.println("error!!!!!!! responseCode= " + responseCode);
                br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            }
            String inputLine;
            if(br != null) {
                StringBuffer response = new StringBuffer();
                while ((inputLine = br.readLine()) != null) {
                    response.append(inputLine);
                }
                br.close();
                System.out.println(response.toString());
            } else {
                System.out.println("error !!!");
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
<?php
  // 네이버 얼굴인식 Open API 예제
  $client_id = "YOUR_CLIENT_ID";
  $client_secret = "YOUR_CLIENT_SECRET";
  $url = "https://naveropenapi.apigw.ntruss.com/vision/v1/face"; // 얼굴감지
  $is_post = true;
  $ch = curl_init();
  $filename = "test.jpg";
  $filesize = filesize($filename);
  echo "filesize=".$filesize;
  if($filesize > 2*1024*1024) {
      echo "2MB 이하의 이미지를 올려주세요.";
      exit;
  }
  $file_name = 'YOUR_FILE_NAME'; // 업로드할 파일명
  $cfile = curl_file_create($file_name,'image/jpeg','test_name');
  $postvars = array("filename" => $filename, "image" => $cfile);
  curl_setopt($ch, CURLOPT_URL, $url);
  curl_setopt($ch, CURLOPT_POST, $is_post);
  curl_setopt($ch, CURLOPT_INFILESIZE, $filesize);
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($ch, CURLOPT_POSTFIELDS, $postvars);
  curl_setopt($ch, CURLINFO_HEADER_OUT, true);
  $headers = array();
  $headers[] = "X-NCP-APIGW-API-KEY-ID: ".$client_id;
  $headers[] = "X-NCP-APIGW-API-KEY: ".$client_secret;
  $headers[] = "Content-Type:multipart/form-data";
  curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  $response = curl_exec ($ch);
  $status_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
  // 헤더 내용 출력
  $headerSent = curl_getinfo($ch, CURLINFO_HEADER_OUT );
  echo $headerSent;
  echo "<br />[status_code]:".$status_code."<br />";
  curl_close ($ch);
  if($status_code == 200) {
    echo $response;
  } else {
    echo "Error 내용:".$response;
  }
?>
var express = require('express');
var app = express();
var client_id = 'YOUR_CLIENT_ID';
var client_secret = 'YOUR_CLIENT_SECRET';
var fs = require('fs');
app.get('/face', function (req, res) {
   var request = require('request');
   var api_url = 'https://naveropenapi.apigw.ntruss.com/vision/v1/face'; // 얼굴 감지

   var _formData = {
     image:'image',
     image: fs.createReadStream(__dirname + 'YOUR_FILE_NAME'); // FILE 이름
   };
    var _req = request.post({url:api_url, formData:_formData,
      headers: {'X-NCP-APIGW-API-KEY-ID':client_id, 'X-NCP-APIGW-API-KEY': client_secret}}).on('response', function(response) {
       console.log(response.statusCode) // 200
       console.log(response.headers['content-type'])
    });
    console.log( request.head  );
    _req.pipe(res); // 브라우저로 출력
 });

 app.listen(3000, function () {
   console.log('http://127.0.0.1:3000/face app listening on port 3000!');
 });
import os
import sys
import requests
client_id = "YOUR_CLIENT_ID"
client_secret = "YOUR_CLIENT_SECRET"
url = "https://naveropenapi.apigw.ntruss.com/vision/v1/face" // 얼굴감지
files = {'image': open('YOUR_FILE_NAME', 'rb')}
headers = {'X-NCP-APIGW-API-KEY-ID': client_id, 'X-NCP-APIGW-API-KEY': client_secret }
response = requests.post(url,  files=files, headers=headers)
rescode = response.status_code
if(rescode==200):
    print (response.text)
else:
    print("Error Code:" + rescode)
using System;
using System.Net;
using System.Text;
using System.IO;
using System.Collections.Generic;
using System.Collections.Specialized;

namespace NaverAPI_Guide
{
    public class APIExamFace
    {
        static void Main(string[] args)
        {
            string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
            string FilePath = "YOUR_FILE_NAME";
            FileStream fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read);
            byte[] fileData = new byte[fs.Length];
            fs.Read(fileData, 0, fileData.Length);
            fs.Close();

            string CRLF = "\r\n";
            string postData = "--" + boundary + CRLF + "Content-Disposition: form-data; name=\"image\"; filename=\"";
            postData += Path.GetFileName(FilePath) + "\"" + CRLF +"Content-Type: image/jpeg" + CRLF + CRLF;
            string footer = CRLF + "--" + boundary + "--" + CRLF;

            Stream DataStream = new MemoryStream();
            DataStream.Write(Encoding.UTF8.GetBytes(postData), 0, Encoding.UTF8.GetByteCount(postData));
            DataStream.Write(fileData, 0, fileData.Length);
            DataStream.Write(Encoding.UTF8.GetBytes("\r\n"), 0, 2);
            DataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer));
            DataStream.Position = 0;
            byte[] formData = new byte[DataStream.Length];
            DataStream.Read(formData, 0, formData.Length);
            DataStream.Close();

            string url = "https://naveropenapi.apigw.ntruss.com/vision/v1/face"; // 얼굴 감지
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Headers.Add("X-NCP-APIGW-API-KEY-ID", "YOUR_CLIENT_ID");
            request.Headers.Add("X-NCP-APIGW-API-KEY", "YOUR_CLIENT_SECRET");
            request.Method = "POST";
            request.ContentType = "multipart/form-data; boundary=" + boundary;
            request.ContentLength = formData.Length;
            using (Stream requestStream = request.GetRequestStream())
            {
                requestStream.Write(formData, 0, formData.Length);
                requestStream.Close();
            }
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream stream = response.GetResponseStream();
            StreamReader reader = new StreamReader(stream, Encoding.UTF8);
            string text = reader.ReadToEnd();
            stream.Close();
            response.Close();
            reader.Close();
            Console.WriteLine(text);
        }
    }
}

오류 코드

HttpStatusCode ErrorCode ErrorMessage Description
400 ER01 image parameter is needed. image 파라미터가 누락되었습니다.
400 ER02 Failed to receive image content. 이미지 데이터를 수신하는데 실패했습니다.
400 ER03 Bad reqeust. 잘못된 요청을 수신했습니다.
400 ER04 Image size is too large. 이미지의 크기가 2MB를 넘었습니다.
400 ER11 Abnormal image format. 인식할 수 없는 이미지 데이터가 입력되었습니다.
400 ER12 Abnormal image width v.s height ratio. 이미지의 너비가 높이의 4 배 이상입니다.
400 ER13 Image width is to small. 이미지의 너비가 50 픽셀보다 작습니다.
400 ER14 Image height is too small. 이미지의 높이가 50 픽셀보다 작습니다.
400 ER15 Failed to analyze image. 분석할 수 없는 이미지가 입력되었습니다.
400 ER21 Timeout error. 서버에서 이미지 분석을 시간 내에 처리하지 못했습니다.
400 ER22 Server is too busy. 현재 이미지 분석 요청이 많아 처리할 수 없습니다.
500 ER92 Failed to generate valid json string. 서버에서 유효한 형식의 JSON 데이터를 결과로 생성하지 못했습니다.
500 ER99 Internal server error. 내부 서버 오류입니다. 포럼에 문의하시면 신속히 조치하겠습니다.