.. raw:: html
Tập dữ liệu Phát hiện Đối tượng
===============================
.. raw:: html
Không có một bộ dữ liệu nhỏ nào cho bài toán phát hiện đối tượng như
MNIST hay Fashion-MNIST. Để nhanh chóng kiểm định mô hình, ta sẽ tập hợp
lại một tập dữ liệu nhỏ. Đầu tiên, ta tạo 1000 bức ảnh Pikachu với nhiều
góc độ và kích thước khác nhau bằng mô hình mã nguồn mở Pikachu 3D. Sau
đó, ta thu thập một loạt các ảnh nền và đặt ngẫu nhiên ảnh Pikachu lên
trên mỗi bức ảnh. Ta dùng `công cụ
im2rec `__
do MXNet cung cấp để chuyển đổi hình ảnh gốc sang định dạng RecordIO nhị
phân[1]. Định dạng này có khả năng giảm dung lượng lưu trữ và cải thiện
hiệu suất đọc dữ liệu. Nếu bạn đọc muốn tìm hiểu thêm về cách đọc ảnh,
có thể tham khảo tài liệu cho `bộ công cụ
GluonCV `__.
.. raw:: html
Tải xuống tập Dữ liệu
---------------------
.. raw:: html
Tập dữ liệu Pikachu ở định dạng RecordIO có thể được tải xuống trực tiếp
từ Internet.
.. code:: python
%matplotlib inline
from d2l import mxnet as d2l
from mxnet import gluon, image, np, npx
import os
npx.set_np()
#@save
d2l.DATA_HUB['pikachu'] = (d2l.DATA_URL + 'pikachu.zip',
'68ab1bd42143c5966785eb0d7b2839df8d570190')
.. raw:: html
Đọc dữ liệu
-----------
.. raw:: html
Ta sẽ đọc tập dữ liệu phát hiện đối tượng theo thứ tự ngẫu nhiên bằng
thực thể ``ImageDetIter``. “Det” (viết tắt cho Detection), đề cập đến
việc phát hiện. Vì định dạng của dữ liệu là RecordIO, ta cần có tệp chỉ
số ``'train.idx'`` để đọc minibatch ngẫu nhiên. Ngoài ra, đối với từng
ảnh trong tập huấn luyện, ta sẽ cắt xén ngẫu nhiên nhưng vẫn yêu cầu bao
phủ ít nhất 95% mỗi đối tượng. Vì việc cắt xén là ngẫu nhiên, yêu cầu
này không phải lúc nào cũng được thỏa mãn. Ta cho trước số lần cắt ảnh
ngẫu nhiên tối đa là 200 lần. Nếu không có lần nào thỏa mãn yêu cầu,
hình ảnh sẽ được giữ nguyên. Để đầu ra được đảm bảo, ta sẽ không cắt
ngẫu nhiên các hình ảnh trong tập kiểm tra. Ta cũng không cần đọc dữ
liệu trong tập kiểm tra theo thứ tự ngẫu nhiên.
.. code:: python
#@save
def load_data_pikachu(batch_size, edge_size=256):
"""Load the pikachu dataset."""
data_dir = d2l.download_extract('pikachu')
train_iter = image.ImageDetIter(
path_imgrec=os.path.join(data_dir, 'train.rec'),
path_imgidx=os.path.join(data_dir, 'train.idx'),
batch_size=batch_size,
data_shape=(3, edge_size, edge_size), # The shape of the output image
shuffle=True, # Read the dataset in random order
rand_crop=1, # The probability of random cropping is 1
min_object_covered=0.95, max_attempts=200)
val_iter = image.ImageDetIter(
path_imgrec=os.path.join(data_dir, 'val.rec'), batch_size=batch_size,
data_shape=(3, edge_size, edge_size), shuffle=False)
return train_iter, val_iter
.. raw:: html
Dưới đây, ta đọc một minibatch rồi in ra kích thước ảnh và nhãn. Kích
thước ảnh vẫn là (kích thước batch, số kênh, chiều cao, chiều rộng)
giống như trong thí nghiệm trước. Kích thước của nhãn là (kích thước
batch, :math:`m`, 5), trong đó :math:`m` là số lượng khung chứa tối đa
trên một bức ảnh trong một tập dữ liệu hình ảnh. Mặc dù việc tính toán
với minibatch rất hiệu quả, nhưng nó lại yêu cầu mỗi hình ảnh phải cùng
một lượng khung chứa để chúng có thể được đặt trong cùng một batch. Vì
mỗi hình ảnh có thể có số lượng khung chứa khác nhau, ta có thể thêm các
khung chứa ngẫu nhiên để mỗi bức ảnh có :math:`m` khung chứa. Do đó,
chúng ta có thể đọc được một minibatch mỗi lần. Nhãn của mỗi khung chứa
trong bức ảnh được biểu diễn bằng một mảng có độ dài là 5. Phần tử đầu
tiên trong mảng là hạng mục của đối tượng xuất hiện trong khung chứa.
Khi giá trị là -1, khung chứa ấy chính là khung chứa ngẫu nhiên dùng để
lấp đầy. Bốn phần tử còn lại trong mảng đại diện cho toạ độ trục
:math:`x, y` của góc trên bên trái và góc dưới bên phải của khung chứa
(miền giá trị từ 0 đến 1). Tập dữ liệu Pikachu ở đây chỉ có một khung
chứa cho mỗi ảnh, vì thế :math:`m=1`.
.. code:: python
batch_size, edge_size = 32, 256
train_iter, _ = load_data_pikachu(batch_size, edge_size)
batch = train_iter.next()
batch.data[0].shape, batch.label[0].shape
.. parsed-literal::
:class: output
Downloading ../data/pikachu.zip from http://d2l-data.s3-accelerate.amazonaws.com/pikachu.zip...
.. parsed-literal::
:class: output
((32, 3, 256, 256), (32, 1, 5))
.. raw:: html
Minh hoạ
--------
.. raw:: html
Ta có mười bức ảnh kèm với các khung chứa trên chúng. Chúng ta có thể
thấy rằng góc, kích thước và vị trí của Pikachu khác nhau trong mỗi bức
ảnh. Dĩ nhiên, đây là một tập dữ liệu tự tạo đơn giản. Trong thực tế, dữ
liệu thường phức tạp hơn nhiều.
.. code:: python
imgs = (batch.data[0][0:10].transpose(0, 2, 3, 1)) / 255
axes = d2l.show_images(imgs, 2, 5, scale=2)
for ax, label in zip(axes, batch.label[0][0:10]):
d2l.show_bboxes(ax, [label[0][1:5] * edge_size], colors=['w'])
.. figure:: output_object-detection-dataset_vn_a60c54_7_0.png
Tóm tắt
-------
.. raw:: html
- Tập dữ liệu Pikachu mà ta tổng hợp có thể được dùng để kiểm tra các
mô hình phát hiện đối tượng.
- Việc đọc dữ liệu để phát hiện đối tượng giống như khi phân loại hình
ảnh. Tuy nhiên, sau khi đưa ra các khung chứa, kích thước nhãn và
việc tăng cường ảnh (ví dụ, cắt xén ngẫu nhiên) sẽ thay đổi.
Bài tập
-------
.. raw:: html
Trong tài liệu MXNet, tham số trong các hàm tạo (*constructors*) của các
lớp ``image.ImageDetIter`` và ``image.CreateDetAugmenter`` là gì? Cho
biết ý nghĩa của chúng?
Thảo luận
---------
- `Tiếng Anh - MXNet `__
- `Tiếng Việt `__
Những người thực hiện
---------------------
Bản dịch trong trang này được thực hiện bởi:
- Đoàn Võ Duy Thanh
- Phạm Đăng Khoa
- Nguyễn Lê Quang Nhật
- Lê Khắc Hồng Phúc
- Nguyễn Văn Cường