오봉이와 함께하는 개발 블로그
Naver A.I Platform - CLOVA Face Recognition(CFR - 얼굴 감지) 본문
728x90
CLOVA Face Recognition(CFR) (얼굴 감지)
- CFRFaceRecogService 클래스 생성
- faceRecog() 메소드 추가
- faceRecog() 메소드 추가
- Client ID / Client Secret
- 파일 경로 및 파일명 직접 입력
- 반환된 결과 콘솔 출력 확인
- 컨트롤러에 추가
- faceRecogView.jsp 추가
- index.jsp에 추가
- JSON 데이터 출력 / 파일 업로드 기능 추가
- gender / age / emotion / pose
- value와 confidence 출력
- jsonToVoList(String jsonResultStr) 메소드 추가로 인한 변경 사항
- faceRecog() 메소드에서 jsonToVoList() 호출하는 코드 추가
- 서비스에서 컨트롤러에게 반환하기 위해 faceRecog() 메소드의 반환형 변경 및 return 값 추가
- 컨트롤러에서는 서비스 호출하고 결과 받는 코드로 변경하고 Model 추가
- faceRecogView.jsp에 출력 부분 추가
- 파일 업로드 기능 추가
- 파일을 서버에 올리는 기능 추가
- 서버의 특정 폴더에 이미지 저장
- 외부 폴더 지정
- 결과 페이지에서 서버로 올린 이미지 출력
- faceRecogView.jsp에 파일 업로드 부분 추가
- 컨트롤러에 추가
public class FaceVO {
private String gender;
private double genderConf;
private String age;
private double ageConf;
private String emotion;
private double emotionConf;
private String pose;
private double poseConf;
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public double getGenderConf() {
return genderConf;
}
public void setGenderConf(double genderConf) {
this.genderConf = genderConf;
}
public String getAge() {
return age;
}
public void setAge(String age) {
this.age = age;
}
public double getAgeConf() {
return ageConf;
}
public void setAgeConf(double ageConf) {
this.ageConf = ageConf;
}
public String getEmotion() {
return emotion;
}
public void setEmotion(String emotion) {
this.emotion = emotion;
}
public double getEmotionConf() {
return emotionConf;
}
public void setEmotionConf(double emotionConf) {
this.emotionConf = emotionConf;
}
public String getPose() {
return pose;
}
public void setPose(String pose) {
this.pose = pose;
}
public double getPoseConf() {
return poseConf;
}
public void setPoseConf(double poseConf) {
this.poseConf = poseConf;
}
}
@ 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 = "C:/ai/family.jpg";
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) {
e.printStackTrace();
}
return faceList;
}
}
@Controller
public class APIController {
@Autowired
private CFRCelebrityService cfrServiceCel;
@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 = "/Users/gobyeongchae/Desktop/productImages";
// 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";
}
}
<%@ 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>
728x90
'Naver A.I Platform' 카테고리의 다른 글
Naver A.I Platform - Object Detection (객체 탐지) (0) | 2022.01.25 |
---|---|
Naver A.I Platform - Pose Estimation(포즈 인식) (0) | 2022.01.24 |
Naver A.I Platform - OCR(텍스트 인식) (6) | 2022.01.24 |
Naver A.I platform - CLOVA Face Recognition (CFR - 유명인 유사도 측정) (0) | 2022.01.22 |
Naver A.I Platform - 개요 (0) | 2022.01.22 |
Comments