API/NAVER CLOVA

CLOVA Face Recognition (CFR)

olli2 2022. 1. 25. 23:03

CLOVA Face Recognition (CFR)

celebrity : 유명인 얼굴 인식 API 서비스

face : 얼굴 감지 API 서비스


개발 가이드 확인

유명인 얼굴 인식 API 서비스

Application 사용 가이드 - CLOVA Face Recognition (CFR) - CFR API v1 - celebrity (유명인 얼굴 인식)

https://api.ncloud-docs.com/docs/ai-naver-clovafacerecognition-celebrity

 

celebrity (유명인 얼굴 인식) - CLOVA Face Recognition(CFR)

 

api.ncloud-docs.com

 

얼굴 감지 API 서비스

Application 사용 가이드 - CLOVA Face Recognition (CFR) - CFR API v1 - face (얼굴 감지)

https://api.ncloud-docs.com/docs/ai-naver-clovafacerecognition-face

 

face (얼굴 감지) - CLOVA Face Recognition(CFR)

 

api.ncloud-docs.com


 

[ 유명인 얼굴 인식 ]

콘솔에 JSON 형태의 결과 출력 확인 -> JSON 데이터 추출

  • 결과로 받은 JSON 형식의 문자열에서 value와 confidence추출하여 (CelebrityVO에 저장)
  • CFRCelebrityService 클래스에 jsonToVoList(String jsonResultStr) 메소드 추가
  • 결과로 받은 JSON 문자열을 전달 받아 value와 confidence추출 -> CelebrityVO에 저장한 후 리스트(ArrayList)에 추가 -> CelebrityVO 리스트 반환

jsonToVoList(String jsonResultStr) 메소드 추가로 인한 변경 사항

  • clovaFaceRecogCel() 메소드에서 jsonToVoList() 호출하는 코드 추가
  • 서비스에서 컨트롤러에게 반환하기 위해 clovaFaceRecogCel() 메소드의 반환형 변경 및 return 값 추가
  • 컨트롤러에서는 서비스 호출하고 결과 받는 코드로 변경하고 Model 추가

CelebrityVO

package com.ai.ex.model;

public class CelebrityVO {
	private String value;
	private double confidence;
	
	public String getValue() {
		return value;
	}
	public void setValue(String value) {
		this.value = value;
	}
	public double getConfidence() {
		return confidence;
	}
	public void setConfidence(double confidence) {
		this.confidence = confidence;
	}
	
}

 

CFRCelebrityService

  • clovaFaceRecogCel() 메소드 추가
  • API Java 코드 복사 & 붙여넣기 ( import java.io.File; / import java.net.URL; )
  • Client ID / Client Secret 입력
  • 이미지 파일 경로 입력
package com.ai.ex.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.stereotype.Service;

import com.ai.ex.model.CelebrityVO;

@Service
public class CFRCelebrityService {
	public ArrayList<CelebrityVO> clovaFaceRecogCel(String filePathName) {
		//StringBuffer reqStr = new StringBuffer();
        String clientId = "";//애플리케이션 클라이언트 아이디값";
        String clientSecret = "";//애플리케이션 클라이언트 시크릿값";
        
        ArrayList<CelebrityVO> celList = new ArrayList<CelebrityVO>();

        try {
            String paramName = "image"; // 파라미터명은 image로 지정
           // String imgFile = "파일 경로명";  // 전송할 이미지 파일
            String imgFile = filePathName; 
            File uploadFile = new File(imgFile);
            String apiURL = "https://naveropenapi.apigw.ntruss.com/vision/v1/celebrity"; // 유명인 얼굴 인식
            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()); // 서버로부터 받은 결과를 콘솔에 출력 (JSON 형태)
                // jsonToVoList() 메소드 호출하면서 결과 json 문자열 전달
                celList = jsonToVoList(response.toString());
            } else {
                System.out.println("error !!!");
            }
        } catch (Exception e) {
            System.out.println(e);
        }
        
        // CelebrityVO 리스트 반환
        return celList;
	}
	
	// API 서버로부터 받은 JSON 형태의 결과 데이터를 전달받아서 value와 confidence 추출하고
	// VO 리스트 만들어 반환하는 함수
	public ArrayList<CelebrityVO> jsonToVoList(String jsonResultStr){
		ArrayList<CelebrityVO> celList = new ArrayList<CelebrityVO>();
		
		try {
			//JSON 형태의 문자열에서 JSON 오브젝트 "faces" 추출해서 JSONArray에 저장
			JSONParser jsonParser = new JSONParser();
			JSONObject jsonObj = (JSONObject) jsonParser.parse(jsonResultStr);
			JSONArray celebrityArray = (JSONArray) jsonObj.get("faces");			
			
			// JSONArray의 각 요소에서 value와 confidence 추출하여
			// CelebrityVO 담아 리스트에 추가
			if(celebrityArray != null) {
				// value와 confidence 추출
				// JSONArray  각 요소에서 value와 confidence 추출
				for(int i=0; i < celebrityArray.size(); i++){
					JSONObject tempObj = (JSONObject) celebrityArray.get(i);
					tempObj = (JSONObject) tempObj.get("celebrity");
					String value = (String) tempObj.get("value");
					double confidence = (double) tempObj.get("confidence");
					
					// VO에 저장해서 리스트에 추가
					CelebrityVO vo = new CelebrityVO();
					vo.setValue(value);
					vo.setConfidence(confidence);
					
					celList.add(vo);					
				}					
			} else {
				//유명인을 찾지 못한 경우 ("faces" : [])
				CelebrityVO vo = new CelebrityVO();
				vo.setValue("없음");
				vo.setConfidence(0);				
			}			
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return celList;
	}
	
}

 

APIController

@Autowired
private CFRCelebrityService cfrServiceCel;

@RequestMapping("/faceRecogCelForm")
public String faceRecogCelForm() {
    return "celebrityView";
}

// (1) 유명인 얼굴인식 API 호출 : 결과를 콘솔에 출력
// 변경  -> 
// (2) 유명인 얼굴인식 API 호출 결과 CelebrityVO 리스트 받아서
// Model에 담아 celebrityView.jsp 뷰 페이지로 전달
@RequestMapping("/faceRecogCel")
public String  faceRecogCel(@RequestParam("uploadFile") MultipartFile file,	Model model) throws IOException {		

    // 1. 파일 저장 경로 설정 : 실제 서비스되는 위치 (프로젝트 외부에 저장)
    String uploadPath = "C:/upload/";

    // 2. 원본 파일 이름 알아오기
    String originalFileName = file.getOriginalFilename();
    String filePathName = uploadPath + originalFileName;

    // 3. 파일 생성
    File file1 = new File(filePathName);

    // 4. 서버로 전송
    file.transferTo(file1);	


    ArrayList<CelebrityVO> celList = new ArrayList<CelebrityVO>();

    // 서비스에 파일 path와 파일명 전달  -> 서비스 메소드에서 변경
    // 서비스에서 반환된 CelebrityVO 리스트 저장
    celList = cfrServiceCel.clovaFaceRecogCel(filePathName);

    //Model에 "celList" 이름으로 저장 -> view 페이지로 전달
    model.addAttribute("celList", celList);
    model.addAttribute("fileName", originalFileName);

    return "celebrityView";
}

 

celebrityView.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>유명인 얼굴 인식</title>
	</head>
	<body>
		<!-- 서버로 파일 전송  -->
		<h3>유명인 얼굴 인식</h3>
		<form id="celebrityForm" method="post" action="<c:url value='/faceRecogCel'/>" enctype="multipart/form-data">
			파일 : <input type="file" id="uploadFile" name="uploadFile"> 
			<input type="submit" value="결과 확인">		
		</form>
		<hr>
		<c:if test="${not empty celList }">
		<h3>유명인 얼굴 인식 결과</h3>
			<table border="1" width="400">
				<tr><th>유명인</th><th>정확도</th></tr>
				<c:forEach items="${celList}" var="cel">
					<tr>
						<td>${cel.value }</td>
						<td><fmt:formatNumber value="${cel.confidence }" pattern="0.0000" /></td>
					</tr>
				</c:forEach>				
			</table>
		</c:if>
		<br><br>
		<c:if test="${not empty fileName }">
			<img src="<c:url value='/images/${fileName}' />">
		</c:if>
		<br><br>
		<a href="/">index 페이지로 이동</a>
	</body>
</html>

 

index.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>index 페이지</title>
	</head>
	<body>
		<h3>Naver AI Platform</h3>

		<a href="faceRecogCelForm">유명인 얼굴 인식</a><br><br>
	</body>
</html>

[ 얼굴 감지 ]

CFRFaceRecogService

  • faceRecog() 메소드 추가
  • 자바  API 코드 복사 / 붙여넣기
  • Client ID / Client Secret
  • 파일 경로 및 파일명 직접 입력
  • 반환된 결과 콘솔 출력 확인
package com.ai.ex.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.stereotype.Service;

import com.ai.ex.model.FaceVO;

@ Service 
public class CFRFaceRecogService {
	public ArrayList<FaceVO> faceRecog(String filePathName) {
		 StringBuffer reqStr = new StringBuffer();
	        String clientId = "";//애플리케이션 클라이언트 아이디값";
	        String clientSecret = "";//애플리케이션 클라이언트 시크릿값";
	        
	        ArrayList<FaceVO> faceList = faceList = new ArrayList<FaceVO>();

	        try {
	            String paramName = "image"; // 파라미터명은 image로 지정
	            //String imgFile = "파일 경로명";
	            String imgFile = filePathName;
	            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()); // 서버로부터 반환된 결과 출력 (JSON 형태)
	                faceList = jsonToVoList(response.toString());
	            } else {
	                System.out.println("error !!!");
	            }
	        } catch (Exception e) {
	            System.out.println(e);
	        }
	        
	        return faceList;
	}
	
	// API 서버로부터 받은 JSON 형태의 데이톨부터 value와 confidence 추출해서
	// VO 리스트 만들어 반환
	public ArrayList<FaceVO> jsonToVoList(String jsonResultStr){
		ArrayList<FaceVO> faceList = faceList = new ArrayList<FaceVO>();
		
		try {			
			JSONParser jsonParser = new JSONParser();
			JSONObject jsonObj = (JSONObject) jsonParser.parse(jsonResultStr);
			JSONArray faceArray = (JSONArray) jsonObj.get("faces");
			
			//JSON 형태의 문자열에서 JSON 오브젝트 "faces" 추출해서 JSONArray에 저장
			if(faceArray != null) {
				// JSONArray의 각 요소에서 value와 confidence 추출
				for(int i=0; i < faceArray.size(); i++) {
					FaceVO vo = new FaceVO();
					JSONObject tempObj = (JSONObject) faceArray.get(i);
					
					String value = "";
					double confidence = 0;
					
					// gender  추출
					JSONObject genObj = (JSONObject) tempObj.get("gender");
					value = (String) genObj.get("value");
					confidence = (double) genObj.get("confidence");
					// vo gender 값 설정
					vo.setGender(value);
					vo.setGenderConf(confidence);					
					
					// age  추출
					JSONObject ageObj = (JSONObject) tempObj.get("age");
					value = (String) ageObj.get("value");
					confidence = (double) ageObj.get("confidence");
					// vo age 값 설정
					vo.setAge(value);
					vo.setAgeConf(confidence);					
					
					// emotion  추출
					JSONObject emotObj = (JSONObject) tempObj.get("emotion");
					value = (String) emotObj.get("value");
					confidence = (double) emotObj.get("confidence");
					// vo emotion 값 설정
					vo.setEmotion(value);
					vo.setEmotionConf(confidence);					
					
					// pose  추출
					JSONObject poseObj = (JSONObject) tempObj.get("pose");
					value = (String) poseObj.get("value");
					confidence = (double) poseObj.get("confidence");
					// vo pose 값 설정
					vo.setPose(value);
					vo.setPoseConf(confidence);
					
					// FaceVO에 담아 리스트에 추가
					faceList.add(vo);
				}
				
			} else {
				//감지한 얼굴이 없는 경우 ("faces":[])
				FaceVO vo = new FaceVO();
				vo.setGender("없음");
				vo.setGenderConf(0);
				vo.setAge("없음");
				vo.setAgeConf(0);
				vo.setEmotion("없음");
				vo.setEmotionConf(0);
				vo.setPose("없음");
				vo.setPoseConf(0);				
			}
			
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return faceList;
	}	
}

 

APIController

@Autowired
private CFRFaceRecogService cfrRecogService;

 @RequestMapping("/faceRecogForm")
    public String faceRecogForm() {
        return "faceRecogView";
    }


// (1) 얼굴 감지 API 호출 : 결과를 콘솔에 출력
@RequestMapping("/faceRecog")
public String  faceRecog(@RequestParam("uploadFile") MultipartFile file,	
        Model model) throws IOException {

    // 1. 파일 저장 경로 설정 : 실제 서비스되는 위치 (프로젝트 외부에 저장)
    String uploadPath = "C:/upload/";

    // 2. 원본 파일 이름 알아오기
    String originalFileName = file.getOriginalFilename();
    String filePathName = uploadPath + originalFileName;

    // 3. 파일 생성
    File file1 = new File(filePathName);

    // 4. 서버로 전송
    file.transferTo(file1);	


    ArrayList<FaceVO> faceList = new ArrayList<FaceVO>();				

    faceList = cfrRecogService.faceRecog(filePathName);

    model.addAttribute("faceList", faceList);
    System.out.println(faceList+"ee");
    model.addAttribute("fileName", originalFileName);
    return "faceRecogView";
}

 

faceRecogView.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
	<h3>얼굴 감지</h3>
	<!-- 서버로 파일 전송 -->
	<form id="faceRecogForm" method="post"
		action="<c:url value='/faceRecog'/>" enctype="multipart/form-data">
		파일 : <input type="file" id="uploadFile" name="uploadFile">  
		<input type="submit" value="결과 확인">
	</form>
	
	<c:if test="${not empty faceList}">
		<h3>얼굴 감지 결과</h3>

		<table border="1" width="800">
			<tr>
				<th>성별</th>
				<th>성별 정확도</th>
				<th>나이</th>
				<th>나이 정확도</th>
				<th>감정</th>
				<th>감정 정확도</th>
				<th>포즈</th>
				<th>포즈 정확도</th>
			</tr>
			<c:forEach items="${faceList }" var="face">
				<tr>
					<td>${face.gender }</td>
					<td><fmt:formatNumber value="${face.genderConf }"
							pattern="0.0000" /></td>
					<td>${face.age }</td>
					<td><fmt:formatNumber value="${face.ageConf }"
							pattern="0.0000" /></td>
					<td>${face.emotion }</td>
					<td><fmt:formatNumber value="${face.emotionConf }"
							pattern="0.0000" /></td>
					<td>${face.pose }</td>
					<td><fmt:formatNumber value="${face.poseConf }"
							pattern="0.0000" /></td>
				</tr>
			</c:forEach>

		</table>
	</c:if>
	<br><br>
	<c:if test="${not empty fileName}">
		<img src="<c:url value='/images/${fileName}'/>"/>
	</c:if>
	
	<br><br>
	<a href="/">index 페이지 이동</a>
</body>
</html>

 

index.jsp

<a href="faceRecogForm">얼굴 감지</a><br><br>