# DeepLabV3+ Utilities import io import base64 import numpy as np import matplotlib.pyplot as plt def show_images(data, model=None, explain=False, n_images=5, SIZE=(15, 5)): """ 이미지와 마스크 시각화 Args: data: tf.data.Dataset (images, masks) 형태 model: 예측에 사용할 모델 (선택) explain: True면 예측 결과도 표시 n_images: 표시할 이미지 수 SIZE: 그림 크기 (width, height) """ # Get batch from dataset for images, masks in data.take(1): images = images.numpy() masks = masks.numpy() # Limit number of images n_images = min(n_images, len(images)) if explain and model is not None: # Show Image, Mask, and Prediction fig, axes = plt.subplots(n_images, 3, figsize=SIZE) predictions = model.predict(images[:n_images]) for i in range(n_images): # Original Image axes[i, 0].imshow(images[i]) axes[i, 0].set_title("Image") axes[i, 0].axis('off') # Ground Truth Mask axes[i, 1].imshow(masks[i]) axes[i, 1].set_title("Mask (GT)") axes[i, 1].axis('off') # Predicted Mask axes[i, 2].imshow(predictions[i]) axes[i, 2].set_title("Prediction") axes[i, 2].axis('off') else: # Show only Image and Mask fig, axes = plt.subplots(n_images, 2, figsize=SIZE) for i in range(n_images): # Original Image axes[i, 0].imshow(images[i]) axes[i, 0].set_title("Image") axes[i, 0].axis('off') # Ground Truth Mask axes[i, 1].imshow(masks[i]) axes[i, 1].set_title("Mask") axes[i, 1].axis('off') plt.tight_layout() plt.show() def show_single_prediction(model, image): """ 단일 이미지 예측 시각화 Args: model: 학습된 DeepLabV3+ 모델 image: 입력 이미지 (numpy array) """ # Ensure correct shape if len(image.shape) == 3: image = np.expand_dims(image, axis=0) # Predict prediction = model.predict(image)[0] # Visualize fig, axes = plt.subplots(1, 2, figsize=(10, 5)) axes[0].imshow(image[0]) axes[0].set_title("Input Image") axes[0].axis('off') axes[1].imshow(prediction) axes[1].set_title("Prediction") axes[1].axis('off') plt.tight_layout() plt.show() def prediction_to_base64(model, image): """ 예측 결과를 base64 이미지로 변환 Args: model: 학습된 DeepLabV3+ 모델 image: 입력 이미지 (numpy array) Returns: base64 인코딩된 이미지 문자열 """ # Ensure correct shape if len(image.shape) == 3: image = np.expand_dims(image, axis=0) # Predict prediction = model.predict(image)[0] # Create figure fig, axes = plt.subplots(1, 2, figsize=(10, 5)) axes[0].imshow(image[0]) axes[0].set_title("Input Image") axes[0].axis('off') axes[1].imshow(prediction) axes[1].set_title("Water Body Prediction") axes[1].axis('off') plt.tight_layout() # Convert to base64 buf = io.BytesIO() plt.savefig(buf, format='png', bbox_inches='tight', dpi=100) buf.seek(0) img_base64 = base64.b64encode(buf.getvalue()).decode('utf-8') plt.close(fig) return img_base64 def mask_to_binary(mask, threshold=0.5): """ 마스크를 이진화 Args: mask: 예측 마스크 threshold: 이진화 임계값 Returns: 이진화된 마스크 """ return (mask > threshold).astype(np.uint8) def calculate_iou(pred_mask, true_mask, threshold=0.5): """ IoU (Intersection over Union) 계산 Args: pred_mask: 예측 마스크 true_mask: 실제 마스크 threshold: 이진화 임계값 Returns: IoU 값 """ pred_binary = mask_to_binary(pred_mask, threshold) true_binary = mask_to_binary(true_mask, threshold) intersection = np.logical_and(pred_binary, true_binary).sum() union = np.logical_or(pred_binary, true_binary).sum() if union == 0: return 1.0 return intersection / union