사용할 네트워크와 클래스 문자열 정보를 제대로 불러왔으면 이제 네트워크에 영상 블롭을 전달하여 추론하는 코드를 알아보겠습니다. 테스트로 사용할 입력 영상은 imread() 함수를 이용하여 불러옵니다. 그리고 불러온 영상을 blobFromImage() 함수를 이용하여 블롭으로 변환합니다. 카페에서 학습된 구글넷은 입력으로 224×224 크기의 BGR 컬러 영상을 사용하였고, 각 영상에서 평균값 Scalar(104, 117, 123)을 빼서 학습시켰습니다.9 그러므로 blobFromImage() 함수 인자는 다음과 같이 구성해야 합니다.
Mat img = imread("space_shuttle.jpg", IMREAD_COLOR); Mat inputBlob = blobFromImage(img, 1, Size(224, 224), Scalar(104, 117, 123));
앞 코드에 의해 만들어지는 inputBlob 행렬은 1×3×224×224 형태를 갖는 4차원 행렬입니다. 이 행렬을 앞서 생성한 네트워크에 입력으로 전달하고, 순방향으로 실행하여 그 결과를 받아 옵니다.
net.setInput(inputBlob);
Mat prob = net.forward();
카페 구글넷 네트워크의 경우 최종 레이어는 1000개의 노드를 가지고 있고, 각 노드 출력은 해당 번호 영상 클래스에 대한 확률을 표현합니다. 앞 코드에서 net.forward() 코드가 반환하는 Mat 객체 prob는 CV_32FC1 타입이고, 1×1000 크기의 행렬입니다. 즉, prob는 1행 1000열 행렬이고, 각 열에는 1000개 클래스에 대한 확률이 저장됩니다. 그러므로 prob 행렬에서 최대 확률을 갖는 열 번호가 입력 영상에 해당하는 클래스 번호라고 판단할 수 있으며, prob 행렬에서 최대 확률 위치는 minMaxLoc() 함수를 이용하여 쉽게 알아낼 수 있습니다. 만약 최대 확률에 해당하는 클래스 이름을 알고 싶다면 classNames 벡터에서 해당 문자열을 추출할 수 있습니다.
9 카페에서 구글넷을 훈련할 때 입력 데이터를 어떻게 설정하였는지에 대한 정보는 다음 링크에서 참조할 수 있습니다. https://github.com/BVLC/caffe/blob/master/models/bvlc_googlenet/train_val.prototxt