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

Naver A.I Platform - Object Detection (객체 탐지) 본문

Naver A.I Platform

Naver A.I Platform - Object Detection (객체 탐지)

오봉봉이 2022. 1. 25. 15:41
728x90

Object Detection (객체 탐지)

  • 이미지 내 사람, 동물, 사물 등 객체의 타입과 위치를 감지하여 정보를 제공하는 API 서비스
  • 탐지된 객체명, 객체의 수, 바운딩 박스용 좌표, 객체별 확률값
  • ObjectDetectionService 클래스 생성
    • objectDetectService() 메소드 추가
  • (1) 콘솔에 결과 출력
@Service
public class ObjectDetectionService {
    public void objectDetect() {
        StringBuffer reqStr = new StringBuffer();
        String clientId = "";//애플리케이션 클라이언트 아이디값";
        String clientSecret = "";//애플리케이션 클라이언트 시크릿값";

        try {
            String paramName = "image"; // 파라미터명은 image로 지정
            String imgFile = "/Users/gobyeongchae/Desktop/images/animal1.jpg";
            File uploadFile = new File(imgFile);
            String apiURL = "https://naveropenapi.apigw.ntruss.com/vision-obj/v1/detect"; // 객체 인식
            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());
            } else {
                System.out.println("error !!!");
            }
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}
@RequestMapping("/objDetect")
    public void objDetect() {
        objectDetectionService.objectDetect();
    }
  • (2) JSON 형태에서 결과에서 이름, 박스 좌표 추출해서 반환
    • ObjectVO 생성
    • jsonToVoList() 메소드 추가
    • 파일 업로드 기능
    • @RestController 사용
// 포즈 인식
    @RequestMapping("/objDetect")
    public ArrayList<ObjectVO>  objectDetect(@RequestParam("uploadFile") MultipartFile file) {
        ArrayList<ObjectVO>objectList = null;
        try {
            // 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);
            // 서비스에 파일 path와 파일명 전달  -> 서비스 메소드에서 변경
            // 서비스에서 반환된 PoseVO 리스트 저장
            objectList = objectDetectionService.objectDetect(filePathName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return objectList;
    }
@Service
public class ObjectDetectionService {
    public  ArrayList<ObjectVO> objectDetect(String filePathName) {
        StringBuffer reqStr = new StringBuffer();
        String clientId = "";//애플리케이션 클라이언트 아이디값";
        String clientSecret = "";//애플리케이션 클라이언트 시크릿값";

        ArrayList<ObjectVO> objectList = new ArrayList<ObjectVO>();

        try {
            String paramName = "image"; // 파라미터명은 image로 지정
            String imgFile = filePathName;
            File uploadFile = new File(imgFile);
            String apiURL = "https://naveropenapi.apigw.ntruss.com/vision-obj/v1/detect"; // 객체 인식
            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());
                objectList = jsonToVoList(response.toString());
            }
            /*   else {
                System.out.println("error !!!");
            }*/
        } catch (Exception e) {
            System.out.println(e);
        }
        return objectList;
    }
    // API 서버로부터 받은 JSON 형태의 테이블부터 names와 x1, x2, y1, y2 추출 후 VO 리스트 만들어 반환
    public ArrayList<ObjectVO> jsonToVoList(String jsonResultStr){
        ArrayList<ObjectVO> objectList = new ArrayList<ObjectVO>();

        try {
            // JSON 형태의 문자열에서 JSON 오브젝트 "predictions" 추출해서 JSONArray에 저장
            JSONParser jsonParser = new JSONParser();
            JSONObject jsonObj = (JSONObject) jsonParser.parse(jsonResultStr);
            JSONArray objArray = (JSONArray) jsonObj.get("predictions");
            JSONObject obj0 = (JSONObject) objArray.get(0);

            JSONArray nameArray = (JSONArray) obj0.get("detection_names");
            JSONArray boxArray = (JSONArray) obj0.get("detection_boxes");

            for(int i=0; i<nameArray.size(); i++) {
                // name 추출
                String name = (String) nameArray.get(i);

                //x1, y1, x2, y2 추출
                JSONArray box = (JSONArray) boxArray.get(i);
                double x1 =(double) box.get(0);
                double y1 =(double) box.get(1);
                double x2 =(double) box.get(2);
                double y2 =(double) box.get(3);

                // VO에 저장
                ObjectVO vo = new ObjectVO();
                vo.setName(name);
                vo.setX1(x1);
                vo.setY1(y1);
                vo.setX2(x2);
                vo.setY2(y2);

                //리스트에 추가
                objectList.add(vo);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return objectList;
    }
}
<html>
    <head>
        <meta charset="UTF-8">
        <title>Object Detect</title>
        <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
        <script src="js/objDetect.js"></script>
    </head>
    <body>
        <!--  파일 업로드 -->
        <h3>포즈 인식</h3>
        <form id="objectForm" enctype="multipart/form-data">
            파일 : <input type="file" id="uploadFile" name="uploadFile">
            <input type="submit" value="결과 확인">
        </form>
        <br><br>
        <!-- 결과 출력  -->
        <h3>포즈 인식 결과를 이미지에 좌표로 표시</h3>
        <canvas id="objectCanvas" width="600" height="600"></canvas>
        <br><br>
        <!-- 객체와 좌표 값 출력 -->
        <div id="resultDiv"></div>
        <br><br>
        <a href="/">index 페이지로 이동</a>
    </body>
</html>
$(function () {
    $('#objectForm').on('submit', function(event){
        event.preventDefault();
        var formData = new FormData($('#objectForm')[0]);

        // 업로드된 파일명 알아오기
        var fileName = $('#uploadFile').val().split("\\").pop();
        //alert(fileName);

        $.ajax({
            url:"objDetect",
            enctype:'multipart/form-data',
            type:"post",
            data:formData,
            processData: false,  // 필수
            contentType: false,  // 필스
            success:function(result){
                drawCanvas(result, fileName);
            },
            error:function(e){
                alert("오류가 발생했습니다." + e)
            }
        });

        function drawCanvas(result, fileName){
            //mycanvas 캔버스 태그 객체로 생성
            var canvas = document.getElementById("objectCanvas");
            var context = canvas.getContext("2d");

            var objectImage = new Image();
            objectImage.src ="/objimages/" + fileName;
            objectImage.width = canvas.width;
            objectImage.height = canvas.height;

            objectImage.onload = function(){
                context.drawImage(objectImage,0, 0, objectImage.width, objectImage.height );
                var values = "";
                $.each(result, function(){
                    // 사각형 좌표
                    var x1 = this.x1 * objectImage.width;
                    var y1 = this.y1 * objectImage.height;
                    var x2 = this.x2 * objectImage.width;
                    var y2 = this.y2 * objectImage.height;

                    context.font = '15px batang';
                    context.fillStyle = "rgb(255, 0, 255)";

                    context.strokeStyle = "red";//선색상
                    context.lineWidth = 2; // 선 굵기

                    context.fillText(this.name, y1, x1);
                    context.strokeRect(y1, x1, y2-y1, x2-x1);
                    values += this.name + "(" + this.x1 + ", " + this.y1 + ", " + this.x2 + ", " + this.y2 + ") <br>";
                });
                $('#resultDiv').html(values);
            };
        }    // function 끝
    });
});
728x90
Comments