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>