HoloLens(1세대) 및 Azure 302: Computer Vision


참고

Mixed Reality 아카데미 자습서는 HoloLens(1세대) 및 Mixed Reality 몰입형 헤드셋을 염두에 두고 설계되었습니다. 따라서 이러한 디바이스 개발에 대한 지침을 계속 찾고 있는 개발자를 위해 이러한 자습서를 그대로 두는 것이 중요합니다. 이러한 자습서는 HoloLens 2에 사용되는 최신 도구 집합 또는 상호 작용으로 업데이트되지 않습니다. 대신 지원되는 디바이스에서 계속 작동하도록 유지 관리됩니다. HoloLens 2 위해 개발하는 방법을 보여 줄 새로운 자습서 시리즈가 미래에 게시 될 예정입니다. 이 알림은 해당 자습서가 게시될 때 해당 자습서에 대한 링크로 업데이트됩니다.


이 과정에서는 혼합 현실 애플리케이션에서 Azure Computer Vision 기능을 사용하여 제공된 이미지 내에서 시각적 콘텐츠를 인식하는 방법을 알아봅니다.

인식 결과는 설명 태그로 표시됩니다. 기계 학습 모델을 학습시킬 필요 없이 이 서비스를 사용할 수 있습니다. 구현에 기계 학습 모델을 학습해야 하는 경우 MR 및 Azure 302b를 참조하세요.

랩 결과

Microsoft Computer Vision 클라우드의 고급 알고리즘을 사용하여 개발자에게 이미지 처리 및 분석(반환 정보 포함)을 제공하도록 설계된 API 집합입니다. 개발자는 이미지 또는 이미지 URL을 업로드하고 Microsoft Computer Vision API 알고리즘은 사용자가 선택한 입력에 따라 시각적 콘텐츠를 분석합니다. 그러면 이미지의 유형 및 품질 식별, 사람의 얼굴 감지(좌표 반환), 이미지 태그 지정 또는 분류 등의 정보를 반환할 수 있습니다. 자세한 내용은 Azure Computer Vision API 페이지를 참조하세요.

이 과정을 완료하면 다음을 수행할 수 있는 혼합 현실 HoloLens 애플리케이션이 있습니다.

  1. 탭 제스처를 사용하여 HoloLens의 카메라는 이미지를 캡처합니다.
  2. 이미지는 Azure Computer Vision API Service로 전송됩니다.
  3. 인식된 개체는 Unity 장면에 배치된 간단한 UI 그룹에 나열됩니다.

애플리케이션에서 결과를 디자인과 통합하는 방법은 사용자에게 달려 있습니다. 이 과정은 Azure 서비스를 Unity 프로젝트와 통합하는 방법을 가르치기 위해 고안되었습니다. 혼합 현실 애플리케이션을 향상시키기 위해 이 과정에서 얻은 지식을 사용하는 것이 당신의 일입니다.

디바이스 지원

과정 HoloLens 몰입형 헤드셋
MR 및 Azure 302: Computer Vision ✔️ ✔️

참고

이 과정은 주로 HoloLens에 중점을 두지만, 이 과정에서 배운 내용을 몰입형(VR) 헤드셋에 Windows Mixed Reality 적용할 수도 있습니다. 몰입형(VR) 헤드셋에는 액세스할 수 있는 카메라가 없으므로 PC에 연결된 외부 카메라가 필요합니다. 과정을 따라가면서 몰입형(VR) 헤드셋을 지원하기 위해 사용해야 할 수 있는 변경 사항에 대한 메모가 표시됩니다.

사전 요구 사항

참고

이 자습서는 Unity 및 C#에 대한 기본 경험이 있는 개발자를 위해 설계되었습니다. 또한 이 문서의 필수 구성 요소와 서면 지침은 작성 당시 테스트 및 확인된 내용을 나타냅니다(2018년 5월). 이 과정의 정보가 아래에 나열된 것보다 최신 소프트웨어에서 찾을 수 있는 것과 완벽하게 일치한다고 가정해서는 안 되지만 , 도구 설치 문서에 나열된 대로 최신 소프트웨어를 자유롭게 사용할 수 있습니다.

이 과정에서는 다음 하드웨어 및 소프트웨어를 사용하는 것이 좋습니다.

시작하기 전에

  1. 이 프로젝트를 빌드하는 데 문제가 발생하지 않도록 하려면 이 자습서에 언급된 프로젝트를 루트 또는 루트에 가까운 폴더에 만드는 것이 좋습니다(긴 폴더 경로는 빌드 시 문제를 일으킬 수 있습니다).
  2. HoloLens를 설정하고 테스트합니다. HoloLens 설정을 지원해야 하는 경우 HoloLens 설정 문서를 참조하세요.
  3. 새 HoloLens 앱 개발을 시작할 때 보정 및 센서 튜닝을 수행하는 것이 좋습니다(때로는 각 사용자에 대해 이러한 작업을 수행하는 데 도움이 될 수 있음).

보정에 대한 도움말은 HoloLens 보정 문서에 대한 링크를 따르세요.

센서 튜닝에 대한 도움말은 HoloLens 센서 튜닝 문서에 대한 링크를 따르세요.

챕터 1 – Azure Portal

Azure에서 Computer Vision API 서비스를 사용하려면 애플리케이션에서 사용할 수 있도록 서비스의 instance 구성해야 합니다.

  1. 먼저 Azure Portal에 로그인합니다.

    참고

    Azure 계정이 아직 없는 경우 계정을 만들어야 합니다. 교실 또는 랩 상황에서 이 자습서를 따르는 경우 강사 또는 감독관 중 한 명에게 새 계정 설정에 대한 도움을 요청하세요.

  2. 로그인한 후 왼쪽 위 모서리에서 새로 만들기를 클릭하고 Computer Vision API를 검색하고 Enter 키를 클릭합니다.

    Azure에서 새 리소스 만들기

    참고

    단어는 최신 포털에서 리소스 만들기로 대체되었을 수 있습니다.

  3. 새 페이지에서는 Computer Vision API 서비스에 대한 설명을 제공합니다. 이 페이지의 왼쪽 아래에서 만들기 단추를 선택하여 이 서비스와의 연결을 만듭니다.

    Computer Vision api 서비스 정보

  4. 만들기를 클릭한 후에는 다음을 수행합니다.

    1. 이 서비스 instance 원하는 이름을 삽입합니다.

    2. 구독을 선택합니다.

    3. 적절한 가격 책정 계층을 선택합니다. Computer Vision API 서비스를 처음 만드는 경우 무료 계층(F0이라는 이름)을 사용할 수 있어야 합니다.

    4. 리소스 그룹을 선택하거나 새 리소스 그룹을 만듭니다. 리소스 그룹은 Azure 자산 컬렉션에 대한 액세스를 모니터링, 제어, 프로비전 및 관리하는 방법을 제공합니다. 단일 프로젝트(예: 이러한 랩)와 연결된 모든 Azure 서비스를 공통 리소스 그룹 아래에 유지하는 것이 좋습니다.

      Azure 리소스 그룹에 대해 자세히 알아보려면 리소스 그룹 문서를 참조하세요.

    5. 리소스 그룹의 위치를 결정합니다(새 리소스 그룹을 만드는 경우). 위치는 애플리케이션이 실행되는 지역에 있는 것이 가장 좋습니다. 일부 Azure 자산은 특정 지역에서만 사용할 수 있습니다.

    6. 또한 이 서비스에 적용된 사용 약관을 이해했음을 확인해야 합니다.

    7. 만들기를 클릭합니다.

      서비스 만들기 정보

  5. 만들기를 클릭하면 서비스가 만들어질 때까지 기다려야 합니다. 이 작업은 1분 정도 걸릴 수 있습니다.

  6. 서비스 instance 만들어지면 포털에 알림이 표시됩니다.

    새 서비스에 대한 새 알림 보기

  7. 알림을 클릭하여 새 서비스 instance 탐색합니다.

    리소스로 이동 단추를 선택합니다.

  8. 알림에서 리소스로 이동 단추를 클릭하여 새 서비스 instance 탐색합니다. 새 Computer Vision API 서비스 instance 이동합니다.

    새 Computer Vision API 서비스 이미지

  9. 이 자습서 내에서 애플리케이션은 서비스의 구독 키를 사용하여 수행되는 서비스를 호출해야 합니다.

  10. 빠른 시작 페이지의 Computer Vision API 서비스에서 첫 번째 단계인 키 가져오기로 이동하고 키를 클릭합니다(키 아이콘으로 표시된 서비스 탐색 메뉴에 있는 파란색 하이퍼링크 키를 클릭하여 이 작업을 수행할 수도 있음). 그러면 서비스 키가 표시됩니다.

  11. 나중에 프로젝트에서 필요하므로 표시된 키 중 하나의 복사본을 가져옵니다.

  12. 빠른 시작 페이지로 돌아가기 엔드포인트를 가져옵니다. 사용자의 지역에 따라 다를 수 있습니다(있는 경우 나중에 코드를 변경해야 합니다). 나중에 사용할 이 엔드포인트의 복사본을 가져옵니다.

    새 Computer Vision API 서비스

    다양한 엔드포인트가 무엇인지 검사 수 있습니다.

2장 - Unity 프로젝트 설정

다음은 혼합 현실로 개발하기 위한 일반적인 설정이며, 따라서 다른 프로젝트에 적합한 템플릿입니다.

  1. Unity를 열고 새로 만들기를 클릭합니다.

    새 Unity 프로젝트를 시작합니다.

  2. 이제 Unity 프로젝트 이름을 제공해야 합니다. MR_ComputerVision 삽입합니다. 프로젝트 형식이 3D로 설정되어 있는지 확인합니다. 위치를 적절한 위치로 설정합니다(루트 디렉터리에 더 가까울수록 좋습니다). 그런 다음 프로젝트 만들기를 클릭합니다.

    새 Unity 프로젝트에 대한 세부 정보를 제공합니다.

  3. Unity가 열려 있는 경우 기본 스크립트 편집 기가 Visual Studio로 설정되어 있는지 확인하는 것이 좋습니다. 기본 설정 편집 > 으로 이동한 다음 새 창에서 외부 도구로 이동합니다. 외부 스크립트 편집기를 Visual Studio 2017로 변경합니다. 기본 설정 창을 닫습니다.

    스크립트 편집기 기본 설정을 업데이트합니다.

  4. 다음으로 파일 > 빌드 설정으로 이동하여 유니버설 Windows 플랫폼 선택한 다음 플랫폼 전환 단추를 클릭하여 선택 항목을 적용합니다.

    빌드 설정 창에서 플랫폼을 UWP로 전환합니다.

  5. 파일 > 빌드 설정에 있는 동안 다음을 확인합니다.

    1. 대상 디바이스HoloLens로 설정됩니다.

      몰입형 헤드셋의 경우 대상 디바이스모든 디바이스로 설정합니다.

    2. 빌드 유형D3D로 설정됨

    3. SDK최신 설치됨으로 설정됨

    4. Visual Studio 버전설치된 최신 버전으로 설정됨

    5. 빌드 및 실행로컬 컴퓨터로 설정됩니다.

    6. 장면을 저장하고 빌드에 추가합니다.

      1. 열린 장면 추가를 선택하여 이 작업을 수행합니다. 저장 창이 나타납니다.

        열린 장면 추가 단추를 클릭합니다.

      2. 이에 대한 새 폴더와 이후의 장면을 만든 다음 새 폴더 단추를 선택하여 새 폴더 를 만들고 이름을 Scenes로 지정 합니다.

        새 스크립트 폴더 만들기

      3. 새로 만든 Scenes 폴더를 연 다음 파일 이름: 텍스트 필드에 MR_ComputerVisionScene 입력한 다음 저장을 클릭합니다.

        새 장면에 이름을 지정합니다.

        Unity 장면이 Unity 프로젝트와 연결되어야 하므로 Assets 폴더 내에 Unity 장면을 저장해야 합니다. scenes 폴더(및 기타 유사한 폴더)를 만드는 것은 Unity 프로젝트를 구성하는 일반적인 방법입니다.

    7. 빌드 설정의 나머지 설정은 현재 기본값으로 남아 있어야 합니다.

  6. 빌드 설정 창에서 플레이어 설정 단추를 클릭하면 Inspector가 있는 공간에서 관련 패널이 열립니다.

    플레이어 설정을 엽니다.

  7. 이 패널에서 몇 가지 설정을 확인해야 합니다.

    1. 기타 설정 탭에서 다음을 수행합니다.

      1. 런타임 버전 스크립팅안정적 이어야 합니다(.NET 3.5 등가).

      2. 백 엔드 스크립팅.NET이어야 합니다.

      3. API 호환성 수준은.NET 4.6이어야 합니다.

        다른 설정을 업데이트합니다.

    2. 게시 설정 탭의 기능에서 다음을 검사.

      1. InternetClient

      2. 웹캠

        게시 설정을 업데이트합니다.

    3. 패널 아래로 XR 설정(게시 설정 아래에 있음)에서 Virtual Reality 지원됨을 체크하고 Windows Mixed Reality SDK가 추가되었는지 확인합니다.

      X R 설정을 업데이트합니다.

  8. 빌드 설정으로 돌아가면 Unity C# 프로젝트가 더 이상 회색으로 표시되지 않습니다. 이 옆에 있는 확인란을 선택합니다.

  9. 빌드 설정 창을 닫습니다.

  10. 장면 및 프로젝트 저장(FILE > SAVE SCENE / FILE > SAVE PROJECT).

챕터 3 – 기본 카메라 설정

중요

이 과정의 Unity 설정 구성 요소를 건너뛰고 코드를 계속 진행하려면 이 .unitypackage를 자유롭게 다운로드하고 사용자 지정 패키지로 프로젝트로 가져온 다음 챕터 5에서 계속 진행하세요.

  1. 계층 구조 패널에서 기본 카메라를 선택합니다.

  2. 선택하면 검사기 패널에서 주 카메라의 모든 구성 요소를 볼 수 있습니다.

    1. Camera 개체의 이름은 Main Camera여야 합니다(맞춤법 유의하세요!)

    2. Main Camera 태그MainCamera (맞춤법 유의)로 설정해야 합니다.

    3. 변환 위치0, 0, 0으로 설정되어 있는지 확인합니다.

    4. 플래그 지우기를 단색으로 설정합니다(몰입형 헤드셋의 경우 무시).

    5. 카메라 구성 요소의 배경 색을 검은색, 알파 0(16진수 코드: #00000000) 으로 설정합니다(몰입형 헤드셋의 경우 무시).

      카메라 구성 요소를 업데이트합니다.

  3. 다음으로, 기본 카메라에 연결된 간단한 "Cursor" 개체를 만들어야 합니다. 그러면 애플리케이션이 실행될 때 이미지 분석 출력의 위치를 지정하는 데 도움이 됩니다. 이 커서는 카메라 포커스의 중심점을 결정합니다.

커서를 만들려면 다음을 수행합니다.

  1. 계층 구조 패널에서 주 카메라를 마우스 오른쪽 단추로 클릭합니다. 3D 개체에서 Sphere를 클릭합니다.

    커서 개체를 선택합니다.

  2. Sphere 이름을 커서로 바꾸고(커서 개체를 두 번 클릭하거나 개체가 선택된 상태에서 'F2' 키보드 단추를 누릅니다.) 기본 카메라의 자식으로 있는지 확인합니다.

  3. 계층 패널에서 커서를 마우스 왼쪽 단추로 클릭합니다. 커서를 선택한 상태에서 검사기 패널에서 다음 변수를 조정합니다.

    1. 변환 위치를0, 0, 5로 설정

    2. 크기 조정0.02, 0.02, 0.02로 설정합니다.

      변환 위치 및 크기 조정을 업데이트합니다.

4장 - 레이블 시스템 설정

HoloLens 카메라로 이미지를 캡처하면 해당 이미지가 분석을 위해 Azure Computer Vision API 서비스 instance 전송됩니다.

해당 분석 결과는 Tags라는 인식된 개체의 목록이 됩니다.

레이블(세계 공간의 3D 텍스트)을 사용하여 사진을 찍은 위치에 이러한 태그를 표시합니다.

다음 단계에서는 Label 개체를 설정하는 방법을 보여줍니다.

  1. 계층 패널의 아무 곳이나 마우스 오른쪽 단추로 클릭하고(현재 위치는 중요하지 않음) 3D 개체에서 3D 텍스트를 추가합니다. 이름을 LabelText로 지정합니다.

    3D Text 개체를 만듭니다.

  2. 계층 패널에서 LabelText를 마우스 왼쪽 단추로 클릭합니다. LabelText를 선택한 상태에서 검사기 패널에서 다음 변수를 조정합니다.

    1. 위치를0,0,0으로 설정합니다.
    2. 크기 조정0.01, 0.01, 0.01로 설정합니다.
    3. 구성 요소 에서 텍스트 메시:
    4. 텍스트 내의 모든 텍스트를 "..."로 바꿉니다.
    5. 앵커중간 센터로 설정
    6. 맞춤가운데로 설정
    7. 탭 크기를4로 설정
    8. 글꼴 크기를50으로 설정
    9. #FFFFFFFF

    텍스트 구성 요소

  3. 계층 구조 패널LabelText프로젝트 패널 내의 자산 폴더로 끌어옵니다. 이렇게 하면 LabelText 를 Prefab으로 만들어 코드에서 인스턴스화할 수 있습니다.

    LabelText 개체의 프리팹을 만듭니다.

  4. 열기 장면에 표시되지 않도록 계층 패널에서 LabelText를 삭제해야 합니다. 이제 Assets 폴더의 개별 인스턴스에 대해 를 호출하는 프리팹이므로 장면 내에 유지할 필요가 없습니다.

  5. 계층 구조 패널의 최종 개체 구조는 아래 이미지에 표시된 구조와 같아야 합니다.

    계층 구조 패널의 최종 구조입니다.

5장 – ResultsLabel 클래스 만들기

만들어야 하는 첫 번째 스크립트는 ResultsLabel 클래스이며, 이 클래스는 다음을 담당합니다.

  • 카메라의 위치를 기준으로 적절한 월드 공간에서 레이블을 만듭니다.
  • 이미지 Anaysis의 태그 표시

이 클래스를 만들려면 다음을 수행합니다.

  1. 프로젝트 패널을 마우스 오른쪽 단추로 클릭한 다음 폴더 만들기>를 클릭합니다. 폴더 이름을 스크립트로 지정합니다.

    스크립트 폴더를 만듭니다.

  2. Scripts 폴더 만들기를 사용하여 두 번 클릭하여 엽니다. 그런 다음 해당 폴더 내에서 마우스 오른쪽 단추를 클릭하고 만들기 > 를 선택한 다음 C# 스크립트를 선택합니다. 스크립트 이름을 ResultsLabel로 지정합니다.

  3. ResultsLabel 스크립트를 두 번 클릭하여 Visual Studio에서 엽니다.

  4. 클래스 내에서 ResultsLabel 클래스에 다음 코드를 삽입합니다.

        using System.Collections.Generic;
        using UnityEngine;
    
        public class ResultsLabel : MonoBehaviour
        {	
            public static ResultsLabel instance;
    
            public GameObject cursor;
    
            public Transform labelPrefab;
    
            [HideInInspector]
            public Transform lastLabelPlaced;
    
            [HideInInspector]
            public TextMesh lastLabelPlacedText;
    
            private void Awake()
            {
                // allows this instance to behave like a singleton
                instance = this;
            }
    
            /// <summary>
            /// Instantiate a Label in the appropriate location relative to the Main Camera.
            /// </summary>
            public void CreateLabel()
            {
                lastLabelPlaced = Instantiate(labelPrefab, cursor.transform.position, transform.rotation);
    
                lastLabelPlacedText = lastLabelPlaced.GetComponent<TextMesh>();
    
                // Change the text of the label to show that has been placed
                // The final text will be set at a later stage
                lastLabelPlacedText.text = "Analysing...";
            }
    
            /// <summary>
            /// Set the Tags as Text of the last Label created. 
            /// </summary>
            public void SetTagsToLastLabel(Dictionary<string, float> tagsDictionary)
            {
                lastLabelPlacedText = lastLabelPlaced.GetComponent<TextMesh>();
    
                // At this point we go through all the tags received and set them as text of the label
                lastLabelPlacedText.text = "I see: \n";
    
                foreach (KeyValuePair<string, float> tag in tagsDictionary)
                {
                    lastLabelPlacedText.text += tag.Key + ", Confidence: " + tag.Value.ToString("0.00 \n");
                }    
            }
        }
    
  5. Unity로 돌아가기 전에 Visual Studio 에서 변경 내용을 저장해야 합니다.

  6. Unity 편집기로 돌아가서 ResultsLabel 클래스를 Scripts 폴더에서 계층 구조 패널Main Camera 개체로 끌어옵니다.

  7. 주 카메라를 클릭하고 검사기 패널을 확인합니다.

방금 카메라로 끌어간 스크립트에는 커서레이블 프리팹의 두 필드가 있습니다.

  1. 아래 이미지와 같이 Cursor 라는 개체를 계층 구조 패널 에서 커서라는 슬롯으로 끌어옵니다.

  2. 아래 이미지와 같이 LabelText라는 개체를 프로젝트 패널Assets 폴더에서 Label Prefab이라는 슬롯으로 끌어옵니다.

    Unity 내에서 참조 대상을 설정합니다.

6장 – ImageCapture 클래스 만들기

만들려는 다음 클래스는 ImageCapture 클래스입니다. 이 클래스는 다음을 담당합니다.

  • HoloLens 카메라를 사용하여 이미지를 캡처하고 앱 폴더에 저장합니다.
  • 사용자로부터 탭 제스처 캡처

이 클래스를 만들려면 다음을 수행합니다.

  1. 이전에 만든 Scripts 폴더로 이동합니다.

  2. C# 스크립트 만들기 >폴더 내부를 마우스 오른쪽 단추로 클릭합니다. ImageCapture 스크립트를 호출합니다.

  3. ImageCapture 스크립트를 두 번 클릭하여 Visual Studio에서 엽니다.

  4. 파일 맨 위에 다음 네임스페이스를 추가합니다.

        using System.IO;
        using System.Linq;
        using UnityEngine;
        using UnityEngine.XR.WSA.Input;
        using UnityEngine.XR.WSA.WebCam;
    
  5. 그런 다음, Start() 메서드 위에 ImageCapture 클래스 내에 다음 변수를 추가합니다.

        public static ImageCapture instance; 
        public int tapsCount;
        private PhotoCapture photoCaptureObject = null;
        private GestureRecognizer recognizer;
        private bool currentlyCapturing = false;
    

tapsCount 변수는 사용자로부터 캡처된 탭 제스처 수를 저장합니다. 이 숫자는 캡처된 이미지의 이름 지정에 사용됩니다.

  1. 이제 Awake()Start() 메서드에 대한 코드를 추가해야 합니다. 클래스가 초기화될 때 호출됩니다.

        private void Awake()
        {
            // Allows this instance to behave like a singleton
            instance = this;
        }
    
        void Start()
        {
            // subscribing to the HoloLens API gesture recognizer to track user gestures
            recognizer = new GestureRecognizer();
            recognizer.SetRecognizableGestures(GestureSettings.Tap);
            recognizer.Tapped += TapHandler;
            recognizer.StartCapturingGestures();
        }
    
  2. Tap 제스처가 발생할 때 호출되는 처리기를 구현합니다.

        /// <summary>
        /// Respond to Tap Input.
        /// </summary>
        private void TapHandler(TappedEventArgs obj)
        {
            // Only allow capturing, if not currently processing a request.
            if(currentlyCapturing == false)
            {
                currentlyCapturing = true;
    
                // increment taps count, used to name images when saving
                tapsCount++;
    
                // Create a label in world space using the ResultsLabel class
                ResultsLabel.instance.CreateLabel();
    
                // Begins the image capture and analysis procedure
                ExecuteImageCaptureAndAnalysis();
            }
        }
    

TapHandler() 메서드는 사용자로부터 캡처된 탭 수를 증가시키고 현재 커서 위치를 사용하여 새 레이블의 위치를 결정합니다.

그런 다음, 이 메서드는 ExecuteImageCaptureAndAnalysis() 메서드를 호출하여 이 애플리케이션의 핵심 기능을 시작합니다.

  1. 이미지가 캡처되고 저장되면 다음 처리기가 호출됩니다. 프로세스가 성공하면 결과를 분석을 위해 VisionManager (아직 만들지 않은)에 전달됩니다.

        /// <summary>
        /// Register the full execution of the Photo Capture. If successful, it will begin 
        /// the Image Analysis process.
        /// </summary>
        void OnCapturedPhotoToDisk(PhotoCapture.PhotoCaptureResult result)
        {
            // Call StopPhotoMode once the image has successfully captured
            photoCaptureObject.StopPhotoModeAsync(OnStoppedPhotoMode);
        }
    
        void OnStoppedPhotoMode(PhotoCapture.PhotoCaptureResult result)
        {
            // Dispose from the object in memory and request the image analysis 
            // to the VisionManager class
            photoCaptureObject.Dispose();
            photoCaptureObject = null;
            StartCoroutine(VisionManager.instance.AnalyseLastImageCaptured()); 
        }
    
  2. 그런 다음 애플리케이션이 이미지 캡처 프로세스를 시작하고 이미지를 저장하는 데 사용하는 메서드를 추가합니다.

        /// <summary>    
        /// Begin process of Image Capturing and send To Azure     
        /// Computer Vision service.   
        /// </summary>    
        private void ExecuteImageCaptureAndAnalysis()  
        {    
            // Set the camera resolution to be the highest possible    
            Resolution cameraResolution = PhotoCapture.SupportedResolutions.OrderByDescending((res) => res.width * res.height).First();    
    
            Texture2D targetTexture = new Texture2D(cameraResolution.width, cameraResolution.height);
    
            // Begin capture process, set the image format    
            PhotoCapture.CreateAsync(false, delegate (PhotoCapture captureObject)    
            {    
                photoCaptureObject = captureObject;    
                CameraParameters camParameters = new CameraParameters();    
                camParameters.hologramOpacity = 0.0f;    
                camParameters.cameraResolutionWidth = targetTexture.width;    
                camParameters.cameraResolutionHeight = targetTexture.height;    
                camParameters.pixelFormat = CapturePixelFormat.BGRA32;
    
                // Capture the image from the camera and save it in the App internal folder    
                captureObject.StartPhotoModeAsync(camParameters, delegate (PhotoCapture.PhotoCaptureResult result)
                {    
                    string filename = string.Format(@"CapturedImage{0}.jpg", tapsCount);
    
                    string filePath = Path.Combine(Application.persistentDataPath, filename);
    
                    VisionManager.instance.imagePath = filePath;
    
                    photoCaptureObject.TakePhotoAsync(filePath, PhotoCaptureFileOutputFormat.JPG, OnCapturedPhotoToDisk);
    
                    currentlyCapturing = false;
                });   
            });    
        }
    

경고

이때 Unity 편집기 콘솔 패널에 오류가 표시됩니다. 코드가 다음 챕터에서 만들 VisionManager 클래스를 참조하기 때문입니다.

7장 - Azure 및 이미지 분석 호출

만들어야 하는 마지막 스크립트는 VisionManager 클래스입니다.

이 클래스는 다음을 담당합니다.

  • 바이트 배열로 캡처된 최신 이미지 로드
  • 분석을 위해 바이트 배열을 Azure Computer Vision API Service instance 보냅니다.
  • 응답을 JSON 문자열로 수신합니다.
  • 응답을 역직렬화하고 결과 태그를 ResultsLabel 클래스에 전달합니다.

이 클래스를 만들려면 다음을 수행합니다.

  1. Scripts 폴더를 두 번 클릭하여 엽니다.

  2. Scripts 폴더 내부를 마우스 오른쪽 단추로 클릭하고 C# 스크립트 만들기>를 클릭합니다. 스크립트 이름을 VisionManager로 지정합니다.

  3. 새 스크립트를 두 번 클릭하여 Visual Studio에서 엽니다.

  4. VisionManager 클래스의 맨 위에서 네임스페이스를 다음과 동일하게 업데이트합니다.

        using System;
        using System.Collections;
        using System.Collections.Generic;
        using System.IO;
        using UnityEngine;
        using UnityEngine.Networking;
    
  5. 스크립트 맨 위에 있는 VisionManager 클래스(Start() 메서드 위)에서 이제 Azure에서 역직렬화된 JSON 응답을 나타내는 두 개의 클래스를 만들어야 합니다.

        [System.Serializable]
        public class TagData
        {
            public string name;
            public float confidence;
        }
    
        [System.Serializable]
        public class AnalysedObject
        {
            public TagData[] tags;
            public string requestId;
            public object metadata;
        }
    

    참고

    Unity 라이브러리를 사용하여 역직렬화하려면 선언 앞에 [System.Serializable] 특성이 추가되어야 TagDataAnalysiedObject 클래스가 추가되어야 합니다.

  6. VisionManager 클래스에서 다음 변수를 추가해야 합니다.

        public static VisionManager instance;
    
        // you must insert your service key here!    
        private string authorizationKey = "- Insert your key here -";    
        private const string ocpApimSubscriptionKeyHeader = "Ocp-Apim-Subscription-Key";
        private string visionAnalysisEndpoint = "https://westus.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures=Tags";   // This is where you need to update your endpoint, if you set your location to something other than west-us.
    
        internal byte[] imageBytes;
    
        internal string imagePath;
    

    경고

    인증 키를authorizationKey 변수에 삽입해야 합니다. 이 과정의 시작 부분에서 인증 키를 적어 두었을 것입니다. 1장.

    경고

    visionAnalysisEndpoint 변수는 이 예제에 지정된 변수와 다를 수 있습니다. west-us는 미국 서부 지역에 대해 만들어진 서비스 인스턴스를 엄격하게 나타냅니다. 엔드포인트 URL로 업데이트합니다. 다음은 다음과 같은 몇 가지 예입니다.

    • 서유럽: https://westeurope.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures=Tags
    • 동남 아시아: https://southeastasia.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures=Tags
    • 오스트레일리아 동부: https://australiaeast.api.cognitive.microsoft.com/vision/v1.0/analyze?visualFeatures=Tags
  7. 이제 Awake에 대한 코드를 추가해야 합니다.

        private void Awake()
        {
            // allows this instance to behave like a singleton
            instance = this;
        }
    
  8. 다음으로, 아래 정적 스트림 메서드를 사용하여 코루틴을 추가합니다. 그러면 ImageCapture 클래스에서 캡처한 이미지 분석 결과를 얻을 수 있습니다.

        /// <summary>
        /// Call the Computer Vision Service to submit the image.
        /// </summary>
        public IEnumerator AnalyseLastImageCaptured()
        {
            WWWForm webForm = new WWWForm();
            using (UnityWebRequest unityWebRequest = UnityWebRequest.Post(visionAnalysisEndpoint, webForm))
            {
                // gets a byte array out of the saved image
                imageBytes = GetImageAsByteArray(imagePath);
                unityWebRequest.SetRequestHeader("Content-Type", "application/octet-stream");
                unityWebRequest.SetRequestHeader(ocpApimSubscriptionKeyHeader, authorizationKey);
    
                // the download handler will help receiving the analysis from Azure
                unityWebRequest.downloadHandler = new DownloadHandlerBuffer();
    
                // the upload handler will help uploading the byte array with the request
                unityWebRequest.uploadHandler = new UploadHandlerRaw(imageBytes);
                unityWebRequest.uploadHandler.contentType = "application/octet-stream";
    
                yield return unityWebRequest.SendWebRequest();
    
                long responseCode = unityWebRequest.responseCode;     
    
                try
                {
                    string jsonResponse = null;
                    jsonResponse = unityWebRequest.downloadHandler.text;
    
                    // The response will be in Json format
                    // therefore it needs to be deserialized into the classes AnalysedObject and TagData
                    AnalysedObject analysedObject = new AnalysedObject();
                    analysedObject = JsonUtility.FromJson<AnalysedObject>(jsonResponse);
    
                    if (analysedObject.tags == null)
                    {
                        Debug.Log("analysedObject.tagData is null");
                    }
                    else
                    {
                        Dictionary<string, float> tagsDictionary = new Dictionary<string, float>();
    
                        foreach (TagData td in analysedObject.tags)
                        {
                            TagData tag = td as TagData;
                            tagsDictionary.Add(tag.name, tag.confidence);                            
                        }
    
                        ResultsLabel.instance.SetTagsToLastLabel(tagsDictionary);
                    }
                }
                catch (Exception exception)
                {
                    Debug.Log("Json exception.Message: " + exception.Message);
                }
    
                yield return null;
            }
        }
    
        /// <summary>
        /// Returns the contents of the specified file as a byte array.
        /// </summary>
        private static byte[] GetImageAsByteArray(string imageFilePath)
        {
            FileStream fileStream = new FileStream(imageFilePath, FileMode.Open, FileAccess.Read);
            BinaryReader binaryReader = new BinaryReader(fileStream);
            return binaryReader.ReadBytes((int)fileStream.Length);
        }  
    
  9. Unity로 돌아가기 전에 Visual Studio 에서 변경 내용을 저장해야 합니다.

  10. Unity 편집기로 돌아가서 VisionManagerImageCapture 클래스를 Scripts 폴더에서 계층 패널의 Main Camera 개체로 끌어옵니다.

8장 – 빌드 전

애플리케이션에 대한 철저한 테스트를 수행하려면 HoloLens에 테스트용으로 로드해야 합니다. 이렇게 하기 전에 다음을 확인합니다.

  • 2장에 언급된 모든 설정이 올바르게 설정됩니다.
  • 모든 스크립트는 Main Camera 개체에 연결됩니다.
  • 주 카메라 검사기 패널의 모든 필드가 제대로 할당됩니다.
  • 인증 키를authorizationKey 변수에 삽입해야 합니다.
  • VisionManager 스크립트에서 엔드포인트도 확인하고 해당 지역에 맞춰야 합니다(이 문서에서는 기본적으로 west-us를 사용).

9장 - UWP 솔루션 빌드 및 애플리케이션 테스트용 로드

이제 이 프로젝트의 Unity 섹션에 필요한 모든 항목이 완료되었으므로 Unity에서 빌드해야 합니다.

  1. 빌드 설정 - 파일 > 빌드 설정으로 이동합니다.

  2. 빌드 설정 창에서 빌드를 클릭합니다.

    Unity에서 앱 빌드

  3. 아직 없는 경우 Unity C# 프로젝트를 선택합니다.

  4. 빌드를 클릭한 다음 Unity는 파일 탐색기 창을 시작합니다. 여기서 앱을 만든 다음, 앱을 빌드할 폴더를 선택해야 합니다. 이제 해당 폴더를 만들고 이름을 앱으로 지정 합니다. 그런 다음 , App 폴더를 선택한 상태에서 폴더 선택을 누릅니다.

  5. Unity는 App 폴더에 프로젝트 빌드를 시작합니다.

  6. Unity 빌드가 완료되면(다소 시간이 걸릴 수 있음) 빌드 위치에서 파일 탐색기 창이 열립니다(작업 표시줄을 검사 항상 창 위에 표시되지는 않지만 새 창이 추가되었음을 알려 줍니다).

10장 – HoloLens에 배포

HoloLens에 배포하려면 다음을 수행합니다.

  1. HoloLens의 IP 주소(원격 배포의 경우)가 필요하며 HoloLens가 개발자 모드에 있는지 확인해야 합니다. 가상 하드 디스크 파일에 대한 중요 정보를 제공하려면

    1. HoloLens를 착용하는 동안 설정을 엽니다.
    2. 네트워크 & 인터넷 > Wi-Fi > 고급 옵션으로 이동합니다.
    3. IPv4 주소를 기록해 둡니다.
    4. 다음으로 설정으로 다시 이동한 다음 개발자용 & 보안 > 업데이트로 이동합니다.
    5. 개발자 모드를 설정합니다.
  2. 새 Unity 빌드( App 폴더)로 이동하여 Visual Studio를 사용하여 솔루션 파일을 엽니다.

  3. 솔루션 구성에서 디버그를 선택합니다.

  4. 솔루션 플랫폼에서 x86, 원격 머신을 선택합니다.

    Visual Studio에서 솔루션을 배포합니다.

  5. 빌드 메뉴로 이동하여 솔루션 배포를 클릭하여 HoloLens에 애플리케이션을 테스트용으로 로드합니다.

  6. 이제 시작 준비가 된 HoloLens에 설치된 앱 목록에 앱이 표시됩니다.

참고

몰입형 헤드셋에 배포하려면 솔루션 플랫폼을로컬 머신으로 설정하고 구성을디버그로 설정하고 x86플랫폼으로 설정합니다. 그런 다음 빌드 메뉴를 사용하여 로컬 머신에 배포하고 솔루션 배포를 선택합니다.

완료된 Computer Vision API 애플리케이션

축하합니다. Azure Computer Vision API를 활용하여 실제 개체를 인식하고 표시된 내용에 대한 신뢰도를 표시하는 혼합 현실 앱을 빌드했습니다.

랩 결과

보너스 연습

연습 1

Tags 매개 변수를 사용한 것처럼(VisionManager 내에서 사용되는 엔드포인트 내에서 입증된 대로) 다른 정보를 검색하도록 앱을 확장합니다. 여기에 액세스할 수 있는 다른 매개 변수를 살펴보세요.

연습 2

반환된 Azure 데이터를 더 대화형으로 표시하고 읽을 수 있는 방식으로 표시합니다. 아마도 숫자를 숨길 수 있습니다. 봇이 사용자에게 말하는 것처럼.