Phát hiện đối tượng với Tensorflow 2

Hôm nay, mình sẽ tiếp tục thực hiện bài toán phát hiện đối tượng sử dụng API của Google là Tensorflow 2.

TensorFlow 2.0, được ra mắt vào tháng 10 năm 2019, cải tiến framework theo nhiều cách dựa trên phản hồi của người dùng, để dễ dàng và hiệu quả hơn khi làm việc cùng nó (ví dụ: bằng cách sử dụng các Keras API liên quan đơn giản cho việc train model). Train phân tán dễ chạy hơn nhờ vào API mới và sự hỗ trợ cho TensorFlow Lite cho phép triển khai các mô hình trên khá nhiều nền tảng khác nhau. Tuy nhiên, nếu đã viết code trên các phiên bản trước đó của TensorFlow thì bạn phải viết lại, đôi lúc 1 ít, đôi lúc cũng khá đáng kể, để tận dụng tối đa các tính năng mới của TensorFlow 2.0. (nguồn bài viết tại đây)

1.Cài đặt thư viện

Như bình thường để không ảnh hưởng đến các thư viện khác mình sẽ tạo một môi trường ảo. Các bạn có thể xem lại tại đây

Sau đó cài thư viện bằng lệnh pip. Ở đây mình cài bản mới nhất hiện tại là tensorflow 2.7

pip install tensorflow

2. Cài API object detection

Tải model tensorflow tại đây.

Sau khi tải về và giải nén chúng ta có thể tìm thấy thư mục object_detection bên trong thư mục model-master/research

Tải protobuf mới nhất tại đây. Ở đây mình dùng trên window nên chọn file protoc-3.19.1-wind64.zip.

Sau đó, giải nén thư mục vừa tải về có các thư mục con

Tiếp theo thêm đường dẫn chỉ tới thư mục bin vừa giải nén ra trong bằng cách thêm path trong environment variable.

Sau khi thêm chỉ đến thư mục bin, chúng ta mở của sổ command line đến thư mục model-master/research chạy lệnh :

protoc object_detection/protos/*.proto --python_out=.

Copy file setup.py trong thư mục object_detection/packages/tf2 đến thư mục research và chạy lệnh có thể mất vài phút

python -m pip install --use-feature=2020-resolver .

Kiếm tra object detection đã cài đặt thành công chưa, kết quả như dưới đây.

python object_detection/builders/model_builder_tf2_test.py

3. Training

Đầu tiên chuẩn bị data train các bạn xem lại bài trước của mình tại đây Dữ liệu hôm nay mình sử dụng là pistol dataset.

Tạo file labelmap cho dataset

item {
    id: 1
    name: 'pistol'
}

Sau khi phân chia dữ liệu và tạo file record

Download model đã được train trước tesorflow 2 model zoo. Mình sẽ chọn SSD ResNet50 V1 FPN 640×640 để train.

Giải nén thư mục đã tải về và thay đổi đường dẫn chỉ đến dataset .

Bây giờ chúng ta sẽ chỉnh sửa file pipeline.config ( các dòng màu xanh).

model {
  ssd {
    num_classes: 1   # số class train
    image_resizer {
      fixed_shape_resizer {
        height: 640
        width: 640
      }
    }
    feature_extractor {
      type: "ssd_resnet50_v1_fpn_keras"
      depth_multiplier: 1.0
      min_depth: 16
      conv_hyperparams {
        regularizer {
          l2_regularizer {
            weight: 0.00039999998989515007
          }
        }
        initializer {
          truncated_normal_initializer {
            mean: 0.0
            stddev: 0.029999999329447746
          }
        }
        activation: RELU_6
        batch_norm {
          decay: 0.996999979019165
          scale: true
          epsilon: 0.0010000000474974513
        }
      }
      override_base_feature_extractor_hyperparams: true
      fpn {
        min_level: 3
        max_level: 7
      }
    }
    box_coder {
      faster_rcnn_box_coder {
        y_scale: 10.0
        x_scale: 10.0
        height_scale: 5.0
        width_scale: 5.0
      }
    }
    matcher {
      argmax_matcher {
        matched_threshold: 0.5
        unmatched_threshold: 0.5
        ignore_thresholds: false
        negatives_lower_than_unmatched: true
        force_match_for_each_row: true
        use_matmul_gather: true
      }
    }
    similarity_calculator {
      iou_similarity {
      }
    }
    box_predictor {
      weight_shared_convolutional_box_predictor {
        conv_hyperparams {
          regularizer {
            l2_regularizer {
              weight: 0.00039999998989515007
            }
          }
          initializer {
            random_normal_initializer {
              mean: 0.0
              stddev: 0.009999999776482582
            }
          }
          activation: RELU_6
          batch_norm {
            decay: 0.996999979019165
            scale: true
            epsilon: 0.0010000000474974513
          }
        }
        depth: 256
        num_layers_before_predictor: 4
        kernel_size: 3
        class_prediction_bias_init: -4.599999904632568
      }
    }
    anchor_generator {
      multiscale_anchor_generator {
        min_level: 3
        max_level: 7
        anchor_scale: 4.0
        aspect_ratios: 1.0
        aspect_ratios: 2.0
        aspect_ratios: 0.5
        scales_per_octave: 2
      }
    }
    post_processing {
      batch_non_max_suppression {
        score_threshold: 9.99999993922529e-09
        iou_threshold: 0.6000000238418579
        max_detections_per_class: 100
        max_total_detections: 100
        use_static_shapes: false
      }
      score_converter: SIGMOID
    }
    normalize_loss_by_num_matches: true
    loss {
      localization_loss {
        weighted_smooth_l1 {
        }
      }
      classification_loss {
        weighted_sigmoid_focal {
          gamma: 2.0
          alpha: 0.25
        }
      }
      classification_weight: 1.0
      localization_weight: 1.0
    }
    encode_background_as_zeros: true
    normalize_loc_loss_by_codesize: true
    inplace_batchnorm_update: true
    freeze_batchnorm: false
  }
}
train_config {
  batch_size: 2  
# tăng/giảm tùy theo cấu hình máy tính, máy của mình cùi vãi :v
  data_augmentation_options {
    random_horizontal_flip {
    }
  }
  data_augmentation_options {
    random_crop_image {
      min_object_covered: 0.0
      min_aspect_ratio: 0.75
      max_aspect_ratio: 3.0
      min_area: 0.75
      max_area: 1.0
      overlap_thresh: 0.0
    }
  }
  sync_replicas: true
  optimizer {
    momentum_optimizer {
      learning_rate {
        cosine_decay_learning_rate {
          learning_rate_base: 0.03999999910593033
          total_steps: 25000
          warmup_learning_rate: 0.013333000242710114
          warmup_steps: 2000
        }
      }
      momentum_optimizer_value: 0.8999999761581421
    }
    use_moving_average: false
  }
  fine_tune_checkpoint:"ssd_resnet50_v1_fpn/checkpoint/ckpt-0"
  num_steps: 25000
  startup_delay_steps: 0.0
  replicas_to_aggregate: 8
  max_number_of_boxes: 100
  unpad_groundtruth_tensors: false
  fine_tune_checkpoint_type: "detection"
  use_bfloat16: false
  fine_tune_checkpoint_version: V2
}
train_input_reader {
  label_map_path: "pistol_dataset/labelmap.pbtxt"
  tf_record_input_reader {
    input_path: "pistol_dataset/train.record"
  }
}
eval_config {
  metrics_set: "coco_detection_metrics"
  use_moving_averages: false
}
eval_input_reader {
  label_map_path: "pistol_dataset/labelmap.pbtxt"
  shuffle: false
  num_epochs: 1
  tf_record_input_reader {
    input_path: "pistol_dataset/test.record"
  }
}

Sau đó các tìm file model_main_tf2.py trong thư mục research/object_detection và chạy lệnh sau :

python model_main_tf2.py 
--model_dir=models/ssd_resnet50_v1_fpn 
-pipeline_config_path=models/ssd_resnet50_v1_fpn/pipeline.config
Checkpoint train

Export model đã được train

Tìm file exporter_main_v2.py trong thư mục object_detection và chạy lệnh sau:

python exporter_main_v2.py 
--input_type image_tensor 
--pipeline_config_path ssd_resnet50_v1_fpn/pipeline.config 
--trained_checkpoint_dir thư_mục_lưu_checkpoint
--output_directory output_dir
output sau khi export

Test model

import time
import tensorflow as tf
from object_detection.utils import label_map_util
from object_detection.utils import visualization_utils as viz_utils
import numpy as np
import warnings
import cv2
import os

warnings.filterwarnings('ignore')  # Suppress Matplotlib warnings


PATH_TO_SAVED_MODEL = r"my_model/saved_model"
PATH_TO_LABELS = r"labelmap.pbtxt"
print('Loading model...', end='')
start_time = time.time()

# Load saved model and build the detection function
detect_fn = tf.saved_model.load(PATH_TO_SAVED_MODEL)

end_time = time.time()
elapsed_time = end_time - start_time
print('Done! Took {} seconds'.format(elapsed_time))

category_index = label_map_util.create_category_index_from_labelmap(PATH_TO_LABELS,
                                                                    use_display_name=True)

for img in os.scandir(r"img/test_model"):
    image_np = cv2.imread(img.path)

    #     np.mean(image_np, 2, keepdims=True), (1, 1, 3)).astype(np.uint8)

    # The input needs to be a tensor, convert it using `tf.convert_to_tensor`.
    input_tensor = tf.convert_to_tensor(image_np)
    # The model expects a batch of images, so add an axis with `tf.newaxis`.
    input_tensor = input_tensor[tf.newaxis, ...]

    # input_tensor = np.expand_dims(image_np, 0)
    detections = detect_fn(input_tensor)

    # All outputs are batches tensors.
    # Convert to numpy arrays, and take index [0] to remove the batch dimension.
    # We're only interested in the first num_detections.
    num_detections = int(detections.pop('num_detections'))
    detections = {key: value[0, :num_detections].numpy()
                  for key, value in detections.items()}
    detections['num_detections'] = num_detections

    # detection_classes should be ints.
    detections['detection_classes'] = detections['detection_classes'].astype(np.int64)

    image_np_with_detections = image_np.copy()

    viz_utils.visualize_boxes_and_labels_on_image_array(
        image_np_with_detections,
        detections['detection_boxes'],
        detections['detection_classes'],
        detections['detection_scores'],
        category_index,
        use_normalized_coordinates=True,
        max_boxes_to_draw=200,
        min_score_thresh=.30,
        agnostic_mode=False)

    cv2.imshow("output", image_np_with_detections)
    cv2.waitKey(0)
Output1

Output 2

Output 3

Tài liệu tham khảo

https://tensorflow-object-detection-api-tutorial.readthedocs.io/en/latest/install.html#tf-models-install

https://tensorflow-object-detection-api-tutorial.readthedocs.io/en/latest/training.html

https://tensorflow-object-detection-api-tutorial.readthedocs.io/en/latest/auto_examples/plot_object_detection_checkpoint.html#load-the-model

One thought on “Phát hiện đối tượng với Tensorflow 2

Bình luận về bài viết này

Tạo trang giống vầy với WordPress.com
Tham gia