Classification
이 문서는 SaigieVision을 통해 이미지를 'Classification(분류)' 하는 방법에 대해 설명합니다.
여러분이 앞서 제공된 Quick Start 를 끝냈다면, 'Classification'을 수행하는 방법은 그리 어렵지 않습니다.
해당 가이드에서 추가된건 오직 ClassificationEngine이기 때문입니다.
아래 코드 블럭은 간단하게 Classification 검사 진행 방법에 대해서 설명합니다.
{
//Initialize
SaigeVision.Core.SaigeVisionApp.Init();
//Prepare
IGpuService gpuService = new NvGpuService();
gpuService.DetectConnectedGPUs();
PhysicalGpu gpu = gpuService.CurrentDetectedGPUs[0];
SrImage image = new SrImage(@"..\..\000001.png");
Uri model = new Uri(@"..\..\model.srCls");
//Inspect
using (var engine = EngineLoader.LoadFrom<ClassificationEngine>(model))
{
ClsInspectionOptions option = engine.ReadInspectionOptions();
option.AdditionalScores[0] = 0;
option.AdditionalScores[1] = 10;
option.AdditionalScores[2] = 10;
engine.AllocateNetwork(gpu, option);
ClassificationReport report = engine.Inspect(image);
ClassInfo prediction = report.Prediction;
Console.WriteLine($"Inspection time : {report.InspectionTime}");
Console.WriteLine($"Predicted : {prediction.Name}");
}
//Clean up (optional)
image.Dispose();
}
Initialize
SaigeVision.Core를 사용하기 위해서는 런타임에 돌입하는 시점에서 1회 SaigeVisionApp.Init()을 통해 SaigeVision.Core를 초기화해야 합니다.
초기화를 진행하기 적절한 장소는 작성중인 애플리케이션의 main() 함수 최상단입니다.
여러분이 Console App이 아닌 다른 플랫폼을 사용하여 main()함수를 찾기 어렵다면 (WPF, WinForms 와 같은...) 어느 위치라도 좋으나 오직 '단 한번' 호출 하는것을 보장하는 장소가 좋습니다.
또한, EngineLoader를 사용하기 전이어야 합니다.
Prepare
ClassificationEngine을 사용하기 위해 필요한 모든 데이터를 준비하는 과정입니다.
일반적으로 아래와 같은 3가지를 요구합니다.
- 검사에 사용할 GPU
- 검사에 사용할 샘플 이미지들
- 검사에 사용할 모델( .srCls 파일)
SaigeVision은 NVIDIA사의 GPU만을 지원하고 있습니다.
또한, SaigeVision은 모든 이미지 개체를 SrImage를 통해 전달 받고 있습니다.
SrImage는 내부적으로 ArrayPool<T>과 같은 .Net의 도구들을 통해 성능 최적화를 이루는데 많은 노력을 기울였습니다.
다양한 생성자를 지원하니 꼭 SrImage에 대한 API docs 확인을 권장합니다.
Inspection
'Inspection'부는 ClassificationEngine을 EngineLoader를 통해 로드하는 것으로 시작합니다.
'Inspection'부는 알아보기 쉽게 아래와 같이 절차를 구분하여 설명하겠습니다.
1. Load engine
이 예제에서는 사용의 안전을 위해 C# 언어의 using 문을 사용합니다.
여러분의 시나리오에서 해당 using문 사용이 알맞지 않다고 생각한다면, 무시 할 수 있습니다.
하지만 using문을 사용하지 않는 경우, 사용이 완료된 ClassificationEngine은 반드시 관리 하에 ClassificationEngine.Dispose() 되어야합니다.
EngineLoader.LoadFrom<T>()는 완료하는데 약간이 시간이 소요 될 수 있습니다. 이는 일반적으로 Thread가 Blocking 될 수 있는 정도의 수준입니다.
2. Inspection Options
다시 샘플 코드의 설명으로 돌아가면, 샘플 코드는 Engine을 로드하고 나서 해당 Engine을 통해 ClsInspectionOptions를 로드하고 있습니다.
ClassificationEngine은 Inspection을 수행할 때 여러가지 옵션을 지정할 수 있습니다.
해당 옵션들은 실제 Inspection을 수행하는데 영향을 주며, 레포트(결과)에 반영됩니다.
이 예제에서는 뒤에 이어지는 코드에서 보이는것 처럼 'Additional score'에 옵션 값을 지정하고 있습니다.
이렇게 만들어진 새로운 옵션은(ClassificationOptions)는 Engine의 AllocateNetowrk()를 통해 주입이 가능합니다.
- 이후 진행되는 모든 'Inspection'의 결과는 해당 Option이 적용된 값입니다.
특정한 시나리오에서는 이렇게 설정한 Option 값을 모델에 기록할 필요가 있을 수 있습니다.
사실 LoadInspectionOptions()는 모델에 기록된 제일 최근의 Option 값을 로드하는 함수입니다.
여러분이 해당 Option을 모델에 기록하길 원한다면 WirteInspectionOptions()를 사용하세요.
또한, WriteInspectionOptionsAsDefault()를 통해 Default options로 되돌릴 수 있습니다.
만약
AllocateNetowrk()를 통해 Options를 지정하지 않는다면, 자동적으로 모델에 기록되어있는 Option을 사용합니다.AllocateNetowrk()는 약간의 시간이 소요될 수 있습니다. 일반적으로 Thread가 Blocking될 수 있는 수준입니다.
3. Inspect
코드에서 볼수 있는 것처럼 'Inspection'을 수행하는 주 함수는 engine.Inspect()입니다. 모든 종류의 Engine들은 이러한 공통의 Inspect() 함수를 보유하고 있습니다. 또한, 다양한 사용을 위해 여러 형태로 중첩 되어 있습니다. 비동기 혹은 다수의 이미지들을 검사하는 등의 여러 시나리오에서 선택적으로 사용할 수 있습니다.
Inspect()가 반환하는 ClassificationReport는 검사를 진행한 후 전달해야 하는 모든 결과를 레포트합니다.
Clean up (Optional)
이 예제에서는 검사에 사용했던 SrImage들을 더 이상 사용할 곳이 없이게 Dispose() 합니다.
많은 수의 이미지를 한번에 검사
앞선 예제에서는 '한 장의 이미지'를 검사하는 시나리오에 대해서 살펴보았습니다. 하지만 '많은 수의 이미지'를 한번에 검사하고자 하는 경우에 대해 알아보겠습니다.
샘플 코드에서 몇가지 부분을 수정하여 이 상황을 해결해봅시다.
우선 SrImage을 배열로 만들어 '많은 수의 이미지' 데이터를 준비합니다. 아래와 같습니다.
SrImage[] srImages = new SrImage[]
{
new SrImage(@"..\...\sample1.png"),
new SrImage(@"..\...\sample2.png"),
new SrImage(@"..\...\sample3.png"),
new SrImage(@"..\...\sample4.png")
};
이후 AllocateNetowrk()에 숨어있던 마지막 인자를 사용할 수 있습니다.
engine.AllocateNetwork(gpu, option, 4);
마지막 인자는 '최대 이미지 수' 를 의미하며 한번에 (병렬로) 처리할 수 있는 이미지 수를 의미합니다.
기본적으로 2의 거듭제곱으로 설정할 것을 추천드립니다.
큰 값이 설정될수록 GPU 메모리 할당량이 커지므로, 메모리가 부족하다면 작은 수로 설정해 주세요.
설정된 값보다 많은 수의 이미지를 검사하는 경우, 내부적으로 여러 번의 검사를 수행합니다.
마지막으로 Inspect() 함수가 포함된 라인 이후를 수정합니다.
ClassificationReport[] reports = engine.Inspect(data);
foreach (var report in reports)
{
ClassInfo prediction = report.Prediction;
Console.WriteLine($"Inspection time : {report.InspectionTime}");
Console.WriteLine($"Predicted : {prediction.Name}");
}
이제 코드를 동작하여 '많은 수의 이미지'를 검사할 수 있습니다.