728x90
반응형
!git clone --depth 1 https://github.com/google/automl

 

!cd /content/automl/efficientdet; pip install -r requirements.txt

 

 

import tensorflow as tf
print(tf.__version__)

# 2.7.0

 

!nvidia-smi

Tue Nov 30 09:31:28 2021       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 495.44       Driver Version: 460.32.03    CUDA Version: 11.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla K80           Off  | 00000000:00:04.0 Off |                    0 |
| N/A   36C    P8    28W / 149W |      0MiB / 11441MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|  No running processes found                                                 |
+-----------------------------------------------------------------------------+

 

efficientdet 수행을 위한 Library path 설정.

import os
import sys
import tensorflow.compat.v1 as tf

 

sys.path.append('/content/automl/efficientdet')

 

# /content/automl/efficient 으로 library path가 정상적으로 잡히면 아래 모듈 import가 되어야함. 
import hparams_config
from tf2 import anchors # keras folder가 tf2로 변경됨
from model_inspect import ModelInspector

COCO 데이터로 Pretrained된 efficientdet-d0 모델을 다운로드

MODEL = 'efficientdet-d0' 

def download(m):
  if m not in os.listdir():
    !wget https://storage.googleapis.com/cloud-tpu-checkpoints/efficientdet/coco/{m}.tar.gz
    !tar zxf {m}.tar.gz
  ckpt_path = os.path.join(os.getcwd(), m)
  return ckpt_path

# Download checkpoint.
ckpt_path = download(MODEL)
print('Use model in {}'.format(ckpt_path))

Use model in /content/efficientdet-d0

 

!mkdir ./data
!wget -O ./data/img01.png https://user-images.githubusercontent.com/11736571/77320690-099af300-6d37-11ea-9d86-24f14dc2d540.png

 

import cv2
import matplotlib.pyplot as plt

image_array = cv2.cvtColor(cv2.imread('/content/data/img01.png'), cv2.COLOR_BGR2RGB)
print(image_array.shape)

plt.figure(figsize=(12, 12))
plt.imshow(image_array)

# (1080, 1920, 3)

Pretrained efficientdet 모델로 Inference 를 수행하기 위한 환경 설정

  • hparams_config.Config 객체를 통해 모델 환경 설정.
class INFER_CFG:
  model_name = 'efficientdet-d0' # efficientdet 모델명
  model_dir = '/content/efficientdet-d0' # pretrained checkpoint 파일이 있는 디렉토리
  hparams = '' # csv 형식의 k=v 쌍 또는 yaml file

 

import numpy as np
from PIL import Image
import tensorflow as tf

import hparams_config
import inference
from tf2 import efficientdet_keras # keras 를 tf2로 변경

 

#efficientdet-d0의 기본 config 확인. 
config = hparams_config.get_efficientdet_config(INFER_CFG.model_name)
print('config type:', type(config))
print(config)


# config 객체, model parameter 등 정보들
config type: <class 'hparams_config.Config'> 
act_type: swish
alpha: 0.25
anchor_scale: 4.0
apply_bn_for_resampling: true
aspect_ratios:
- 1.0
- 2.0
- 0.5
autoaugment_policy: null
backbone_config: null
backbone_name: efficientnet-b0
box_class_repeats: 3
box_loss_weight: 50.0
ckpt_var_scope: null
clip_gradients_norm: 10.0
conv_after_downsample: false
conv_bn_act_pattern: false
data_format: channels_last
dataset_type: null
delta: 0.1
drop_remainder: true
first_lr_drop_epoch: 200.0
fpn_cell_repeats: 3
fpn_config: null
fpn_name: null
fpn_num_filters: 64
fpn_weight_method: null
gamma: 1.5
grad_checkpoint: false
grid_mask: false
heads:
- object_detection
image_size: 512
img_summary_steps: null
input_rand_hflip: true
iou_loss_type: null
iou_loss_weight: 1.0
is_training_bn: true
jitter_max: 2.0
jitter_min: 0.1
label_map: null
label_smoothing: 0.0
learning_rate: 0.08
loss_scale: null
lr_decay_method: cosine
lr_warmup_epoch: 1.0
lr_warmup_init: 0.008
map_freq: 5
max_instances_per_image: 100
max_level: 7
mean_rgb:
- 123.675
- 116.28
- 103.53
min_level: 3
mixed_precision: false
model_optimizations: {}
momentum: 0.9
moving_average_decay: 0.9998
name: efficientdet-d0
nms_configs:
    iou_thresh: null
    max_nms_inputs: 0
    max_output_size: 100
    method: gaussian
    pyfunc: false
    score_thresh: 0.0
    sigma: null
num_classes: 90
num_epochs: 300
num_scales: 3
optimizer: sgd
poly_lr_power: 0.9
positives_momentum: null
regenerate_source_id: false
sample_image: null
save_freq: epoch
scale_range: false
second_lr_drop_epoch: 250.0
seg_num_classes: 3
separable_conv: true
skip_crowd_during_training: true
skip_mismatch: true
stddev_rgb:
- 58.395
- 57.120000000000005
- 57.375
strategy: null
survival_prob: null
target_size: null
tflite_max_detections: 100
use_keras_model: true
var_freeze_expr: null
verbose: 1
weight_decay: 4.0e-05

 

# config의 특정 항목을 update
config.is_training_bn = False # batch_normalization 옵션인데 학습이 아닌 inference라서 false
#config.image_size = '1920x1280'
config.nms_configs.score_thresh = 0.4 # nms의 threshold filtering 0.4이하는 아웃시킴
config.nms_configs.max_output_size = 100

config.override(INFER_CFG.hparams)

Pretrained 모델 생성 후 Inference 수행

  • config인자로 하여 EfficientDetModel생성
  • 만들어진 모델에 다운로드 된 Pretrained Weight 파일의 weight값을 model.load_weights()로 입력
INFER_CFG.model_dir

/content/efficientdet-d0

 

import inference
from tf2 import efficientdet_keras # keras를 tf2로 변경

# 빈 모델,random weight 상태
model = efficientdet_keras.EfficientDetModel(config=config)
model.build((None, None, None, 3)) # input layer가 개수, h,w가 정해지지 않음, 채널은 3
print('#### checkpoint name:', tf.train.latest_checkpoint(INFER_CFG.model_dir))
# load_weight로 weights 채움
model.load_weights(tf.train.latest_checkpoint(INFER_CFG.model_dir))
model.summary()

Model: ""
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 efficientnet-b0 (Model)     multiple                  3634844    # backbone : b1 
                                                                 
 resample_p6 (ResampleFeatur  multiple                 20800     # neck : BiFPN
 eMap)                                                           
                                                                 
 resample_p7 (ResampleFeatur  multiple                 0         
 eMap)                                                           
                                                                 
 fpn_cells (FPNCells)        multiple                  179321    
                                                                 
 class_net (ClassNet)        multiple                  71274     # head 
                                                                 
 box_net (BoxNet)            multiple                  20964     
                                                                 
=================================================================
Total params: 3,927,203
Trainable params: 3,880,067
Non-trainable params: 47,136
_________________________________________________________________

입력

from PIL import Image
import cv2

# image는 4차원 array, Tensor 모두 가능.  
imgs = [np.array(Image.open('/content/data/img01.png'))]
imgs = tf.convert_to_tensor(imgs, dtype=tf.uint8)

### 아래와 같이 numpy array도 모델에 입력되는 이미지 값으로 가능. 
''' 
img = cv2.cvtColor(cv2.imread('/content/data/img01.png'), cv2.COLOR_BGR2RGB)
imgs= img[np.newaxis, ...]
boxes, scores, classes, valid_len = model(imgs, training=False, post_mode='global')
'''
print()

 

import time

# Inference 수행하고 수행 시간을 측정. 
start_time = time.time()
boxes, scores, classes, valid_len = model(imgs, training=False, post_mode='global')
print('elapsed time:', time.time() - start_time)


/content/automl/efficientdet/utils.py:255: UserWarning: `layer.updates` will be removed in a future version. This property should not be used in TensorFlow 2.0, as `updates` are applied automatically.
  for u in self.updates:
elapsed time: 7.936372518539429

Inference 반환 결과 살펴보고 API로 시각화 하기

  • inference model에 image tensor를 입력하여 반환된 결과는 모두 tensor이며, bounding box의 좌표, confidence score, class id 값, valid한 갯수가 반환됨.
  • config에 max_instances_per_image이 100으로 설정되었으므로 기본적으로 inference결과는 100개의 object들의 Detection 결과를 가지게 됨.
  • 이들 중 valid한 갯수(valid_len)은 이들중 의미있는 object detection 갯수를 의미함.(0 부터 valid_len-1 까지의 index를 가진 array결과가 의미있는 detection 결과임)
  • inference.visualize_image()로 반화 결과를 입력하여 시각화 적용
boxes

<tf.Tensor: shape=(1, 100, 4), dtype=float32, numpy=
array([[[ 898.7691   , 1250.5381   , 1078.944    , 1593.3597   ],
        [ 485.65512  , 1178.6895   ,  613.15283  , 1317.9205   ],
        [ 620.43     , 1313.1947   ,  905.7822   , 1625.1599   ],
        [ 870.51105  ,  490.04422  , 1078.4515   ,  778.78973  ],
        [ 505.97702  , 1356.5035   ,  636.8839   , 1533.2777   ],
        [ 628.0882   ,  211.97603  ,  842.73444  ,  485.74365  ],
        [ 648.43634  , 1553.6306   ,  911.2138   , 1901.6282   ],
        [ 875.3995   ,    3.3257744, 1039.7441   ,  182.6283   ],
        [ 925.4872   ,  301.89096  , 1075.1144   ,  460.31177  ],
        [ 619.0373   ,  873.7107   ,  927.9857   , 1069.7871   ],
        [ 351.75012  ,  582.6734   ,  511.38934  ,  738.4224   ],
        [ 690.2022   , 1238.6897   ,  860.37756  , 1316.6832   ],
        [ 677.63     , 1087.3639   ,  835.46027  , 1159.2014   ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ],
        [ 677.3427   , 1864.105    ,  759.21936  , 1864.105    ]]],
      dtype=float32)>

ㄴ> 있든 없든 max_instances_per_image 100개를 다 채우려고 중복값이 나옴

valid_len이 13임

 

print(valid_len.numpy())
boxes.shape, scores.shape, classes.shape

# [13]
# (TensorShape([1, 100, 4]), TensorShape([1, 100]), TensorShape([1, 100]))

 

scores

<tf.Tensor: shape=(1, 100), dtype=float32, numpy=
array([[0.84579366, 0.6978561 , 0.68892914, 0.6842166 , 0.67942005,
        0.6492443 , 0.61395675, 0.484145  , 0.44828248, 0.43981278,
        0.41531536, 0.41527689, 0.41297233, 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ,
        0.        , 0.        , 0.        , 0.        , 0.        ]],
      dtype=float32)>

object는 13개보다 많을 수 있는데 필터링을 0.4 초과인 것만 찾아낸 것임

 

print('##bboxes:', boxes[0, :10], '\n##scores:', scores[0, :10], '\n##classes:', classes[0, :10])

##bboxes: tf.Tensor(
[[ 898.7691    1250.5381    1078.944     1593.3597   ]
 [ 485.65512   1178.6895     613.15283   1317.9205   ]
 [ 620.43      1313.1947     905.7822    1625.1599   ]
 [ 870.51105    490.04422   1078.4515     778.78973  ]
 [ 505.97702   1356.5035     636.8839    1533.2777   ]
 [ 628.0882     211.97603    842.73444    485.74365  ]
 [ 648.43634   1553.6306     911.2138    1901.6282   ]
 [ 875.3995       3.3257744 1039.7441     182.6283   ]
 [ 925.4872     301.89096   1075.1144     460.31177  ]
 [ 619.0373     873.7107     927.9857    1069.7871   ]], shape=(10, 4), dtype=float32) 
##scores: tf.Tensor(
[0.84579366 0.6978561  0.68892914 0.6842166  0.67942005 0.6492443
 0.61395675 0.484145   0.44828248 0.43981278], shape=(10,), dtype=float32) 
##classes: tf.Tensor([3. 3. 3. 3. 3. 3. 3. 4. 4. 3.], shape=(10,), dtype=float32)

 

!mkdir -p /content/data_output

 

for i, img in enumerate(imgs):
  length = valid_len[i]
  
  img = inference.visualize_image(
      img,
      boxes[i].numpy()[:length],
      classes[i].numpy().astype(np.int)[:length],
      scores[i].numpy()[:length],
      label_map=config.label_map,
      min_score_thresh=config.nms_configs.score_thresh,
      max_boxes_to_draw=config.nms_configs.max_output_size)
  
  output_image_path = os.path.join('/content/data_output', str(i) + '.jpg')
  Image.fromarray(img).save(output_image_path)
  print('writing annotated image to %s' % output_image_path)
  
  writing annotated image to /content/data_output/0.jpg

 

Static Graph mode(Non eager mode)로 Inference 수행 성능 향상 시키기

  • @tf.function을 이용하여 static mode로 inference를 수행할 수 있도록 ExportModel 클래스 생성
  • inference 수행 시 ExportModel의 @tf.function이 적용된 메소드를 호출할 수 있도록 함.
import time

class ExportModel(tf.Module):

  def __init__(self, model):
    super().__init__()
    self.model = model

  @tf.function
  def f(self, imgs):
    #model(imgs, training=False, post_mode='global')
    return self.model(imgs, training=False, post_mode='global')

export_model = ExportModel(model)

 

# p100에서 image 1920x1280일 경우 74ms, v100에서 image 512x512일 경우 24ms

start_time = time.time()
boxes, scores, classes, valid_len = export_model.f(imgs)

print('elapsed time:', time.time() - start_time)

/content/automl/efficientdet/utils.py:23: UserWarning: `layer.updates` will be removed in a future version. This property should not be used in TensorFlow 2.0, as `updates` are applied automatically.
  from tensorflow.python.tpu import tpu_function  # pylint:disable=g-direct-tensorflow-import
/content/automl/efficientdet/utils.py:255: UserWarning: `layer.updates` will be removed in a future version. This property should not be used in TensorFlow 2.0, as `updates` are applied automatically.
  for u in self.updates:
elapsed time: 8.002159118652344

시각화 함수 생성하고 inference 결과를 시각화

labels_to_names = {1:'person',2:'bicycle',3:'car',4:'motorcycle',5:'airplane',6:'bus',7:'train',8:'truck',9:'boat',10:'traffic light',
                    11:'fire hydrant',12:'street sign',13:'stop sign',14:'parking meter',15:'bench',16:'bird',17:'cat',18:'dog',19:'horse',20:'sheep',
                    21:'cow',22:'elephant',23:'bear',24:'zebra',25:'giraffe',26:'hat',27:'backpack',28:'umbrella',29:'shoe',30:'eye glasses',
                    31:'handbag',32:'tie',33:'suitcase',34:'frisbee',35:'skis',36:'snowboard',37:'sports ball',38:'kite',39:'baseball bat',40:'baseball glove',
                    41:'skateboard',42:'surfboard',43:'tennis racket',44:'bottle',45:'plate',46:'wine glass',47:'cup',48:'fork',49:'knife',50:'spoon',
                    51:'bowl',52:'banana',53:'apple',54:'sandwich',55:'orange',56:'broccoli',57:'carrot',58:'hot dog',59:'pizza',60:'donut',
                    61:'cake',62:'chair',63:'couch',64:'potted plant',65:'bed',66:'mirror',67:'dining table',68:'window',69:'desk',70:'toilet',
                    71:'door',72:'tv',73:'laptop',74:'mouse',75:'remote',76:'keyboard',77:'cell phone',78:'microwave',79:'oven',80:'toaster',
                    81:'sink',82:'refrigerator',83:'blender',84:'book',85:'clock',86:'vase',87:'scissors',88:'teddy bear',89:'hair drier',90:'toothbrush',
                    91:'hair brush'}

 

def get_detected_img(export_model, img_array, is_print=True):   
  # automl efficent은 반환 bbox 좌표값이 원본 이미지 좌표값으로 되어 있으므로 별도의 scaling작업 필요 없음. 
  '''
  height = img_array.shape[0]
  width = img_array.shape[1]
  '''
  # cv2의 rectangle()은 인자로 들어온 이미지 배열에 직접 사각형을 업데이트 하므로 그림 표현을 위한 별도의 이미지 배열 생성. 
  draw_img = img_array.copy()

  # bounding box의 테두리와 caption 글자색 지정
  green_color=(0, 255, 0)
  red_color=(0, 0, 255)

  # cv2로 만들어진 numpy image array를 tensor로 변환
  img_tensor = tf.convert_to_tensor(img_array, dtype=tf.uint8)[tf.newaxis, ...]
  #img_tensor = tf.convert_to_tensor(img_array, dtype=tf.float32)[tf.newaxis, ...]

  # efficientdet 모델을 다운로드 한 뒤 inference 수행. 
  start_time = time.time()
  # automl efficientdet 모델은 boxes, score, classes, num_detections를 각각 Tensor로 반환. 
  boxes, scores, classes, valid_len = export_model.f(img_tensor)
  # Tensor값을 시각화를 위해 numpy 로 변환. 
  boxes = boxes.numpy()
  scores = scores.numpy()
  classes = classes.numpy()
  valid_len = valid_len.numpy()
  
  # detected 된 object들을 iteration 하면서 정보 추출. detect된 object의 갯수는 100개
  for i in range(valid_len[0]):
    # detection score를 iteration시 마다 높은 순으로 추출하고 SCORE_THRESHOLD보다 낮으면 loop 중단. 
    score = scores[0, i]
    
    # detected된 object들은 scale된 기준으로 예측되었으므로 다시 원본 이미지 비율로 계산
    box = boxes[0, i]

    ''' **** 주의 ******
    box는 ymin, xmin, ymax, xmax 순서로 되어 있음. 또한 원본 좌표값으로 되어 있음. '''
    left = box[1]
    top = box[0] 
    right = box[3] 
    bottom = box[2] 

    # class id 추출하고 class 명으로 매핑
    class_id = classes[0, i]
    caption = "{}: {:.4f}".format(labels_to_names[class_id], score)
    print(caption)
    #cv2.rectangle()은 인자로 들어온 draw_img에 사각형을 그림. 위치 인자는 반드시 정수형.
    cv2.rectangle(draw_img, (int(left), int(top)), (int(right), int(bottom)), color=green_color, thickness=2)
    cv2.putText(draw_img, caption, (int(left), int(top - 5)), cv2.FONT_HERSHEY_SIMPLEX, 0.4, red_color, 1)

  if is_print:
    print('Detection 수행시간:',round(time.time() - start_time, 2),"초")

  return draw_img

 

 

import cv2
img_array = cv2.cvtColor(cv2.imread('/content/data/img01.png'), cv2.COLOR_BGR2RGB)

draw_img = get_detected_img(export_model, img_array, is_print=True)
plt.figure(figsize=(16, 16))
plt.imshow(draw_img)

car: 0.8458
car: 0.6979
car: 0.6889
car: 0.6842
car: 0.6794
car: 0.6492
car: 0.6140
motorcycle: 0.4841
motorcycle: 0.4483
car: 0.4398
bus: 0.4153
person: 0.4153
motorcycle: 0.4130
Detection 수행시간: 0.08 초

 

!wget -O ./data/beatles01.jpg https://raw.githubusercontent.com/chulminkw/DLCV/master/data/image/beatles01.jpg
!wget -O ./data/baseball01.jpg https://raw.githubusercontent.com/chulminkw/DLCV/master/data/image/baseball01.jpg

 

import cv2
img_array = cv2.cvtColor(cv2.imread('/content/data/beatles01.jpg'), cv2.COLOR_BGR2RGB)
print(img_array.shape)

draw_img = get_detected_img(export_model, img_array, is_print=True)
plt.figure(figsize=(12, 12))
plt.imshow(draw_img)

(633, 806, 3)
/content/automl/efficientdet/utils.py:23: UserWarning: `layer.updates` will be removed in a future version. This property should not be used in TensorFlow 2.0, as `updates` are applied automatically.
  from tensorflow.python.tpu import tpu_function  # pylint:disable=g-direct-tensorflow-import
/content/automl/efficientdet/utils.py:255: UserWarning: `layer.updates` will be removed in a future version. This property should not be used in TensorFlow 2.0, as `updates` are applied automatically.
  for u in self.updates:
person: 0.9486
person: 0.9406
person: 0.9362
person: 0.8914
car: 0.6025
car: 0.5251
Detection 수행시간: 4.61 초

 

반응형

+ Recent posts