Computer Vision API Java 자습서

등록일시: 2017-11-23 08:00,  수정일시: 2017-11-27 22:55
조회수: 3,564
이 문서는 Cognitive Services 기술을 널리 알리고자 하는 개인적인 취지로 제공되는 번역문서입니다. 이 문서에 대한 모든 저작권은 마이크로소프트에 있으며 요청이 있을 경우 언제라도 게시가 중단될 수 있습니다. 번역 내용에 오역이 존재할 수 있고 주석은 번역자 개인의 의견일 뿐이며 마이크로소프트는 이에 관한 어떠한 보장도 하지 않습니다. 번역이 완료된 이후에도 대상 제품 및 기술이 개선되거나 변경됨에 따라 원문의 내용도 변경되거나 보완되었을 수 있으므로 주의하시기 바랍니다.
본문에서는 Computer Vision API를 활용하는 기초적인 Java Swing 예제 응용 프로그램을 살펴봅니다.

본 자습서에서는 Microsoft Cognitive Services의 Computer Vision REST API 기능을 살펴봅니다.

Computer Vision REST API를 이용해서 광학 문자 인식(OCR)을 수행하거나 스마트하게 자른 썸네일을 생성하고, 이미지에서 얼굴을 비롯한 다양한 시각적 특징들을 감지해서 분류하고, 태깅하고, 설명하는 Java Swing 응용 프로그램을 살펴봅니다. 본문의 예제 응용 프로그램은 이미지의 URL을 전달하거나 로컬에 저장된 이미지 파일을 제출하는 방식으로 동작합니다. 이 오픈 소스 예제 응용 프로그램을 템플릿으로 삼아서 Java로 Computer Vision REST API를 활용하는 자신만의 개별 응용 프로그램을 개발해도 무방합니다.

본문에서는 Computer Vision API를 사용해서 다음과 같은 작업들을 수행하는 방법을 살펴봅니다:

  • 이미지 분석하기
  • 이미지에 포함된 자연적 또는 인공적 랜드마크 식별하기
  • 이미지에 포함된 유명인사 식별하기
  • 이미지로부터 고품질의 썸네일 생성하기
  • 이미지에서 인쇄된 텍스트 읽기
  • 이미지에서 필기체 텍스트 읽기

본 자습서를 위한 Java Swing 폼 응용 프로그램은 이미 준비되어 있지만, 아직 실제 기능은 구현되지 않은 상태입니다. 본문에서는 이 예제 응용 프로그램에 Computer Vision REST API 관련 코드를 하나씩 추가해보면서 응용 프로그램의 기능을 완성할 것입니다.

요구 사항

플랫폼 요구 사항

본문의 예제 응용 프로그램은 NetBeans IDE를 이용해서 개발되었습니다. 보다 구체적으로 말하자면 Java SE 버전의 NetBeans가 사용되었으며 이 IDE는 여기에서 다운로드 받을 수 있습니다.

Computer Vision API 구독 및 구독 키 발급받기

예제 응용 프로그램을 직접 실행해보려면, 먼저 Microsoft Cognitive Services의 (구 프로젝트 Oxford) 일부인 Computer Vision API에 가입해야 합니다. 구독 및 구독 키 관리에 관한 세부적인 사항들은 Cognitive Services 체험하기 페이지를 참고하시기 바랍니다. 본 자습서에서는 발급된 기본 키와 보조 키, 모두 사용 가능합니다.

자습서 프로젝트 다운로드

  1. Cognitive Services Java Computer Vision Tutorial 리파지터리로 이동합니다.
  2. Clone or download 버튼을 클릭합니다.
  3. Download ZIP 버튼을 클릭해서 자습서 프로젝트의 .zip 파일을 다운로드 받습니다.

NetBeans IDE가 자체적으로 .zip 파일을 프로젝트로 가져올 수 있기 때문에 .zip 파일의 압축을 풀 필요는 없습니다.

자습서 프로젝트 가져오기

다운로드 받은 cognitive-services-java-computer-vision-tutorial-master.zip 파일을 NetBeans로 가져옵니다.

  1. NetBeans에서 File > Import Project > From ZIP... 메뉴를 클릭하면, Import Project(s) from ZIP 대화 상자가 나타납니다.
  2. ZIP File: 필드의 Browse 버튼을 클릭한 다음, cognitive-services-java-computer-vision-tutorial-master.zip 파일을 선택하고 열기(Open) 버튼을 클릭합니다.
  3. Import Project(s) from ZIP 대화 상자에서 Import 버튼을 클릭합니다.
  4. Projects 패널에서 ComputerVision > Source Packages > <default package> 노드를 확장합니다. NetBeans의 일부 버전은 Source Packages > <default package> 노드 대신 src 노드를 사용하는데, 그 경우에는 src 노드를 확장합니다.
  5. MainFrame.java 파일을 더블 클릭해서 NetBeans 편집기에서 엽니다. 그러면 MainFrame.java 파일의 Design 탭이 나타납니다.
  6. Source 탭을 클릭해서 Java 소스 코드를 살펴봅니다.

자습서 프로젝트 빌드 및 실행하기

  1. F6 키를 누르면 자습서 응용 프로그램이 빌드되고 실행됩니다.

    자습서 응용 프로그램의 각 탭을 클릭해보면 해당 기능에 대한 패인이 나타납니다. 현재 각 버튼들에는 빈 메서드만 연결되어 있기 때문에 아무런 작업도 수행하지 않습니다.

    그리고 창의 하단을 살펴보면 Subscription Key 필드 및 Subscription Region 필드가 존재합니다. 이 필드들에는 유효한 구독 키와 해당 구독 키가 유효한 올바른 지역을 입력해야 합니다. 구독 키를 발급받으려면 Cognitive Services 체험하기 페이지를 참고하시기 바랍니다. 이 Computer Vision 무료 평가판 서비스에서 구독 키를 발급받은 경우, 기본값인 westcentralus가 구독 키가 유효한 지역입니다.

  2. 자습서 응용 프로그램을 종료합니다.

역주

예제 프로젝트의 소스를 검색해보면 subscriptionRegionComboBox.setModel(...) 메서드 호출 부분을 찾을 수 있는데, 여기에 지역 목록을 지정하는 문자열 배열이 전달되는 것을 볼 수 있습니다. 이 문자열 배열에 eastasia 등을 추가하여 원하는 지역을 등록할 수 있는데, 코드를 직접 수정할 수는 없으며 Design 탭에서 해당 컨트롤을 선택한 다음, 우측의 Properties 패인에서 model 항목을 편집하여 처리가 가능합니다.

자습서 코드 추가하기

본문의 Java Swing 응용 프로그램은 여섯 개의 탭으로 구성되어 있으며, 각각의 탭은 Computer Vision의 서로 다른 기능들을 (분석, OCR 등) 보여줍니다. 여섯 개의 자습서 절들은 서로 상호 의존적이지 않으므로, 한 절의 코드만 추가하거나, 여섯 개 절들의 코드를 모두를 추가하거나, 또는 한 두 절의 코드만 추가할 수도 있습니다. 물론 절을 추가하는 순서도 전혀 상관 없습니다.

이미지 분석하기

Computer Vision API의 분석 기능은 이미지에 포함된 2,000 가지 이상의 인식 가능한 개체, 생명체, 풍경 및 동작을 분석합니다. 분석 기능은 처리가 완료되면 설명 태그, 색상 분석, 캡션 등으로 이미지를 설명하는 JSON 개체를 반환합니다.

자습서 응용 프로그램의 분석 기능을 구현하려면, 다음의 단계들을 수행합니다:

분석 단계 1: 폼 버튼에 대한 이벤트 처리기 추가하기

analyzeImageButtonActionPerformed 이벤트 처리기 메서드는 폼을 초기화하고, URL로 지정한 이미지를 출력한 다음, 이미지를 분석하기 위한 AnalyzeImage 메서드를 호출합니다. AnalyzeImage 메서드가 결과를 반환하면, 정리된 JSON 응답을 Response 텍스트 영역에 출력하고, JSONObject에서 첫 번째 캡션을 추출한 다음, 캡션과 해당 캡션의 신뢰 수준을 표시합니다.

다음 코드를 analyzeImageButtonActionPerformed 메서드에 복사해서 붙여 넣습니다.

노트

NetBeans에서는 메서드를 정의하는 줄이나 (private void) 메서드를 닫는 중괄호는 편집할 수 없습니다. 코드를 복사하려면, 메서드 정의와 닫는 중괄호 사이의 코드만 복사해서 메서드 본문에 붙여 넣습니다.

private void analyzeImageButtonActionPerformed(java.awt.event.ActionEvent evt) {
    URL analyzeImageUrl;

    // Clear out the previous image, response, and caption, if any.
    analyzeImage.setIcon(new ImageIcon());
    analyzeCaptionLabel.setText("");
    analyzeResponseTextArea.setText("");

    // Display the image specified in the text box.
    try {
        analyzeImageUrl = new URL(analyzeImageUriTextBox.getText());
        BufferedImage bImage = ImageIO.read(analyzeImageUrl);
        scaleAndShowImage(bImage, analyzeImage);
    } catch(IOException e) {
        analyzeResponseTextArea.setText("Error loading Analyze image: " + e.getMessage());
        return;
    }

    // Analyze the image.
    JSONObject jsonObj = AnalyzeImage(analyzeImageUrl.toString());

    // A return of null indicates failure.
    if (jsonObj == null) {
        return;
    }

    // Format and display the JSON response.
    analyzeResponseTextArea.setText(jsonObj.toString(2));

    // Extract the text and confidence from the first caption in the description object.
    if (jsonObj.has("description") && jsonObj.getJSONObject("description").has("captions")) {

        JSONObject jsonCaption = jsonObj.getJSONObject("description").getJSONArray("captions").getJSONObject(0);

        if (jsonCaption.has("text") && jsonCaption.has("confidence")) {

            analyzeCaptionLabel.setText("Caption: " + jsonCaption.getString("text") + 
                    " (confidence: " + jsonCaption.getDouble("confidence") + ").");
        }
    }
}

분석 단계 2: REST API 호출 래퍼 추가하기

AnalyzeImage 메서드는 이미지를 분석하는 REST API 호출을 래핑합니다. 이 메서드는 이미지를 설명하는 JSONObject를 반환하거나, 오류가 발생할 경우 null을 반환합니다.

다음 AnalyzeImage 메서드를 복사해서 analyzeImageButtonActionPerformed 메서드 바로 아래에 붙여 넣습니다.

/**
 * Encapsulates the Microsoft Cognitive Services REST API call to analyze an image.
 * @param imageUrl: The string URL of the image to analyze.
 * @return: A JSONObject describing the image, or null if a runtime error occurs.
 */
private JSONObject AnalyzeImage(String imageUrl) {
    try (CloseableHttpClient httpclient = HttpClientBuilder.create().build())
    {
        // Create the URI to access the REST API call for Analyze Image.
        String uriString = uriBasePreRegion + 
                String.valueOf(subscriptionRegionComboBox.getSelectedItem()) + 
                uriBasePostRegion + uriBaseAnalyze;
        URIBuilder builder = new URIBuilder(uriString);

        // Request parameters. All of them are optional.
        builder.setParameter("visualFeatures", "Categories,Description,Color,Adult");
        builder.setParameter("language", "en");

        // Prepare the URI for the REST API call.
        URI uri = builder.build();
        HttpPost request = new HttpPost(uri);

        // Request headers.
        request.setHeader("Content-Type", "application/json");
        request.setHeader("Ocp-Apim-Subscription-Key", subscriptionKeyTextField.getText());

        // Request body.
        StringEntity reqEntity = new StringEntity("{\"url\":\"" + imageUrl + "\"}");
        request.setEntity(reqEntity);

        // Execute the REST API call and get the response entity.
        HttpResponse response = httpclient.execute(request);
        HttpEntity entity = response.getEntity();

        // If we got a response, parse it and display it.
        if (entity != null) {
            // Return the JSONObject.
            String jsonString = EntityUtils.toString(entity);
            return new JSONObject(jsonString);
        } else {
            // No response. Return null.
            return null;
        }
    }
    catch (Exception e)
    {
        // Display error message.
        System.out.println(e.getMessage());
        return null;
    }
}

분석 단계 3: 응용 프로그램 실행하기

F6 키를 눌러서 응용 프로그램을 실행합니다. Subscription Key 필드에는 구독 키를 입력하고, Subscription Region 필드가 올바른 지역을 선택하고 있는지 확인합니다. 분석하고자 하는 이미지의 URL을 입력한 다음, Analyze Image 버튼을 클릭해서 이미지를 분석하고 그 결과를 확인합니다.

랜드마크 식별하기

Computer Vision의 랜드마크 기능은 이미지에 포함된 산이나 유명한 빌딩 같은, 자연적 또는 인공적 랜드마크를 분석합니다. 그리고 처리가 완료되면 이미지에서 발견한 랜드마크를 식별하는 JSON 개체를 반환합니다.

자습서 응용 프로그램의 랜드마크 기능을 구현하려면, 다음의 단계들을 수행합니다:

랜드마크 단계 1: 폼 버튼에 대한 이벤트 처리기 추가하기

landmarkImageButtonActionPerformed 이벤트 처리기 메서드는 폼을 초기화하고, URL로 지정한 이미지를 출력한 다음, 이미지를 분석하기 위한 LandmarkImage 메서드를 호출합니다. LandmarkImage 메서드가 결과를 반환하면, 정리된 JSON 응답을 Response 텍스트 영역에 출력하고, JSONObject에서 첫 번째 랜드마크 이름을 추출한 다음, 랜드마크 이름과 식별 결과의 신뢰 수준을 창에 표시합니다.

다음 코드를 landmarkImageButtonActionPerformed 메서드에 복사해서 붙여 넣습니다.

노트

NetBeans에서는 메서드를 정의하는 줄이나 (private void) 메서드를 닫는 중괄호는 편집할 수 없습니다. 코드를 복사하려면, 메서드 정의와 닫는 중괄호 사이의 코드만 복사해서 메서드 본문에 붙여 넣습니다.

private void landmarkImageButtonActionPerformed(java.awt.event.ActionEvent evt) {
    URL landmarkImageUrl;

    // Clear out the previous image, response, and caption, if any.
    landmarkImage.setIcon(new ImageIcon());
    landmarkCaptionLabel.setText("");
    landmarkResponseTextArea.setText("");

    // Display the image specified in the text box.
    try {
        landmarkImageUrl = new URL(landmarkImageUriTextBox.getText());
        BufferedImage bImage = ImageIO.read(landmarkImageUrl);
        scaleAndShowImage(bImage, landmarkImage);
    } catch(IOException e) {
        landmarkResponseTextArea.setText("Error loading Landmark image: " + e.getMessage());
        return;
    }

    // Identify the landmark in the image.
    JSONObject jsonObj = LandmarkImage(landmarkImageUrl.toString());

    // A return of null indicates failure.
    if (jsonObj == null) {
        return;
    }

    // Format and display the JSON response.
    landmarkResponseTextArea.setText(jsonObj.toString(2));

    // Extract the text and confidence from the first caption in the description object.
    if (jsonObj.has("result") && jsonObj.getJSONObject("result").has("landmarks")) {

        JSONObject jsonCaption = jsonObj.getJSONObject("result").getJSONArray("landmarks").getJSONObject(0);

        if (jsonCaption.has("name") && jsonCaption.has("confidence")) {

            landmarkCaptionLabel.setText("Caption: " + jsonCaption.getString("name") + 
                    " (confidence: " + jsonCaption.getDouble("confidence") + ").");
        }
    }
}

랜드마크 단계 2: REST API 호출 래퍼 추가하기

LandmarkImage 메서드는 이미지를 분석하는 REST API 호출을 래핑합니다. 이 메서드는 랜드마크를 설명하는 JSONObject를 반환하거나, 오류가 발생할 경우 null을 반환합니다.

다음 LandmarkImage 메서드를 복사해서 landmarkImageButtonActionPerformed 메서드 바로 아래에 붙여 넣습니다.

/**
 * Encapsulates the Microsoft Cognitive Services REST API call to identify a landmark in an image.
 * @param imageUrl: The string URL of the image to process.
 * @return: A JSONObject describing the image, or null if a runtime error occurs.
 */
private JSONObject LandmarkImage(String imageUrl) {
    try (CloseableHttpClient httpclient = HttpClientBuilder.create().build())
    {
        // Create the URI to access the REST API call to identify a Landmark in an image.
        String uriString = uriBasePreRegion + 
                String.valueOf(subscriptionRegionComboBox.getSelectedItem()) + 
                uriBasePostRegion + uriBaseLandmark;
        URIBuilder builder = new URIBuilder(uriString);

        // Request parameters. All of them are optional.
        builder.setParameter("visualFeatures", "Categories,Description,Color");
        builder.setParameter("language", "en");

        // Prepare the URI for the REST API call.
        URI uri = builder.build();
        HttpPost request = new HttpPost(uri);

        // Request headers.
        request.setHeader("Content-Type", "application/json");
        request.setHeader("Ocp-Apim-Subscription-Key", subscriptionKeyTextField.getText());

        // Request body.
        StringEntity reqEntity = new StringEntity("{\"url\":\"" + imageUrl + "\"}");
        request.setEntity(reqEntity);

        // Execute the REST API call and get the response entity.
        HttpResponse response = httpclient.execute(request);
        HttpEntity entity = response.getEntity();

        // If we got a response, parse it and display it.
        if (entity != null) {
            // Return the JSONObject.
            String jsonString = EntityUtils.toString(entity);
            return new JSONObject(jsonString);
        } else {
            // No response. Return null.
            return null;
        }
    }
    catch (Exception e)
    {
        // Display error message.
        System.out.println(e.getMessage());
        return null;
    }
}

랜드마크 단계 3: 응용 프로그램 실행하기

F6 키를 눌러서 응용 프로그램을 실행합니다. Subscription Key 필드에는 구독 키를 입력하고, Subscription Region 필드가 올바른 지역을 선택하고 있는지 확인합니다. Landmark 탭을 클릭하고 분석하고자 하는 이미지의 URL을 입력한 다음, Analyze Image 버튼을 클릭해서 이미지를 분석하고 그 결과를 확인합니다.

유명인사 식별하기

Computer Vision의 유명인사 기능은 이미지에 포함된 유명한 사람들을 분석합니다. 그리고 처리가 완료되면 이미지에서 발견된 유명인사를 식별하는 JSON 개체를 반환합니다.

자습서 응용 프로그램의 유명인사 기능을 구현하려면, 다음의 단계들을 수행합니다:

유명인사 단계 1: 폼 버튼에 대한 이벤트 처리기 추가하기

celebritiesImageButtonActionPerformed 이벤트 처리기 메서드는 폼을 초기화하고, URL로 지정한 이미지를 출력한 다음, 이미지를 분석하기 위한 CelebritiesImage 메서드를 호출합니다. CelebritiesImage 메서드가 결과를 반환하면, 정리된 JSON 응답을 Response 텍스트 영역에 출력하고, JSONObject에서 첫 번째 유명인사 이름을 추출한 다음, 유명인사 이름과 식별 결과의 신뢰 수준을 창에 표시합니다.

다음 코드를 celebritiesImageButtonActionPerformed 메서드에 복사해서 붙여 넣습니다.

노트

NetBeans에서는 메서드를 정의하는 줄이나 (private void) 메서드를 닫는 중괄호는 편집할 수 없습니다. 코드를 복사하려면, 메서드 정의와 닫는 중괄호 사이의 코드만 복사해서 메서드 본문에 붙여 넣습니다.

private void celebritiesImageButtonActionPerformed(java.awt.event.ActionEvent evt) {
    URL celebritiesImageUrl;

    // Clear out the previous image, response, and caption, if any.
    celebritiesImage.setIcon(new ImageIcon());
    celebritiesCaptionLabel.setText("");
    celebritiesResponseTextArea.setText("");

    // Display the image specified in the text box.
    try {
        celebritiesImageUrl = new URL(celebritiesImageUriTextBox.getText());
        BufferedImage bImage = ImageIO.read(celebritiesImageUrl);
        scaleAndShowImage(bImage, celebritiesImage);
    } catch(IOException e) {
        celebritiesResponseTextArea.setText("Error loading Celebrity image: " + e.getMessage());
        return;
    }

    // Identify the celebrities in the image.
    JSONObject jsonObj = CelebritiesImage(celebritiesImageUrl.toString());

    // A return of null indicates failure.
    if (jsonObj == null) {
        return;
    }

    // Format and display the JSON response.
    celebritiesResponseTextArea.setText(jsonObj.toString(2));

    // Extract the text and confidence from the first caption in the description object.
    if (jsonObj.has("result") && jsonObj.getJSONObject("result").has("celebrities")) {

        JSONObject jsonCaption = jsonObj.getJSONObject("result").getJSONArray("celebrities").getJSONObject(0);

        if (jsonCaption.has("name") && jsonCaption.has("confidence")) {

            celebritiesCaptionLabel.setText("Caption: " + jsonCaption.getString("name") + 
                    " (confidence: " + jsonCaption.getDouble("confidence") + ").");
        }
    }
}

유명인사 단계 2: REST API 호출 래퍼 추가하기

CelebritiesImage 메서드는 이미지를 분석하는 REST API 호출을 래핑합니다. 이 메서드는 유명인사를 설명하는 JSONObject를 반환하거나, 오류가 발생할 경우 null을 반환합니다.

다음 CelebritiesImage 메서드를 복사해서 celebritiesImageButtonActionPerformed 메서드 바로 아래에 붙여 넣습니다.

/**
 * Encapsulates the Microsoft Cognitive Services REST API call to identify celebrities in an image.
 * @param imageUrl: The string URL of the image to process.
 * @return: A JSONObject describing the image, or null if a runtime error occurs.
 */
private JSONObject CelebritiesImage(String imageUrl) {
    try (CloseableHttpClient httpclient = HttpClientBuilder.create().build())
    {
        // Create the URI to access the REST API call to identify celebrities in an image.
        String uriString = uriBasePreRegion + 
                String.valueOf(subscriptionRegionComboBox.getSelectedItem()) + 
                uriBasePostRegion + uriBaseCelebrities;
        URIBuilder builder = new URIBuilder(uriString);

        // Request parameters. All of them are optional.
        builder.setParameter("visualFeatures", "Categories,Description,Color");
        builder.setParameter("language", "en");

        // Prepare the URI for the REST API call.
        URI uri = builder.build();
        HttpPost request = new HttpPost(uri);

        // Request headers.
        request.setHeader("Content-Type", "application/json");
        request.setHeader("Ocp-Apim-Subscription-Key", subscriptionKeyTextField.getText());

        // Request body.
        StringEntity reqEntity = new StringEntity("{\"url\":\"" + imageUrl + "\"}");
        request.setEntity(reqEntity);

        // Execute the REST API call and get the response entity.
        HttpResponse response = httpclient.execute(request);
        HttpEntity entity = response.getEntity();

        // If we got a response, parse it and display it.
        if (entity != null) {
            // Return the JSONObject.
            String jsonString = EntityUtils.toString(entity);
            return new JSONObject(jsonString);
        } else {
            // No response. Return null.
            return null;
        }
    }
    catch (Exception e)
    {
        // Display error message.
        System.out.println(e.getMessage());
        return null;
    }
}

유명인사 단계 3: 응용 프로그램 실행하기

F6 키를 눌러서 응용 프로그램을 실행합니다. Subscription Key 필드에는 구독 키를 입력하고, Subscription Region 필드가 올바른 지역을 선택하고 있는지 확인합니다. Celebrities 탭을 클릭하고 분석하고자 하는 이미지의 URL을 입력한 다음, Analyze Image 버튼을 클릭해서 이미지를 분석하고 그 결과를 확인합니다.

지능적으로 썸네일 생성하기

Computer Vision의 썸네일 기능은 이미지의 썸네일을 생성합니다. 또한 Smart Crop 기능을 사용해서 이미지의 관심 영역을 식별하고 이 영역을 썸네일의 중앙에 배치함으로써 더 보기 좋은 썸네일을 생성할 수도 있습니다.

자습서 응용 프로그램의 썸네일 기능을 구현하려면, 다음의 단계들을 수행합니다:

썸네일 단계 1: 폼 버튼에 대한 이벤트 처리기 추가하기

thumbnailImageButtonActionPerformed 이벤트 처리기 메서드는 폼을 초기화하고, URL로 지정한 이미지를 출력한 다음, 썸네일을 생성하기 위한 getThumbnailImage 메서드를 호출합니다. getThumbnailImage 메서드가 결과를 반환하면 생성된 썸네일을 출력합니다.

다음 코드를 thumbnailImageButtonActionPerformed 메서드에 복사해서 붙여 넣습니다.

노트

NetBeans에서는 메서드를 정의하는 줄이나 (private void) 메서드를 닫는 중괄호는 편집할 수 없습니다. 코드를 복사하려면, 메서드 정의와 닫는 중괄호 사이의 코드만 복사해서 메서드 본문에 붙여 넣습니다.

private void thumbnailImageButtonActionPerformed(java.awt.event.ActionEvent evt) {
    URL thumbnailImageUrl;
    JSONObject jsonError[] = new JSONObject[1];

    // Clear out the previous image, response, and thumbnail, if any.
    thumbnailSourceImage.setIcon(new ImageIcon());
    thumbnailResponseTextArea.setText("");
    thumbnailImage.setIcon(new ImageIcon());

    // Display the image specified in the text box.
    try {
        thumbnailImageUrl = new URL(thumbnailImageUriTextBox.getText());
        BufferedImage bImage = ImageIO.read(thumbnailImageUrl);
        scaleAndShowImage(bImage, thumbnailSourceImage);
    } catch(IOException e) {
        thumbnailResponseTextArea.setText("Error loading image to thumbnail: " + e.getMessage());
        return;
    }

    // Get the thumbnail for the image.
    BufferedImage thumbnail = getThumbnailImage(thumbnailImageUrl.toString(), jsonError);

    // A non-null value indicates error.
    if (jsonError[0] != null) {
        // Format and display the JSON error.
        thumbnailResponseTextArea.setText(jsonError[0].toString(2));
        return;
    }

    // Display the thumbnail.
    if (thumbnail != null) {
        scaleAndShowImage(thumbnail, thumbnailImage);
    }
}

썸네일 단계 2: REST API 호출 래퍼 추가하기

getThumbnailImage 메서드는 썸네일을 생성하는 REST API 호출을 래핑합니다. 이 메서드는 썸네일을 담고 있는 BufferedImage를 반환하거나, 오류가 발생할 경우 null을 반환합니다. 그 경우, 오류 메시지는 jsonError 문자열 배열의 첫 번째 요소에 담겨서 반환됩니다.

다음 getThumbnailImage 메서드를 복사해서 thumbnailImageButtonActionPerformed 메서드 바로 아래에 붙여 넣습니다.

/**
 * Encapsulates the Microsoft Cognitive Services REST API call to create a thumbnail for an image.
 * @param imageUrl: The string URL of the image to process.
 * @return: A BufferedImage containing the thumbnail, or null if a runtime error occurs. In the case
 * of an error, the error message will be returned in the first element of the jsonError string array.
 */
private BufferedImage getThumbnailImage(String imageUrl, JSONObject[] jsonError) {
    try (CloseableHttpClient httpclient = HttpClientBuilder.create().build())
    {
        // Create the URI to access the REST API call to identify celebrities in an image.
        String uriString = uriBasePreRegion + 
                String.valueOf(subscriptionRegionComboBox.getSelectedItem()) + 
                uriBasePostRegion + uriBaseThumbnail;
        URIBuilder uriBuilder = new URIBuilder(uriString);

        // Request parameters.
        uriBuilder.setParameter("width", "100");
        uriBuilder.setParameter("height", "150");
        uriBuilder.setParameter("smartCropping", "true");

        // Prepare the URI for the REST API call.
        URI uri = uriBuilder.build();
        HttpPost request = new HttpPost(uri);

        // Request headers.
        request.setHeader("Content-Type", "application/json");
        request.setHeader("Ocp-Apim-Subscription-Key", subscriptionKeyTextField.getText());

        // Request body.
        StringEntity requestEntity = new StringEntity("{\"url\":\"" + imageUrl + "\"}");
        request.setEntity(requestEntity);

        // Execute the REST API call and get the response entity.
        HttpResponse response = httpclient.execute(request);
        HttpEntity entity = response.getEntity();

        // Check for success.
        if (response.getStatusLine().getStatusCode() == 200)
        {
            // Return the thumbnail.
            return ImageIO.read(entity.getContent());
        }
        else
        {
            // Format and display the JSON error message.
            String jsonString = EntityUtils.toString(entity);
            jsonError[0] = new JSONObject(jsonString);
            return null;
        }
    }
    catch (Exception e)
    {
        String errorMessage = e.getMessage();
        System.out.println(errorMessage);
        jsonError[0] = new JSONObject(errorMessage);
        return null;
    }
}

썸네일 단계 3: 응용 프로그램 실행하기

F6 키를 눌러서 응용 프로그램을 실행합니다. Subscription Key 필드에는 구독 키를 입력하고, Subscription Region 필드가 올바른 지역을 선택하고 있는지 확인합니다. Thumbnail 탭을 클릭하고 이미지의 URL을 입력한 다음, Generate Thumbnail 버튼을 클릭해서 썸네일을 얻고 그 결과를 확인합니다.

인쇄된 텍스트 읽기 (OCR)

Computer Vision의 광학 문자 인식 (OCR, Optical Character Recognition) 기능은 이미지에 포함된 인쇄된 텍스트를 분석합니다. 그리고 처리가 완료되면 이미지에서 발견한 텍스트와 해당 텍스트의 이미지 상의 좌표가 담긴 JSON 개체를 반환합니다.

자습서 응용 프로그램의 광학 문자 인식 기능을 구현하려면, 다음의 단계들을 수행합니다:

OCR 단계 1: 폼 버튼에 대한 이벤트 처리기 추가하기

ocrImageButtonActionPerformed 이벤트 처리기 메서드는 폼을 초기화하고, URL로 지정한 이미지를 출력한 다음, 이미지를 분석하기 위한 OcrImage 메서드를 호출합니다. OcrImage 메서드가 결과를 반환하면, 감지된 텍스트들을 정리된 JSON 응답으로 Response 텍스트 영역에 출력합니다.

다음 코드를 ocrImageButtonActionPerformed 메서드에 복사해서 붙여 넣습니다.

노트

NetBeans에서는 메서드를 정의하는 줄이나 (private void) 메서드를 닫는 중괄호는 편집할 수 없습니다. 코드를 복사하려면, 메서드 정의와 닫는 중괄호 사이의 코드만 복사해서 메서드 본문에 붙여 넣습니다.

private void ocrImageButtonActionPerformed(java.awt.event.ActionEvent evt) {
    URL ocrImageUrl;

    // Clear out the previous image, response, and caption, if any.
    ocrImage.setIcon(new ImageIcon());
    ocrResponseTextArea.setText("");

    // Display the image specified in the text box.
    try {
        ocrImageUrl = new URL(ocrImageUriTextBox.getText());
        BufferedImage bImage = ImageIO.read(ocrImageUrl);
        scaleAndShowImage(bImage, ocrImage);
    } catch(IOException e) {
        ocrResponseTextArea.setText("Error loading OCR image: " + e.getMessage());
        return;
    }

    // Read the text in the image.
    JSONObject jsonObj = OcrImage(ocrImageUrl.toString());

    // A return of null indicates failure.
    if (jsonObj == null) {
        return;
    }

    // Format and display the JSON response.
    ocrResponseTextArea.setText(jsonObj.toString(2));
}

OCR 단계 2: REST API 호출 래퍼 추가하기

OcrImage 메서드는 이미지를 분석하는 REST API 호출을 래핑합니다. 이 메서드는 호출에서 반환된 JSONObject를 반환하거나, 오류가 발생할 경우 null을 반환합니다.

다음 OcrImage 메서드를 복사해서 ocrImageButtonActionPerformed 메서드 바로 아래에 붙여 넣습니다.

/**
 * Encapsulates the Microsoft Cognitive Services REST API call to read text in an image.
 * @param imageUrl: The string URL of the image to process.
 * @return: A JSONObject describing the image, or null if a runtime error occurs.
 */
private JSONObject OcrImage(String imageUrl) {
    try (CloseableHttpClient httpclient = HttpClientBuilder.create().build())
    {
        // Create the URI to access the REST API call to read text in an image.
        String uriString = uriBasePreRegion + 
                String.valueOf(subscriptionRegionComboBox.getSelectedItem()) + 
                uriBasePostRegion + uriBaseOcr;
        URIBuilder uriBuilder = new URIBuilder(uriString);

        // Request parameters.
        uriBuilder.setParameter("language", "unk");
        uriBuilder.setParameter("detectOrientation ", "true");

        // Prepare the URI for the REST API call.
        URI uri = uriBuilder.build();
        HttpPost request = new HttpPost(uri);

        // Request headers.
        request.setHeader("Content-Type", "application/json");
        request.setHeader("Ocp-Apim-Subscription-Key", subscriptionKeyTextField.getText());

        // Request body.
        StringEntity reqEntity = new StringEntity("{\"url\":\"" + imageUrl + "\"}");
        request.setEntity(reqEntity);

        // Execute the REST API call and get the response entity.
        HttpResponse response = httpclient.execute(request);
        HttpEntity entity = response.getEntity();

        // If we got a response, parse it and display it.
        if (entity != null)
        {
            // Return the JSONObject.
            String jsonString = EntityUtils.toString(entity);
            return new JSONObject(jsonString);
        } else {
            // No response. Return null.
            return null;
        }
    }
    catch (Exception e)
    {
        // Display error message.
        System.out.println(e.getMessage());
        return null;
    }
}

OCR 단계 3: 응용 프로그램 실행하기

F6 키를 눌러서 응용 프로그램을 실행합니다. Subscription Key 필드에는 구독 키를 입력하고, Subscription Region 필드가 올바른 지역을 선택하고 있는지 확인합니다. OCR 탭을 클릭하고 인쇄된 텍스트 이미지의 URL을 입력한 다음, Read Image 버튼을 클릭해서 이미지를 분석하고 그 결과를 확인합니다.

필기체 텍스트 읽기 (필기 인식하기)

Computer Vision의 필기체 인식 기능은 이미지에 포함된 필기체 텍스트를 분석합니다. 그리고 처리가 완료되면 이미지에서 발견한 텍스트와 해당 텍스트의 이미지 상의 좌표가 담긴 JSON 개체를 반환합니다.

자습서 응용 프로그램의 필기체 인식 기능을 구현하려면, 다음의 단계들을 수행합니다:

역주

현재 필기체 인식 기능은 영어만 지원됩니다.

필기체 인식 단계 1: 폼 버튼에 대한 이벤트 처리기 추가하기

handwritingImageButtonActionPerformed 이벤트 처리기 메서드는 폼을 초기화하고, URL로 지정한 이미지를 출력한 다음, 이미지를 분석하기 위한 HandwritingImage 메서드를 호출합니다. HandwritingImage 메서드가 결과를 반환하면, 감지된 텍스트들을 정리된 JSON 응답으로 Response 텍스트 영역에 출력합니다.

다음 코드를 handwritingImageButtonActionPerformed 메서드에 복사해서 붙여 넣습니다.

노트

NetBeans에서는 메서드를 정의하는 줄이나 (private void) 메서드를 닫는 중괄호는 편집할 수 없습니다. 코드를 복사하려면, 메서드 정의와 닫는 중괄호 사이의 코드만 복사해서 메서드 본문에 붙여 넣습니다.

private void handwritingImageButtonActionPerformed(java.awt.event.ActionEvent evt) {
    URL handwritingImageUrl;

    // Clear out the previous image, response, and caption, if any.
    handwritingImage.setIcon(new ImageIcon());
    handwritingResponseTextArea.setText("");

    // Display the image specified in the text box.
    try {
        handwritingImageUrl = new URL(handwritingImageUriTextBox.getText());
        BufferedImage bImage = ImageIO.read(handwritingImageUrl);
        scaleAndShowImage(bImage, handwritingImage);
    } catch(IOException e) {
        handwritingResponseTextArea.setText("Error loading Handwriting image: " + e.getMessage());
        return;
    }

    // Read the text in the image.
    JSONObject jsonObj = HandwritingImage(handwritingImageUrl.toString());

    // A return of null indicates failure.
    if (jsonObj == null) {
        return;
    }

    // Format and display the JSON response.
    handwritingResponseTextArea.setText(jsonObj.toString(2));
}

필기체 인식 단계 2: REST API 호출 래퍼 추가하기

HandwritingImage 메서드는 이미지를 분석하는 REST API 호출을 래핑합니다. 필기체 인식은 다소 시간이 소요되는 처리이기 때문에, 처리 과정이 두 단계로 나눠집니다. 먼저 첫 번째 호출은 분석할 이미지를 제출하고, 이어지는 두 번째 호출은 처리가 끝나면 감지된 텍스트를 받아옵니다.

HandwritingImage 메서드는 텍스트를 가져온 다음, 텍스트 및 해당 텍스트의 위치를 설명하는 JSONObject를 반환하거나, 오류가 발생할 경우 null을 반환합니다.

다음 HandwritingImage 메서드를 복사해서 handwritingImageButtonActionPerformed 메서드 바로 아래에 붙여 넣습니다.

/**
 * Encapsulates the Microsoft Cognitive Services REST API call to read handwritten text in an image.
 * @param imageUrl: The string URL of the image to process.
 * @return: A JSONObject describing the image, or null if a runtime error occurs.
 */
private JSONObject HandwritingImage(String imageUrl) {
    try (CloseableHttpClient textClient = HttpClientBuilder.create().build();
            CloseableHttpClient resultClient = HttpClientBuilder.create().build())
    {
        // Create the URI to access the REST API call to read text in an image.
        String uriString = uriBasePreRegion + 
                String.valueOf(subscriptionRegionComboBox.getSelectedItem()) + 
                uriBasePostRegion + uriBaseHandwriting;
        URIBuilder uriBuilder = new URIBuilder(uriString);

        // Request parameters.
        uriBuilder.setParameter("handwriting", "true");

        // Prepare the URI for the REST API call.
        URI uri = uriBuilder.build();
        HttpPost request = new HttpPost(uri);

        // Request headers.
        request.setHeader("Content-Type", "application/json");
        request.setHeader("Ocp-Apim-Subscription-Key", subscriptionKeyTextField.getText());

        // Request body.
        StringEntity reqEntity = new StringEntity("{\"url\":\"" + imageUrl + "\"}");
        request.setEntity(reqEntity);

        // Execute the REST API call and get the response.
        HttpResponse textResponse = textClient.execute(request);

        // Check for success.
        if (textResponse.getStatusLine().getStatusCode() != 202) {
            // An error occured. Return the JSON error message.
            HttpEntity entity = textResponse.getEntity();
            String jsonString = EntityUtils.toString(entity);
            return new JSONObject(jsonString);
        }

        String operationLocation = null;

        // The 'Operation-Location' in the response contains the URI to retrieve the recognized text.
        Header[] responseHeaders = textResponse.getAllHeaders();
        for(Header header : responseHeaders) {
            if(header.getName().equals("Operation-Location"))
            {
                // This string is the URI where you can get the text recognition operation result.
                operationLocation = header.getValue();
                break;
            }
        }

        // NOTE: The response may not be immediately available. Handwriting recognition is an
        // async operation that can take a variable amount of time depending on the length
        // of the text you want to recognize. You may need to wait or retry this operation.
        //
        // This example checks once per second for ten seconds.

        JSONObject responseObj = null;
        int i = 0;
        do {
            // Wait one second.
            Thread.sleep(1000);

            // Check to see if the operation completed.
            HttpGet resultRequest = new HttpGet(operationLocation);
            resultRequest.setHeader("Ocp-Apim-Subscription-Key", subscriptionKeyTextField.getText());
            HttpResponse resultResponse = resultClient.execute(resultRequest);
            HttpEntity responseEntity = resultResponse.getEntity();
            if (responseEntity != null)
            {
                // Get the JSON response.
                String jsonString = EntityUtils.toString(responseEntity);
                responseObj = new JSONObject(jsonString);
            }
        }
        while (i < 10 && responseObj != null &&
                !responseObj.getString("status").equalsIgnoreCase("Succeeded"));

        // If the operation completed, return the JSON object.
        if (responseObj != null) {
            return responseObj;
        } else {
            // Return null for timeout error.
            System.out.println("Timeout error.");
            return null;
        }
    }
    catch (Exception e)
    {
        // Display error message.
        System.out.println(e.getMessage());
        return null;
    }
}

필기체 인식 단계 3: 응용 프로그램 실행하기

F6 키를 눌러서 응용 프로그램을 실행합니다. Subscription Key 필드에는 구독 키를 입력하고, Subscription Region 필드가 올바른 지역을 선택하고 있는지 확인합니다. Read Handwritten Text 탭을 클릭하고 필기체 텍스트 이미지의 URL을 입력한 다음, Read Image 버튼을 클릭해서 이미지를 분석하고 그 결과를 확인합니다.

관련 자료