오봉이와 함께하는 개발 블로그

Naver A.I Platform - CLOVA Face Recognition(CFR - 얼굴 감지) 본문

Naver A.I Platform

Naver A.I Platform - CLOVA Face Recognition(CFR - 얼굴 감지)

오봉봉이 2022. 1. 22. 23:11
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
Comments