본문 바로가기

API/NAVER CLOVA

Object Detection (객체 탐지)

Object Detection (객체 탐지)

  • 이미지 내 사람, 동물, 사물 등 객체의 타입과 위치를 감지하여 정보 제공
  • 탐지된 객체명, 객체의 수, 바운딩 박스용 좌표, 객체별 확률값
  • Object Detection 서비스 추가하여 사용

개발 가이드 확인

https://api.ncloud-docs.com/docs/ai-naver-objectdetection-object

 

object detection (객체 탐지) - Object Detection

 

api.ncloud-docs.com


Object Detection 실습

(1) 콘솔에 결과 출력

(2) JSON 형태에서 결과에서 이름, 박스 좌표 추출해서 반환

 

ObjectDetectionService

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.ObjectVO;

@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 poseArray = (JSONArray) jsonObj.get("predictions");			
			JSONObject obj0 = (JSONObject) poseArray.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) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}		
		
		return objectList;
	}
}

 

APIController

@Autowired
private ObjectDetectionService objService;

// 객체 탐지
// (1) 결과를 콘솔에 출력
/*	@RequestMapping("/objectDetect")
    public void objectDetect() {
        objService.objectDetect();
    }*/

@RequestMapping("/objectForm")
public String objectForm() {
    return "objectView";
}

 

APIRestController

@Autowired
private ObjectDetectionService objectService;

@RequestMapping("/objectDetect")
	public ArrayList<ObjectVO>  objectDetect(@RequestParam("uploadFile") MultipartFile file) {		
		
		ArrayList<ObjectVO>objectList = null; 
		
		try {
			// 1. 파일 저장 경로 설정 : 실제 서비스되는 위치 (프로젝트 외부에 저장)
			String uploadPath = "C:/upload/";
			
			// 2. 원본 파일 이름 알아오기
			String originalFileName = file.getOriginalFilename();
			String filePathName = uploadPath + originalFileName;
			
			// 3. 파일 생성
			File file1 = new File(filePathName);
			
			// 4. 서버로 전송
			file.transferTo(file1);				
			
			// 서비스에 파일 path와 파일명 전달  -> 서비스 메소드에서 변경
			// 서비스에서 반환된 PoseVO 리스트 저장
			objectList = objectService.objectDetect(filePathName);			
		
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		return objectList;
	}

 

index.jsp

<a href="objectForm">객체 탐지</a><br><br>

 

ObjectVO

package com.ai.ex.model;

public class ObjectVO {
	private String name;
	private double x1;
	private double x2;
	private double y1;
	private double y2;
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public double getX1() {
		return x1;
	}
	public void setX1(double x1) {
		this.x1 = x1;
	}
	public double getX2() {
		return x2;
	}
	public void setX2(double x2) {
		this.x2 = x2;
	}
	public double getY1() {
		return y1;
	}
	public void setY1(double y1) {
		this.y1 = y1;
	}
	public double getY2() {
		return y2;
	}
	public void setY2(double y2) {
		this.y2 = y2;
	}	
	
}

 

object.js

/**
 * object.js
 */
 
 $(function(){
	
	$('#objectForm').on('submit', function(event){	
		event.preventDefault();
		 var formData = new FormData($('#objectForm')[0]);
		 
		 // 업로드된 파일명 알아오기
		 var fileName = $('#uploadFile').val().split("\\").pop();
		 //alert(fileName);
		 
		$.ajax({
			url:"objectDetect",
			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 ="/images/" + 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 끝	
	});		
});

 

objectView.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title>객체 탐지</title>
		<script src="<c:url value='/js/jquery-3.6.0.min.js'/>"></script>
		<script src="<c:url value='/js/object.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>