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

Naver A.I platform - CLOVA Face Recognition (CFR - 유명인 유사도 측정) 본문

Naver A.I Platform

Naver A.I platform - CLOVA Face Recognition (CFR - 유명인 유사도 측정)

오봉봉이 2022. 1. 22. 23:08
728x90

CLOVA Face Recognition (CFR) 실습 (유명인 유사도 측정)

  • 스프링 부트 프로젝트 생성
  • JSON dependency 추가
    • json-simple
    • json
  • CelebrityVO 생성
  • CFRCelebrityService 클래스 추가
    • clovaFaceRecogCel() 메소드 추가
      • API Java 코드 복사해서 붙여넣기
  • APIController에 추가
  • celebrityView.jsp 생성
  • index.jsp에 추가
  • 콘솔에 JSON 형태의 결과 출력 확인
  • JSON 데이터 추출
    • 결과로 받은 JSON 형식의 문자열에서 value와 confidence추출해서 CelebrityVO에 저장
    • CFRCelebrityService 클래스에 메소드로 추가
      • jsonToVo(String jsonResultStr)
        • 결과로 받은 JSON 문자열을 전달 받아, value와 confidence추출
        • CelebrityVO에 저장한 후 리스트(ArrayList)에 추가
        • CelebrityVO 리스트 반환
      • jsonToVoList(String jsonResultStr) 메소드 추가로 인한 변경 사항
        • clovaFaceRecogCel() 메소드에서 jsonToVoList() 호출하는 코드 추가
        • 서비스에서 컨트롤러에게 반환하기 위해 clovaFaceRecogCel() 메소드의 반환형 변경 및 return 값 추가
        • 컨트롤러에서는 서비스 호출하고 결과 받는 코드로 변경하고 Model 추가
        • celebrityView.jsp에 출력 부분 추가
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;
    }
}
@Controller
public class APIController {
    @Autowired
    private CFRCelebrityService cfrserviceCel;

    @RequestMapping("/")
    public String index() {
        return "index";
    }
    @RequestMapping("/faceRecogCel")
    public String faceRecogCel() {
        cfrserviceCel.clovaFaceRecogCel();
        return "celebrityView";
    }
}
package com.ai.ex.naver_ai_platform.service;

import com.ai.ex.naver_ai_platform.model.CelebrityVO;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.springframework.stereotype.Service;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;

@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 = "C:/ai/song.jpg";  // 전송할 이미지 파일
            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) {
            e.printStackTrace();
        }
        return celList;
    }
}
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
    <head>
        <title>결과</title>
    </head>
    <body>
        <h1>인식 결과</h1>
        <a href="/">인덱스 이동</a>
    </body>
</html>
  • 첨부 파일로 변경
    • 현재 코드에서 파일명을 직접 적었는데, 파일을 서버에 올리는 기능 추가
    • 서버의 특정 폴더에 이미지 저장
    • 외부 폴더 지정
    • 결과 페이지에서 서버로 올린 이미지 출력
    • celebrityView.jsp에 파일 업로드 부분 추가
    • 컨트롤러에 추가
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;
    }
}
@Controller
public class APIController {
    @Autowired
    private CFRCelebrityService cfrServiceCel;

    // index 페이지로 이동
    @RequestMapping("/")
    public String index() {
        return "index";
    }

    @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 = "/Users/gobyeongchae/Desktop/productImages";
        // 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";
    }
<%@ 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>
728x90
Comments