자습서: Python에서 TensorFlow 모델 실행
이 자습서에서는 내보낸 TensorFlow 모델을 로컬로 사용하여 이미지를 분류하는 방법을 보여 줍니다.
참고 항목
이 자습서는 “일반(압축)” 이미지 분류 프로젝트에서 내보낸 모델에만 적용됩니다. 다른 모델을 내보낸 경우 샘플 코드 리포지토리를 참조하세요.
필수 조건
- Python 2.7+ 또는 Python 3.6+ 중 하나를 설치합니다.
- pip를 설치합니다.
다음으로, 다음과 같은 패키지를 설치해야 합니다.
pip install tensorflow
pip install pillow
pip install numpy
pip install opencv-python
모델 및 태그 로드
다운로드한 zip 파일에는 model.pb 및 labels.txt가 포함되어 있습니다. 이러한 파일은 학습된 모델 및 분류 레이블을 나타냅니다. 첫 번째 단계는 프로젝트에 모델을 로드하는 것입니다. 새 Python 스크립트에 다음 코드를 추가합니다.
import tensorflow as tf
import os
graph_def = tf.compat.v1.GraphDef()
labels = []
# These are set to the default names from exported models, update as needed.
filename = "model.pb"
labels_filename = "labels.txt"
# Import the TF graph
with tf.io.gfile.GFile(filename, 'rb') as f:
graph_def.ParseFromString(f.read())
tf.import_graph_def(graph_def, name='')
# Create a list of labels.
with open(labels_filename, 'rt') as lf:
for l in lf:
labels.append(l.strip())
예측을 위해 이미지 준비
예측을 위한 이미지를 준비하기 위해 수행해야 하는 몇 가지 단계가 있습니다. 이러한 단계는 학습 동안 수행되는 이미지 조작을 모방한 것입니다.
파일 열기 및 BGR 색 공간에 이미지 만들기
from PIL import Image import numpy as np import cv2 # Load from a file imageFile = "<path to your image file>" image = Image.open(imageFile) # Update orientation based on EXIF tags, if the file has orientation info. image = update_orientation(image) # Convert to OpenCV format image = convert_to_opencv(image)
이미지의 크기가 1600픽셀보다 큰 경우 이 메서드를 호출합니다(나중에 정의됨).
image = resize_down_to_1600_max_dim(image)
가장 큰 가운데 사각형 자르기
h, w = image.shape[:2] min_dim = min(w,h) max_square_image = crop_center(image, min_dim, min_dim)
해당 사각형의 크기를 256x256으로 조정
augmented_image = resize_to_256_square(max_square_image)
모델의 특정 입력 크기에 맞게 가운데 자르기
# Get the input size of the model with tf.compat.v1.Session() as sess: input_tensor_shape = sess.graph.get_tensor_by_name('Placeholder:0').shape.as_list() network_input_size = input_tensor_shape[1] # Crop the center for the specified network_input_Size augmented_image = crop_center(augmented_image, network_input_size, network_input_size)
도우미 함수 정의 위의 단계는 다음과 같은 도우미 함수를 사용합니다.
def convert_to_opencv(image): # RGB -> BGR conversion is performed as well. image = image.convert('RGB') r,g,b = np.array(image).T opencv_image = np.array([b,g,r]).transpose() return opencv_image def crop_center(img,cropx,cropy): h, w = img.shape[:2] startx = w//2-(cropx//2) starty = h//2-(cropy//2) return img[starty:starty+cropy, startx:startx+cropx] def resize_down_to_1600_max_dim(image): h, w = image.shape[:2] if (h < 1600 and w < 1600): return image new_size = (1600 * w // h, 1600) if (h > w) else (1600, 1600 * h // w) return cv2.resize(image, new_size, interpolation = cv2.INTER_LINEAR) def resize_to_256_square(image): h, w = image.shape[:2] return cv2.resize(image, (256, 256), interpolation = cv2.INTER_LINEAR) def update_orientation(image): exif_orientation_tag = 0x0112 if hasattr(image, '_getexif'): exif = image._getexif() if (exif != None and exif_orientation_tag in exif): orientation = exif.get(exif_orientation_tag, 1) # orientation is 1 based, shift to zero based and flip/transpose based on 0-based values orientation -= 1 if orientation >= 4: image = image.transpose(Image.TRANSPOSE) if orientation == 2 or orientation == 3 or orientation == 6 or orientation == 7: image = image.transpose(Image.FLIP_TOP_BOTTOM) if orientation == 1 or orientation == 2 or orientation == 5 or orientation == 6: image = image.transpose(Image.FLIP_LEFT_RIGHT) return image
이미지 분류
이미지가 텐서로서 준비되면 예측을 위해 모델을 통해 보낼 수 있습니다.
# These names are part of the model and cannot be changed.
output_layer = 'loss:0'
input_node = 'Placeholder:0'
with tf.compat.v1.Session() as sess:
try:
prob_tensor = sess.graph.get_tensor_by_name(output_layer)
predictions = sess.run(prob_tensor, {input_node: [augmented_image] })
except KeyError:
print ("Couldn't find classification output layer: " + output_layer + ".")
print ("Verify this a model exported from an Object Detection project.")
exit(-1)
결과를 표시합니다
모델을 통해 이미지 텐서를 실행한 결과를 레이블에 다시 매핑해야 합니다.
# Print the highest probability label
highest_probability_index = np.argmax(predictions)
print('Classified as: ' + labels[highest_probability_index])
print()
# Or you can print out all of the results mapping labels to probabilities.
label_index = 0
for p in predictions:
truncated_probablity = np.float64(np.round(p,8))
print (labels[label_index], truncated_probablity)
label_index += 1
다음 단계
다음으로, 모바일 애플리케이션에 모델을 래핑하는 방법을 알아봅니다.