Avatar
Ba
Phần 1 - Xử lý bộ dữ liệu cho mô hình phát hiện đối tượng (Object Detection)

Phần 1 - Xử lý bộ dữ liệu cho mô hình phát hiện đối tượng (Object Detection)

Mô hình YOLO là một mô hình rất phổ biến trong nhận diện hình ảnh vì tính tiện dụng của mình.

Phiên bản đầu tiên của mô hình này chủ yếu sử dụng kiến trúc CNN. Kiến trúc CNN được đề cập chi tiết tại đây.

Để có thể chuẩn bị dữ liệu cho mình này, bạn cần nắm được đầu ra của mô hình và lập trình sao cho với các bộ dữ liệu khác nhau, bạn có thể cung cấp cấu trúc mà YOLO yêu cầu.

Dưới đây là một ví dụ tiền xử lý nhãn cho bộ dữ liệu Pascal VOC

1) Giới thiệu bộ dữ liệu Pascal VOC

Pascal VOC là một bộ dữ liệu nổi tiếng cung cấp cho chúng ta dữ liệu phục vụ cho việc nhận diện đối tượng trong ảnh. Trong bài này chúng ta sẽ sử dụng dữ liệu từ năm 2017 để thực hành.

Một cặp dữ liệu của VOC bao gồm 2 phần

  • Hình ảnh dưới dạng Tensor

  • Nhãn của ảnh này dưới dạng như sau

{
    "annotation": {
        "folder": "VOC2007",
        "filename": "000219.jpg",
        "source": {
            "database": "The VOC2007 Database",
            "annotation": "PASCAL VOC2007",
            "image": "flickr",
            "flickrid": "321854556",
        },
        "owner": {"flickrid": "momimdr", "name": "?"},
        "size": {"width": "333", "height": "500", "depth": "3"},
        "segmented": "0",
        "object": [
            {
                "name": "motorbike",
                "pose": "Left",
                "truncated": "0",
                "difficult": "0",
                "bndbox": {"xmin": "120", "ymin": "333", "xmax": "310", "ymax": "464"},
            }
        ],
    }
}

Object chính là phần bounding box của bức ảnh mà chúng ta cần.

{
    "object": [
        {
            "name": "motorbike",
            "pose": "Left",
            "truncated": "0",
            "difficult": "0",
            "bndbox": {"xmin": "120", "ymin": "333", "xmax": "310", "ymax": "464"},
        }
    ],
}

Object này chính là chứa khung đỏ bao quanh (bounding box) chiếc xe máy mà chúng ta nhìn thấy ảnh bên trên. Cùng phân tích xem các giá trị xmin, ymin, xmax, ymax thể hiện ý nghĩa như thế nào của khung?

2) Scale ảnh về kích cỡ 448 x 448

Ảnh sẽ được resize ở kích thước bất kỳ về một Tensor có cỡ 3 x 448 x 448 với

  • 3 lớp đại diện cho 3 màu đỏ, xanh lục, xanh dương

  • 448 là chiều dài

  • 448 là chiều cào

Cách load dữ liệu và resize ngay sau đó rất đơn giản, bạn có thể load trực tiếp từ thư viện Pytorch

dataset = VOCDetection(
        root='data',
        year='2007',
        image_set=('train' if set_type == 'train' else 'val'),
        download=True,
        transform=T.Compose([
            T.ToTensor(),
            T.Resize((448, 448)
            )
        ])
    )

Hàm resize về cỡ 448 x 448 đã nằm ngay trong phần load dữ liệu này.

3) Bounding box là gì

Bounding box là hình chữ nhật bao quanh vật thể được xác lập bởi 2 điểm.

  • Điểm min: Điểm nằm bên trái góc trên của bounding box

  • Điểm max: Điểm nằm bên phải góc dưới của bounding box

Trong trường hợp này bạn cần chú ý:

  • Trục x nằm ngang bên trên

  • Trục y nằm dọc bên tay trái

  • Điểm min có giá trị theo trục x là xmin = 161 và theo trục y là ymin = 298

  • Điểm max có giá trị theo trục x là xmax = 417 và theo trục y là ymax = 415.

4) Giãn Bounding Box

Tuy nhiên khi thay đổi kích cỡ của ảnh thì cũng cần thay đổi kích cỡ của bouding box vì thế trong trong trường hợp này ta sẽ scale cả bouding box tương ứng.

def get_bounding_boxes(label):
    width, height = get_dimensions(label)
    x_scale = config.IMAGE_SIZE[0] / width
    y_scale = config.IMAGE_SIZE[1] / height
    boxes = []
    objects = label['annotation']['object']
    for obj in objects:
        box = obj['bndbox']
        coords = (
            int(int(box['xmin']) * x_scale),
            int(int(box['xmax']) * x_scale),
            int(int(box['ymin']) * y_scale),
            int(int(box['ymax']) * y_scale)
        )
        name = obj['name']
        boxes.append((name, coords))
    return boxes

Nhìn hàm trên bạn có thể thấy ta sẽ:

  • Tìm độ giãn x_scale theo chiều dài của ảnh mới (448) và chiều dài của ảnh cũ

  • Tìm độ giản y_scale theo chiều cao của ảnh mới (448) và chiều cao của ảnh cũ

Sau khi có hai độ giãn này

  • Giãn các giá trị xmin, xmax theo độ giãn x_scale

  • Giãn các giá trị ymin, ymax theo độ giãn y_scale

5) Chia ảnh thành Grid

Thuật toán YOLO sẽ chia ảnh thành một Grid cỡ S x S và nếu trong trường hợp này S = 7 thì Grid sẽ trông như thế này:

Tức là ta sẽ có 7x7 = 49 ô.

Từ mỗi ô này, YOLO sẽ cố gắng vẽ ra được các bounding box khớp nhất với bounding box màu đỏ nhãn. Ô này sẽ chứa tâm của bounding box Yolo học.

Chi tiết Đầu ra của Yolo sẽ được mô phỏng dưới hình dạng này:

Chi tiết sẽ được giải thích tại phần hai sẽ được công bố vào ngày mai 07/11/2023. Bạn cũng chờ đón nhé.