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

Naver A.I Platform - OCR(텍스트 인식) 본문

Naver A.I Platform

Naver A.I Platform - OCR(텍스트 인식)

오봉봉이 2022. 1. 24. 15:10
728x90

CLOVA OCR (Optical Character Recognition)

  • 광학 문자 인식 API 서비스
  • 사진 속에서 텍스트 정보를 찾고 의미를 판별하는 기술
  • 언어와 이미지 데이터를 입력 받아서, 그에 맞는 인식 결과를 텍스트로 반환
  • 결과를 콘솔에 출력
    • 텍스트가 포함된 이미지 파일을 전송하고
    • JSON 형태의 결과 받아서 콘솔에 출력
    • OCRService 클래스 생성
      • clovaOCRService() 메소드 추가 : 결과 콘솔에 출력
      • jsonToString() 메소드 추가 : 결과로 추출된 텍스트 반환
@Service
public class OCRService {
    public void clovaOCRService() {
        String apiURL = "";
        String secretKey = "";
        String imageFile = "/Users/gobyeongchae/Desktop/ocr1.PNG";
        String result = "";

        try {
            URL url = new URL(apiURL);
            HttpURLConnection con = (HttpURLConnection)url.openConnection();
            con.setUseCaches(false);
            con.setDoInput(true);
            con.setDoOutput(true);
            con.setReadTimeout(30000);
            con.setRequestMethod("POST");
            String boundary = "----" + UUID.randomUUID().toString().replaceAll("-", "");
            con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
            con.setRequestProperty("X-OCR-SECRET", secretKey);

            JSONObject json = new JSONObject();
            json.put("version", "V2");
            json.put("requestId", UUID.randomUUID().toString());
            json.put("timestamp", System.currentTimeMillis());
            JSONObject image = new JSONObject();
            image.put("format", "jpg");
            image.put("name", "demo");
            JSONArray images = new JSONArray();
            images.put(image);
            json.put("images", images);
            String postParams = json.toString();

            con.connect();
            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
            long start = System.currentTimeMillis();
            File file = new File(imageFile);
            writeMultiPart(wr, postParams, file, boundary);
            wr.close();

            int responseCode = con.getResponseCode();
            BufferedReader br;
            if (responseCode == 200) {
                br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            } else {
                br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
            }
            String inputLine;
            StringBuffer response = new StringBuffer();
            while ((inputLine = br.readLine()) != null) {
                response.append(inputLine);
            }
            br.close();

            System.out.println(response);
            result = jsonToString(response.toString());
            System.out.println(result);
        } catch (Exception e) {
            System.out.println(e);
        }
    }
    private static void writeMultiPart(OutputStream out, String jsonMessage, File file, String boundary) throws
            IOException {
        StringBuilder sb = new StringBuilder();
        sb.append("--").append(boundary).append("\r\n");
        sb.append("Content-Disposition:form-data; name=\"message\"\r\n\r\n");
        sb.append(jsonMessage);
        sb.append("\r\n");

        out.write(sb.toString().getBytes("UTF-8"));
        out.flush();

        if (file != null && file.isFile()) {
            out.write(("--" + boundary + "\r\n").getBytes("UTF-8"));
            StringBuilder fileString = new StringBuilder();
            fileString
                    .append("Content-Disposition:form-data; name=\"file\"; filename=");
            fileString.append("\"" + file.getName() + "\"\r\n");
            fileString.append("Content-Type: application/octet-stream\r\n\r\n");
            out.write(fileString.toString().getBytes("UTF-8"));
            out.flush();

            try (FileInputStream fis = new FileInputStream(file)) {
                byte[] buffer = new byte[8192];
                int count;
                while ((count = fis.read(buffer)) != -1) {
                    out.write(buffer, 0, count);
                }
                out.write("\r\n".getBytes());
            }

            out.write(("--" + boundary + "--\r\n").getBytes("UTF-8"));
        }
        out.flush();
    }
    public String jsonToString(String jsonResultStr) {
        String resultText = "";
        // API 호출 결과 받은 JSON 형태 문자열에서 텍스트 추출
        // JSONParser  사용하지 않음
        // images / 0 / fields / inferText 추출
        JSONObject jsonObj = new JSONObject(jsonResultStr);
        JSONArray imageArray = (JSONArray) jsonObj.get("images");
        if(imageArray != null) {
            JSONObject tempObj = (JSONObject) imageArray.get(0);
            JSONArray fieldArray = (JSONArray) tempObj.get("fields");
            if(fieldArray != null) {
                for(int i=0; i<fieldArray.length(); i++) {
                    tempObj = (JSONObject) fieldArray.get(i);
                    resultText += (String) tempObj.get("inferText") + " ";
                }
            }
        } else {
            System.out.println("없음");
        }
        return resultText;
    }
}
    // ocr 페이지 호출
    @RequestMapping("/clovaOCR")
    public void clovaOCR() {
        ocrService.clovaOCRService();
    }
  • 서비스에서 결과 반환하고 컨트롤러에서 뷰 페이지로 출력
    • REST API 방법 : @RestController 사용
    • 파일 업로드
    • Ajax 사용해서 서버로 전달하고 결과 받아서 현재 페이지에 출력
    • APIRestController 클래스 추가 : @RestController
      • 서비스 클래스의 메소드 호출하고 결과 받아서 반환
    • ocr.js
      • Ajax 사용해서 파일 전송하고 결과 받아서 현재 페이지에 출력
@Service
public class OCRService {
    public String clovaOCRService(String filePathName) {
        String apiURL = "";
        String secretKey = "";
        String imageFile = filePathName;
        String result = "";
        try {
            URL url = new URL(apiURL);
            HttpURLConnection con = (HttpURLConnection)url.openConnection();
            con.setUseCaches(false);
            con.setDoInput(true);
            con.setDoOutput(true);
            con.setReadTimeout(30000);
            con.setRequestMethod("POST");
            String boundary = "----" + UUID.randomUUID().toString().replaceAll("-", "");
            con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
            con.setRequestProperty("X-OCR-SECRET", secretKey);
            JSONObject json = new JSONObject();
            json.put("version", "V2");
            json.put("requestId", UUID.randomUUID().toString());
            json.put("timestamp", System.currentTimeMillis());
            JSONObject image = new JSONObject();
            image.put("format", "jpg");
            image.put("name", "demo");
            JSONArray images = new JSONArray();
            images.put(image);
            json.put("images", images);
            String postParams = json.toString();
            con.connect();
            DataOutputStream wr = new DataOutputStream(con.getOutputStream());
            long start = System.currentTimeMillis();
            File file = new File(imageFile);
            writeMultiPart(wr, postParams, file, boundary);
            wr.close();
            int responseCode = con.getResponseCode();
            BufferedReader br;
            if (responseCode == 200) {
                br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            } else {
                br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
            }
            String inputLine;
            StringBuffer response = new StringBuffer();
            while ((inputLine = br.readLine()) != null) {
                response.append(inputLine);
            }
            br.close();
            System.out.println(response); // API 호출 결과를 콘솔에 출력
            // jsonToString() 메소드 호출하고 결과 받아옴
            result = jsonToString(response.toString());
            System.out.println(result); // 뭔가가 있는 줄 알았어요

        } catch (Exception e) {
            System.out.println(e);
        }
        return result;
    }
    private static void writeMultiPart(OutputStream out, String jsonMessage, File file, String boundary) throws
            IOException {
        StringBuilder sb = new StringBuilder();
        sb.append("--").append(boundary).append("\r\n");
        sb.append("Content-Disposition:form-data; name=\"message\"\r\n\r\n");
        sb.append(jsonMessage);
        sb.append("\r\n");

        out.write(sb.toString().getBytes("UTF-8"));
        out.flush();

        if (file != null && file.isFile()) {
            out.write(("--" + boundary + "\r\n").getBytes("UTF-8"));
            StringBuilder fileString = new StringBuilder();
            fileString
                    .append("Content-Disposition:form-data; name=\"file\"; filename=");
            fileString.append("\"" + file.getName() + "\"\r\n");
            fileString.append("Content-Type: application/octet-stream\r\n\r\n");
            out.write(fileString.toString().getBytes("UTF-8"));
            out.flush();

            try (FileInputStream fis = new FileInputStream(file)) {
                byte[] buffer = new byte[8192];
                int count;
                while ((count = fis.read(buffer)) != -1) {
                    out.write(buffer, 0, count);
                }
                out.write("\r\n".getBytes());
            }

            out.write(("--" + boundary + "--\r\n").getBytes("UTF-8"));
        }
        out.flush();
    }
    public String jsonToString(String jsonResultStr) {
        String resultText = "";
        // API 호출 결과 받은 JSON 형태 문자열에서 텍스트 추출
        // JSONParser  사용하지 않음
        // images / 0 / fields / inferText 추출
        JSONObject jsonObj = new JSONObject(jsonResultStr);
        JSONArray imageArray = (JSONArray) jsonObj.get("images");
        if(imageArray != null) {
            JSONObject tempObj = (JSONObject) imageArray.get(0);
            JSONArray fieldArray = (JSONArray) tempObj.get("fields");
            if(fieldArray != null) {
                for(int i=0; i<fieldArray.length(); i++) {
                    tempObj = (JSONObject) fieldArray.get(i);
                    resultText += (String) tempObj.get("inferText") + " ";
                }
            }
        } else {
            System.out.println("없음");
        }
        return resultText;
    }
}
@RestController
public class APIRestController {
    @Autowired
    private OCRService ocrService;
    @RequestMapping("/clovaOCR")
    public String clovaOCR(@RequestParam("uploadFile") MultipartFile file){
        String result = "";
        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와 파일명 전달  -> 서비스 메소드에서 변경
            // 서비스에서 반환된 텍스트를 result에 저장
            result = ocrService.clovaOCRService(filePathName);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}
<%@ 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>OCR</title>
        <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
        <script src="/js/ocr.js"></script>
    </head>
    <body>
        <!--  파일 업로드 -->
        <h3>OCR : 텍스트 추출</h3>
        <form id="ocrForm" enctype="multipart/form-data">
            파일 : <input type="file" id="uploadFile" name="uploadFile"> 
            <input type="submit" value="결과 확인">        
        </form>
        <br><br>

        <!-- 결과 출력 (텍스트) -->
        <h3>OCR : 텍스트 추출 결과</h3>
        <div id="resultDiv"></div>
        <br><br>

        <!-- 이미지 출력 (새로운 방법으로 알려줄 것임)  -->
        <h3>OCR : 원본 이미지 파일</h3>
        <div id="resultImg"></div>

        <br><br>
        <a href="/">index 페이지로 이동</a>
    </body>
</html>
$(function () {
    // submit 했을 때 처리
    $('#ocrForm').on('submit', function (event) {
        event.preventDefault();
        var formData = new FormData($('#ocrForm')[0]);
        var fileName = $('#uploadFile').val().split("\\").pop();
        $.ajax({
            type : "post",
            enctype : "multipart/form-data",
            url : "clovaOCR",
            data : formData,
            processData : false, // 필수
            contentType : false, // 필수
            success:function (result) {
                $('#resultDiv').text(result);
                // 이미지 출력 (div에 append)
                $('#resultImg').empty();
                $('#resultImg').append('<img src="/images/'+fileName+'"/>');
            },
            error:function (e) {
                alert("오류 발생" + e);
            }
        });
    })
})
728x90
Comments