모델 테스트를 위해서는 다음과 같은 과정이 필요합니다.
추론 그래프 추출
추론 그래프를 사용하여 객체 검출
추론그래프를 추출하기 위해서는 Tensorflow object Detection API에서 제공되는 export_inference_graph.py을 사용하면 됩니다.
바로 본론으로 넘어가겠습니다. 챕터3에서 학습을 진행하면 체크포인트가 실행폴더에 저장되게 됩니다. 파일형태는 model.ckpt-xxxx와 같은 형태로 저장되며, 원하는 체크포인트 번호를 명령어에 입력해 추론그래프로 만들어주는 과정이 필요합니다. 명령어 코드는 아래에 작성되어 있으며, 제가 프로젝트를 진행하며 사용한 ipynb 코드는 깃허브를 통해 업로드 하였습니다.
! python export_inference_graph.py --input_type image_tensor --pipeline_config_path training/faster_rcnn_inception_resnet_v2_atrous_coco.config --trained_checkpoint_prefix samples/model.ckpt-xxxxx --output_directory inference_graph

이 과정에서 추론그래프를 생성할 수 있습니다. 추론그래프는 위와 같이 저장됩니다. 그 중 frozen_inference_graph.pb 파일이 모델 테스트를 위해 사용할 추론그래프 파일입니다.
추론그래프를 생성하였다면 test set으로 추론 결과를 시각화 하게 됩니다.
자세한 코드는 깃허브에 업로드 하였습니다.
추가로 각 코드에 대해 설명하겠습니다.
PATH_TO_FROZEN_GRAPH = 'inference_graph/frozen_inference_graph.pb'
 
detection_graph = tf.Graph()
with detection_graph.as_default():
 
    od_graph_def = tf.compat.v1.GraphDef()
 
    with tf.compat.v2.io.gfile.GFile(PATH_TO_FROZEN_GRAPH, 'rb') as f:
 
        serialized_graph = f.read()
        od_graph_def.ParseFromString(serialized_graph)
 
        tf.import_graph_def(od_graph_def, name = "")
먼저 앞에서 생성한 추론그래프를 불러옵니다.
PATH_TO_FROZEN_GRAPH 에서 저장된 추론그래프의 경로를 지정해주면 됩니다.
def run_inference_for_single_image(image, graph):
    with tf.compat.v1.Session(graph = graph) as sess:
 
        input_tensor = graph.get_tensor_by_name('image_tensor:0')
        
        target_operation_names = ['num_detections', 'detection_boxes',
                                  'detection_scores', 'detection_classes', 'detection_masks']
        tensor_dict = {}
        for key in target_operation_names:
            op = None
            try:
                op = graph.get_operation_by_name(key)
                
            except:
                continue
 
            tensor = graph.get_tensor_by_name(op.outputs[0].name)
            tensor_dict[key] = tensor
 
        if 'detection_masks' in tensor_dict:
            detection_boxes = tf.squeeze(tensor_dict['detection_boxes'], [0])
 
        output_dict = sess.run(tensor_dict, feed_dict = {input_tensor : [image]})
            
        output_dict['num_detections'] = int(output_dict['num_detections'][0])
        output_dict['detection_classes'] = output_dict['detection_classes'][0].astype(np.uint8)
        output_dict['detection_boxes'] = output_dict['detection_boxes'][0]
        output_dict['detection_scores'] = output_dict['detection_scores'][0]
 
        return output_dict
run_inference_for_single_image 함수입니다. 이 함수를 통해 output 딕셔너리를 return 하게 되는데, 이것은 하나의 이미지에 대해 객체가 있는 좌표, score, 클래스 number등을 정보에 저장하는 것입니다.
def draw_bounding_boxes(img, output_dict,count):
    boxlist = []
    height, width, _ = img.shape
 
    obj_index = output_dict['detection_scores'] > 0.8
    
    scores = output_dict['detection_scores'][obj_index]
    boxes = output_dict['detection_boxes'][obj_index]
    classes = output_dict['detection_classes'][obj_index]
    for i in range(len(boxes)):
      boxlist.append([boxes[i][0], boxes[i][1], boxes[i][2], boxes[i][3]])
    
    boxlist.sort(key=lambda x:x[1])
    print(boxlist)
    if(len(boxlist) >= 3):
      if(len(boxlist) == 4):
        if(boxlist[0][0] > boxlist[1][0]):
          boxlist[0], boxlist[1] = boxlist[1], boxlist[0]
        if(boxlist[2][0] > boxlist[3][0]):
          boxlist[2], boxlist[3] = boxlist[3], boxlist[2]
      else:
        if(boxlist[0][0] > boxlist[1][0]):
          boxlist[0], boxlist[1] = boxlist[1], boxlist[0]
    print(boxlist)
 
    count1 = 0
    for box in boxlist:
        count1 += 1
        cut_img = img[int(box[0] * height):int(box[2] * height), int(box[1] * width):int(box[3] * width)].copy()
        save_img = Image.fromarray(cut_img)
        save_img.save("data/images_choice/train/cut_jpgs/image_{0}{1}.jpg".format(count,count1))
        
    return img
draw_bounding_boxes 함수입니다. 이것은 모델이 추론한 객체의 부분을 박스로 그려 return 하는 함수인데, 저는 이것에 추가로 박스 모양을 각각 잘라 저장하는 코드를 추가했습니다. 코드의 중간쯤에 if 문으로 작성된 코드는 위치별로 시험지 속 문제들을 순서대로 저장하기 위한 코드이며, 이 코드에 따라 페이지 속 문제들이 번호 순서대로 잘려 저장됩니다.
Cropping Question By Inference.ipynb

최종적으로 잘려진 이미지들은 위와 같이 디렉토리에 저장되고, 저는 이 이미지에서 항목들을 따로 라벨링하여 학습시켜주었습니다. 해당 내용은 챕터 4에 담겠습니다.