Cheat sheet phát hiện đối tượng

Gần đây, tôi muốn xây dựng một hệ thống để phát hiện các đối tượng trong một số dữ liệu hình ảnh. Vì vậy, tôi bắt đầu tìm hiểu Mạng thần kinh chuyển đổi dựa trên khu vực (RCNN) và đó là sự phát triển, mô hình CNN đã có sẵn, v.v. Đối với tôi, nó rất khó nắm bắt vì có nhiều thuật ngữ mới xuất hiện trong các bài đọc tham khảo

Vì vậy, để khắc phục điều này, tôi đã xây dựng tất cả các thuật ngữ đặc biệt xuất hiện trong bài đọc tham khảo của mình.

  1. CNN là một mạng thần kinh có một lớp đặc biệt là lớp tích chập (và lớp tổng hợp). Trong mô hình CNN thông thường, lớp cuối cùng thường là lớp dày đặc
  2. RCNN là một CNN đặc biệt và là thế hệ mô hình RCNN đầu tiên sử dụng thuật toán tìm kiếm chọn lọc để đề xuất một số hộp giới hạn bao phủ đối tượng mà chúng tôi muốn phát hiện. Đầu tiên, chúng tôi áp dụng thuật toán tìm kiếm có chọn lọc để lấy một số hộp giới hạn (đề xuất khu vực). Và sau đó, đưa các khu vực được đề xuất đó vào mô hình CNN
  3. Fast-RCNN là thế hệ thứ hai của mô hình RCNN. Mô hình này nhanh hơn RCNN (Fast-RCNN > RCNN). Hình ảnh đầu vào ban đầu được đưa vào mô hình CNN để thực hiện trích xuất tính năng. Sau đó, chúng tôi sử dụng tìm kiếm có chọn lọc để nhận đề xuất khu vực và đưa chúng vào Lớp Vùng quan tâm (RoI) để cố định kích thước ma trận của chúng (khu vực được đề xuất có nhiều hình dạng có thể). Sau khi chúng có kích thước cố định, hãy đưa chúng vào lớp dày đặc để dự đoán lớp đó và xác định hộp giới hạn
  4. Faster-RCNN là thế hệ thứ ba của mô hình RCNN. Mô hình này nhanh hơn Fast-RCNN (Faster-RCNN > Fast-RCNN > RCNN). Mô hình này loại bỏ việc sử dụng các thuật toán tìm kiếm chọn lọc chậm. Để nhận đề xuất khu vực, chúng tôi sử dụng Mạng đề xuất khu vực (RPN)
  5. Trích xuất tính năng là để đạt được đầu ra của lớp cuối cùng của mô hình CNN thông thường trước lớp dày đặc (hoặc lớp trước đó)
  6. Bản đồ tính năng là ma trận kết quả từ trích xuất tính năng
  7. Tìm kiếm chọn lọc là một thuật toán đề xuất hoạt động bằng cách phân đoạn quá mức hình ảnh dựa trên cường độ của pixel bằng phương pháp phân đoạn dựa trên biểu đồ
  8. Lớp RoI là lớp tổng hợp đặc biệt để làm cho kích thước vùng được đề xuất khớp với lớp dày đặc tiếp theo của mạng thần kinh
  9. RPN là một mạng thần kinh có 2 đầu. Một để phân loại nền hoặc tiền cảnh và cái còn lại để xác định vùng hộp giới hạn
  10. Anchor là trung tâm của khu vực được đề xuất trong Faster-RCNN
  11. Giao lộ trên Liên minh (IoU) là thước đo đánh giá các đề xuất khu vực. Nó được hình thành dưới dạng diện tích chồng lấn / diện tích hợp nhất
  12. Non Maximum Suppression là một cách để đảm bảo một đối tượng chỉ được phát hiện một lần. Điều này được thực hiện bằng cách áp dụng một số ngưỡng

Tôi sẽ bổ sung danh sách này trong tương lai nếu tôi tìm thấy các thuật ngữ mới liên quan đến phát hiện đối tượng trong Deep Learning

Người giới thiệu

https. // hướng tới khoa học dữ liệu. com/r-cnn-fast-r-cnn-faster-r-cnn-yolo-object-detection-algorithms-36d53571365e, truy cập ngày 3 tháng 2 năm 2019

https. //www. họcopencv. com/selective-search-for-object-detection-cpp-python/, truy cập ngày 3 tháng 2 năm 2019

https. //thử nghiệm. com/blog/2018/01/18/faster-r-cnn-down-the-rabbit-hole-of-modern-object-detection/, truy cập ngày 3 tháng 2 năm 2019

Khi làm việc trong Object Detection, đã bao giờ bạn hí hửng tải mô hình đã được huấn luyện sẵn về rồi phát hiện ra mô hình không có đối tượng mà bạn cần?

Đối với những trường hợp này thì có lẽ không còn cách nào khác, chúng ta phải huấn luyện mô hình cấu hình với tệp dữ liệu mới. May mắn cho chúng ta là việc huấn luyện mô hình trên tập dữ liệu mới ngày càng trở nên dễ dàng

Cheat sheet phát hiện đối tượng

Hãy cùng tìm hiểu các bước đào tạo mô hình Phát hiện đối tượng cho một đối tượng mới, cụ thể là gấu trúc (phát hiện gấu trúc) dựa trên YOLOv5 trong bài hôm nay. Mình chọn đối tượng này, một phần là mình thích gấu trúc, một phần nữa là mình chưa thấy mô hình nào có đối tượng này. Hơn nữa, các bước xây dựng mô hình hoàn toàn có thể áp dụng cho bất kỳ đối tượng nào khác

Sơ lược về YOLOv5

YOLOv5 là một mô hình Object Detection thuộc họ mô hình YOLO. Nếu các bạn chưa biết thì 3 phiên bản YOLO đầu tiên được phát triển bởi Joseph Redmon. Sau đó, Alexey Bochkovskiy cho ra mắt YOLOv4 với sự cải thiện cả về tốc độ cũng như độ chính xác. Và rồi YOLOv5 đã được công bố gần đây với những so sánh ban đầu cho thấy mức độ chính xác tương đương với YOLOv4 và có tốc độ nhanh hơn khi thực hiện dự đoán (tuy nhiên vẫn có rất nhiều hoài nghi về mức độ tin cậy của những so sánh

Khác với các phiên bản tiền nhiệm, YOLOv5 được phát triển dựa trên PyTorch thay vì DarkNet. Đây là một điểm cộng không nhỏ đối với YOLOv5 vì PyTorch phổ biến hơn rất nhiều, điều này đồng nghĩa với việc sẽ có nhiều tài liệu và hướng dẫn cho chúng tôi tham khảo về mô hình này

Cá nhân mình đánh giá cấu trúc YOLOv5 không có nhiều thay đổi quá lớn nhưng lại được phát triển trên PyTorch và có hướng dẫn rất chi tiết và đầy đủ. Làm đó, mình chọn YOLOv5 cho bài thực hành hôm nay

Chuẩn bị dữ liệu

Trước hết chúng ta cần phải có dữ liệu ảnh và nhãn (images & label). Dữ liệu đối với mô hình cũng giống như những viên gạch để xây dựng nhà, không có dữ liệu thì không xây dựng được mô hình nào cả

Tập hợp ảnh

Có vài cách để thu thập ảnh cho việc huấn luyện mô hình

  • Tìm trên Open Images Dataset, đây là tập hợp hơn 9 triệu ảnh với 6000 nhóm khác nhau
  • Tìm kiếm với công cụ tìm kiếm (Google, Bing, …) với lưu ý cần kiểm tra kỹ năng bản quyền sử dụng ảnh
  • Trích xuất các khung hình từ Video
  • Tự chụp ảnh

Trong bài viết hôm nay, mình sử dụng thư viện năm mươi mốt để tải ảnh từ Open Images Dataset

1
2
3
4
5
6
7
dataset = fiftyone.zoo.load_zoo_dataset(
    "open-images-v6",
    split="train",
    label_types=["detections"],
    classes=["Panda"],
    max_samples=250,
)

Dữ liệu tải về sẽ có 3 thư mục, mình chỉ lấy ảnh thư mục ảnh

dataset = fiftyone.zoo.load_zoo_dataset(
    "open-images-v6",
    split="train",
    label_types=["detections"],
    classes=["Panda"],
    max_samples=250,
)
3 để thực hiện việc gán nhãn ở bước tiếp theo

.
├── data
│   ├── 02a4749df3d7a0c9.jpg
│   ├── 0b5547d4aa16e365.jpg
│   ...
├── labels
│   └── detections.csv
└── metadata
    ├── classes.csv
    ├── hierarchy.json
    └── image_ids.csv

Gán nhãn

Mình sử dụng thư viện nhãnImg cho việc gán nhãn và mất khoảng hơn 1h để gán nhãn cho khoảng 130 ảnh. (Bạn nào biết công cụ nào tiện hơn thì chia sẻ cho mình và mọi người biết nhé)

Bước gán nhãn này thường tốn nhiều thời gian và không thú vị lắm, nhưng tự nhủ không có gạch thì không xây được nhà nên cố gắng thử

Cheat sheet phát hiện đối tượng
Gán nhãn với LabelImg

Các bạn lưu ý chọn định dạng YOLO khi xuất các tệp để đảm bảo định dạng đúng cho việc huấn luyện mô hình sau này

Cheat sheet phát hiện đối tượng
To the style of the format of YOLO (Ultralytics)

Mỗi ảnh sẽ có một nhãn (tệp

dataset = fiftyone.zoo.load_zoo_dataset(
    "open-images-v6",
    split="train",
    label_types=["detections"],
    classes=["Panda"],
    max_samples=250,
)
4) tương ứng để chứa thông tin về đường bao của đối tượng

  • Mỗi dòng chứa thông tin của một đối tượng
  • Mỗi dòng có 5 giá trị chứa thông tin về đối tượng và đường bao. object, to speed center x, to speed trung tâm y, width, length
  • Lưu ý là đường bao đã được chuẩn hóa về khoảng
    dataset = fiftyone.zoo.load_zoo_dataset(
        "open-images-v6",
        split="train",
        label_types=["detections"],
        classes=["Panda"],
        max_samples=250,
    )
    
    5 (đây là yêu cầu của mô hình YOLO)

Dưới đây là ví dụ về nhãn và tệp chứa thông tin về đối tượng

Cheat sheet phát hiện đối tượng
Nhãn và tệp chứa tên các nhóm đối tượng

Sắp xếp thư mục ảnh và nhãn

Sau khi đã có ảnh và nhãn, chúng ta có thể sắp xếp các thư mục như sau

custom_dataset
├── custom_dataset.yaml
├── custom_model.yaml
└── images_and_labels

  • Cấu hình tệp của tệp dữ liệu
    dataset = fiftyone.zoo.load_zoo_dataset(
        "open-images-v6",
        split="train",
        label_types=["detections"],
        classes=["Panda"],
        max_samples=250,
    )
    
    6 chứa đường dẫn đến thư mục ảnh và đối tượng thông tin

    ________số 8

  • Tệp cấu hình của mô hình
    dataset = fiftyone.zoo.load_zoo_dataset(
        "open-images-v6",
        split="train",
        label_types=["detections"],
        classes=["Panda"],
        max_samples=250,
    )
    
    7 chứa thông tin cấu trúc mạng, ở đây chúng ta sử dụng cấu trúc mô hình YOLOv5s (cỡ nhỏ) với mục tiêu rút ngắn thời gian huấn luyện và kích thước mô hình. Lưu ý là chúng ta hoàn toàn có thể sử dụng cấu trúc khác, ví dụ như YOLOv5m, YOLOv5l, YOLOv5x từ YOLOv5 hoặc một cấu trúc mới do chúng ta tự thiết kế

    dataset = fiftyone.zoo.load_zoo_dataset(
        "open-images-v6",
        split="train",
        label_types=["detections"],
        classes=["Panda"],
        max_samples=250,
    )
    
    0

  • Thư mục
    dataset = fiftyone.zoo.load_zoo_dataset(
        "open-images-v6",
        split="train",
        label_types=["detections"],
        classes=["Panda"],
        max_samples=250,
    )
    
    8 chứa ảnh và nhãn được sử dụng để huấn luyện mô hình

    dataset = fiftyone.zoo.load_zoo_dataset(
        "open-images-v6",
        split="train",
        label_types=["detections"],
        classes=["Panda"],
        max_samples=250,
    )
    
    2

    • Thư mục
      dataset = fiftyone.zoo.load_zoo_dataset(
          "open-images-v6",
          split="train",
          label_types=["detections"],
          classes=["Panda"],
          max_samples=250,
      )
      
      9 và
      .
      ├── data
      │   ├── 02a4749df3d7a0c9.jpg
      │   ├── 0b5547d4aa16e365.jpg
      │   ...
      ├── labels
      │   └── detections.csv
      └── metadata
          ├── classes.csv
          ├── hierarchy.json
          └── image_ids.csv
      
      0 chứa ảnh và nhãn tương ứng
    • Ảnh và nhãn được chia thành 2 thư mục
      .
      ├── data
      │   ├── 02a4749df3d7a0c9.jpg
      │   ├── 0b5547d4aa16e365.jpg
      │   ...
      ├── labels
      │   └── detections.csv
      └── metadata
          ├── classes.csv
          ├── hierarchy.json
          └── image_ids.csv
      
      1 và
      .
      ├── data
      │   ├── 02a4749df3d7a0c9.jpg
      │   ├── 0b5547d4aa16e365.jpg
      │   ...
      ├── labels
      │   └── detections.csv
      └── metadata
          ├── classes.csv
          ├── hierarchy.json
          └── image_ids.csv
      
      2 (dùng để huấn luyện và kiểm tra mô hình)
    • Thư mục
      dataset = fiftyone.zoo.load_zoo_dataset(
          "open-images-v6",
          split="train",
          label_types=["detections"],
          classes=["Panda"],
          max_samples=250,
      )
      
      9 còn có 1 thư mục con
      .
      ├── data
      │   ├── 02a4749df3d7a0c9.jpg
      │   ├── 0b5547d4aa16e365.jpg
      │   ...
      ├── labels
      │   └── detections.csv
      └── metadata
          ├── classes.csv
          ├── hierarchy.json
          └── image_ids.csv
      
      4 chứa ảnh dùng để kiểm tra chất lượng mô hình

Huấn luyện mô hình

Cài đặt thư viện liên quan

Tải YOLOv5 từ GitHub và cài đặt các thư viện liên quan

dataset = fiftyone.zoo.load_zoo_dataset(
    "open-images-v6",
    split="train",
    label_types=["detections"],
    classes=["Panda"],
    max_samples=250,
)
9

Lưu ý là chúng ta cần YOLOv5 ở cùng thư mục với

.
├── data
│   ├── 02a4749df3d7a0c9.jpg
│   ├── 0b5547d4aa16e365.jpg
│   ...
├── labels
│   └── detections.csv
└── metadata
    ├── classes.csv
    ├── hierarchy.json
    └── image_ids.csv
5 ở trên

dataset = fiftyone.zoo.load_zoo_dataset(
    "open-images-v6",
    split="train",
    label_types=["detections"],
    classes=["Panda"],
    max_samples=250,
)
1

Huấn luyện

Các bước chuẩn bị đã hoàn thành, giờ luyện tập trở nên rất đơn giản

dataset = fiftyone.zoo.load_zoo_dataset(
    "open-images-v6",
    split="train",
    label_types=["detections"],
    classes=["Panda"],
    max_samples=250,
)
2

  • .
    ├── data
    │   ├── 02a4749df3d7a0c9.jpg
    │   ├── 0b5547d4aa16e365.jpg
    │   ...
    ├── labels
    │   └── detections.csv
    └── metadata
        ├── classes.csv
        ├── hierarchy.json
        └── image_ids.csv
    
    6. image size (decal mode)
  • .
    ├── data
    │   ├── 02a4749df3d7a0c9.jpg
    │   ├── 0b5547d4aa16e365.jpg
    │   ...
    ├── labels
    │   └── detections.csv
    └── metadata
        ├── classes.csv
        ├── hierarchy.json
        └── image_ids.csv
    
    7. số ảnh dùng để huấn luyện trong mỗi lần
  • .
    ├── data
    │   ├── 02a4749df3d7a0c9.jpg
    │   ├── 0b5547d4aa16e365.jpg
    │   ...
    ├── labels
    │   └── detections.csv
    └── metadata
        ├── classes.csv
        ├── hierarchy.json
        └── image_ids.csv
    
    8. training number for all the image in file data
    .
    ├── data
    │   ├── 02a4749df3d7a0c9.jpg
    │   ├── 0b5547d4aa16e365.jpg
    │   ...
    ├── labels
    │   └── detections.csv
    └── metadata
        ├── classes.csv
        ├── hierarchy.json
        └── image_ids.csv
    
    1
  • dataset = fiftyone.zoo.load_zoo_dataset(
        "open-images-v6",
        split="train",
        label_types=["detections"],
        classes=["Panda"],
        max_samples=250,
    )
    
    3. path to configure file of data file
  • custom_dataset
    ├── custom_dataset.yaml
    ├── custom_model.yaml
    └── images_and_labels
    
    1. đường dẫn đến file cấu hình của mô hình
  • custom_dataset
    ├── custom_dataset.yaml
    ├── custom_model.yaml
    └── images_and_labels
    
    2. đường dẫn đến tệp
    custom_dataset
    ├── custom_dataset.yaml
    ├── custom_model.yaml
    └── images_and_labels
    
    3 chứa các liên kết giữa các nơ-ron (đến
    custom_dataset
    ├── custom_dataset.yaml
    ├── custom_model.yaml
    └── images_and_labels
    
    4 là để luyện tập từ đầu)
  • custom_dataset
    ├── custom_dataset.yaml
    ├── custom_model.yaml
    └── images_and_labels
    
    5. tên thư mục để lưu cấu hình
  • custom_dataset
    ├── custom_dataset.yaml
    ├── custom_model.yaml
    └── images_and_labels
    
    6. use memory buffer to training nhanh hơn

Kết quả

Sử dụng

custom_dataset
├── custom_dataset.yaml
├── custom_model.yaml
└── images_and_labels
7 để kiểm tra kết quả của bài tập huấn luyện (các số chỉ thay đổi như thế nào sau mỗi
custom_dataset
├── custom_dataset.yaml
├── custom_model.yaml
└── images_and_labels
8)

dataset = fiftyone.zoo.load_zoo_dataset(
    "open-images-v6",
    split="train",
    label_types=["detections"],
    classes=["Panda"],
    max_samples=250,
)
0

Cheat sheet phát hiện đối tượng

dataset = fiftyone.zoo.load_zoo_dataset(
    "open-images-v6",
    split="train",
    label_types=["detections"],
    classes=["Panda"],
    max_samples=250,
)
1

Khi tập luyện kết thúc, có 2 trọng lượng tệp mô hình được lưu lại

  • Mô hình tốt nhất.
    custom_dataset
    ├── custom_dataset.yaml
    ├── custom_model.yaml
    └── images_and_labels
    
    9 (tốt nhất chỉ dựa trên số Độ chính xác trung bình trên tập kiểm tra)
  • Cuối cùng mô hình.
    # relative paths from folder yolov5
    #  .
    #  ├── custom_dataset
    #  └── yolov5
    train: ../custom_dataset/images_and_labels/images/train/
    val: ../custom_dataset/images_and_labels/images/valid/
    # number of classes
    nc: 1
    # class names
    names: ['panda']
    
    0

Dự đoán với mô hình được huấn luyện

dataset = fiftyone.zoo.load_zoo_dataset(
    "open-images-v6",
    split="train",
    label_types=["detections"],
    classes=["Panda"],
    max_samples=250,
)
2

  • custom_dataset
    ├── custom_dataset.yaml
    ├── custom_model.yaml
    └── images_and_labels
    
    2. trọng lượng tệp được sử dụng để dự đoán
  • .
    ├── data
    │   ├── 02a4749df3d7a0c9.jpg
    │   ├── 0b5547d4aa16e365.jpg
    │   ...
    ├── labels
    │   └── detections.csv
    └── metadata
        ├── classes.csv
        ├── hierarchy.json
        └── image_ids.csv
    
    6. image size (decal mode)
  • # relative paths from folder yolov5
    #  .
    #  ├── custom_dataset
    #  └── yolov5
    train: ../custom_dataset/images_and_labels/images/train/
    val: ../custom_dataset/images_and_labels/images/valid/
    # number of classes
    nc: 1
    # class names
    names: ['panda']
    
    3. độ tin cậy
  • # relative paths from folder yolov5
    #  .
    #  ├── custom_dataset
    #  └── yolov5
    train: ../custom_dataset/images_and_labels/images/train/
    val: ../custom_dataset/images_and_labels/images/valid/
    # number of classes
    nc: 1
    # class names
    names: ['panda']
    
    4. path to the image directory

Kết quả dự đoán được lưu tại thư mục

# relative paths from folder yolov5
#  .
#  ├── custom_dataset
#  └── yolov5
train: ../custom_dataset/images_and_labels/images/train/
val: ../custom_dataset/images_and_labels/images/valid/
# number of classes
nc: 1
# class names
names: ['panda']
5 (hoặc exp2, 3,… tùy vào số lần chúng ta chạy dự đoán với
# relative paths from folder yolov5
#  .
#  ├── custom_dataset
#  └── yolov5
train: ../custom_dataset/images_and_labels/images/train/
val: ../custom_dataset/images_and_labels/images/valid/
# number of classes
nc: 1
# class names
names: ['panda']
6)

Cheat sheet phát hiện đối tượng
Kết quả dự đoán trên ảnh mới từ tập tin thử nghiệm

Google Colab and data

Mình đã chuẩn bị sẵn một Google Colab Notebook để tiện cho việc tham khảo. Các bạn hoàn toàn có thể sử dụng dữ liệu của mình để sử dụng với notebook này (chỉ cần chuẩn bị đúng cấu hình của file là ổn định)

Bên cạnh đó, mình lưu tệp cấu trúc sắc nét với nhãn ở Panda ML Blog Github để các bạn có thể thực hiện các hành động quen thuộc với các bước xây dựng mô hình khi chưa có dữ liệu trong tay

pause

Bài hôm nay đã giới thiệu đến các bạn các bước huấn luyện mô hình Phát hiện đối tượng dựa trên YOLOv5. Có thể bước khoảng thời gian ngắn nhất là bước tìm ảnh phù hợp và gắn nhãn cho ảnh. Ngoài ra các bước huấn luyện và dự đoán, khá dễ dàng. Trong thực tế cũng vậy,bước chuẩn bị dữ liệu (chuẩn bị dữ liệu) thường cũng là bước thời gian nhất

Với tệp dữ liệu hơn 100 ảnh, mình khá hài lòng với mô hình đã được huấn luyện khi mô hình này cho kết quả tương đối ổn. Hy vọng là với bài hướng dẫn này, các bạn cũng sẽ rèn luyện được những mô hình thú vị cho riêng mình