Data augmentation images cho CNN model theo cách đơn giản và hiệu quả.
1. Vì sao phải Data augmentation ???.
Đối với các model CNN, nguồn dữ liệu đầu vào luôn là thứ gây ảnh hưởng nhiều nhất tới kết quả đầu ra. Model có hoạt động tốt hay không, phần lớn là do việc sàng lọc data kỹ như thế nào cũng như số lượng data anh em đưa vào train cho model đó. Nhất là đối với model đặc thù, việc thu thập data luôn là những thứ đau đầu và vất vả. Hiểu vấn đề đó, nên hôm nay mình sẽ chia sẻ cho anh em cách mà mình sử dụng phục vụ việc data augmentation ( mình thấy nhanh và hiệu quả) 😀 Hi vọng là sẽ có ích đối với mọi người.
Hôm nay, mình sẽ chia sẻ trên tập dataset của mô hình YOLOv4 ( files label có đuôi là .txt),các mô hình với file .xml cũng sẽ tương tự nhé .Let’s gooooo!
2.Nắm bắt số lượng label trong dataset trước khi thực hiện data augmentation .
Việc nắm bắt số lượng nhãn đối với từng đối tượng là rất quan trọng. Mình đã thực hiện cũng kha khá model object detection và nhận ra một điều là: nếu dataset của bạn có số lượng nhãn đối với từng đối tượng không đều, thì hoặc là overfit đối với object có features tương đối giống nhau, hoặc là model không đủ “khôn” để nhận dạng, hoặc là làm giảm các giá trị trong các thang đánh giá model, hoặc là nó chỉ nhận dạng được đối với những ảnh đã có sẵn trong dataset 😀 Việc xảy ra trường hợp nào thì còn tùy thuộc vào nhiều vấn đề chủ quan và khách quan nữa nhé!
Vậy nên, phải nắm bắt được số lượng nhãn trên từng đối tượng để tiện tính tới phương án tiếp theo cho model nữa nhé! Và “nắm bắt” như thế nào thì … cùng tìm hiểu nhé.
Đối với file label cho YOLOv4 sẽ có dạng:<Nhãn đối tượng> <trọng tâm phương x> <trọng tâm phương y> <độ dài> <độ rộng> ( còn làm sao để tạo file label này thì bạn xem Series YOLOv4: #1Train model trên Google Colab – Object detection. – DevAI và Hướng dẫn cài LabelImg tool – DevAI)

Chúng ta sẽ đi đếm các <nhãn đối tượng> để nắm bắt được số lượng nhãn. Sử dụng các đoạn code ( đầu tiên phải đặt tất cả các file .txt vào chung 1 folder nhé):
path_txt = 'Địa_chỉ_thư_mục_chứa_file_đuôi_.txt'
no=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
for file in glob.glob(pathSrc + '/*.txt'):
# Tìm các file có đuôi .txt trong thư mục path_txt
fileNew = file.split('/')[-1]
# Cắt tên file .txt
lines = []
with open(file, 'r+') as stream:
# Mở file .txt
lines = [line.strip() for line in stream.readlines()]
# Đọc từng dòng trong file .txt đã mở
for line in lines:
num = int(line.split(' ',1)[0])
# Cắt tên nhãn
no[num] +=1
# Đếm tên nhãn
stream.close()
print(no)
Nếu lười thì các bạn có thể tải code tại đây 😀
3.Augmentation data.
3.1. Crop vật thể.
Rồi, sau khi đã nắm được số lượng nhãn cho từng đối tượng, chúng ta nên augment cho những đối tượng có ít nhãn hơn( tới lúc đối tượng có số lượng nhãn gần bằng nhau). Đối với mình thì mọi đối tượng đều phải ít nhất 10k nhãn thì model mới ổn được.
Ví dụ, model của mình đang thực hiện là: nhận dạng cỏ( chỉ có 7k nhãn) và rau xà lách( có 15k nhãn). Bây giờ, mình sẽ tạo một folder với tên Grass_augmentation , sau đó mình sẽ tìm cắt những cây cỏ riêng biệt trên những bức ảnh có nhiều cây:

Các cây cỏ ở đây mình đã zoom ra cho dễ nhìn hơn :D.
3.2. Data augmentation.
Có nhiều phương pháp để augment như: brightness, zoom, rotate, flip, translation , Gaussian noise,… Thường thì mình sẽ sử dụng 3 phương pháp đầu tiên, vừa nhanh vừa hiệu quả đủ xài 😀
Các bạn tạo một file python: Augmentation.py trong thư mục chứa ảnh đã crop và copy các đoạn code dưới đây vào để sử dụng.
3.2.1. Brightness.
Phương pháp này giúp thay đổi độ sáng của bức ảnh. Bởi vì nó chỉ tăng giảm sáng nên sẽ không ảnh hưởng tới đặc điểm của vật thể.
def brightness_img():
for img in glob.glob("*.png"):
# read the image
name = img
# print(name)
name = name.split(".PNG")[0]
print(name)
img = Image.open(img)
count = 0
for factor in range(3, 15, 1):
# image brightness enhancer
enhancer = ImageEnhance.Brightness(img)
# factor = 1.5 # brightens the image
im_output = enhancer.enhance((factor/10))
im_output.save( name + '_brightness_' + str(count) + '.png')
count+=1
Kết quả thực hiện:

3.2.2. Zoom.
Phương pháp này làm tăng hoặc giảm kích thước của vật thể.
def zoom_img(image):
count = 0
name = image
name = name.split(".PNG")[0]
image = cv2.imread(image)
for scale_percent in range(50, 150, 10):
width = int(image.shape[1] * scale_percent / 100)
height = int(image.shape[0] * scale_percent / 100)
image = cv2.resize(src=image, dsize=(width, height))
cv2.imwrite( name + '_zoom' + str(count) + '.png', image)
count +=1
Kết quả thực hiện:

3.2.3. Rotate.
Phương pháp này là xoay ảnh. áp dụng cho những vật thể không chịu ảnh hưởng bởi góc.
def rotate_img(image): count = 0 name = image name = name.split(".PNG")[0] cv2.imread(image) for angle in np.arange(0, 360, 15): rotated = imutils.rotate_bound(image, angle) cv2.imwrite(name + "_rotate_" + str(count) + ".png", rotated) count +=1
Kết quả thực hiện:

\
LƯU Ý:
- Nên crop ảnh SÁT VỚI BIÊN của vật thể, để phục vụ việc gán nhãn hiệu quả hơn.
- Nên crop nhiều ảnh để model không bị overfit khi trainning.
- Các bạn nên sử dụng kết quả của thuật toán augmentation này làm input cho thuật toán augmentation kia, khi đó thì số lượng ảnh được tăng sinh sẽ rất nhiều.
- Để ảnh và code vào chung một folfer.
3.3. Gán nhãn tự động.
Sau khi đã có kết quả thực hiện data augmentation, công việc “nặng nhọc’ tiếp theo là phải gán nhãn cho toàn bộ chúng nó.
Vâng, và bước này chúng ta có thể code được 😀 nhưng các bạn phải thực hiện đúng với lưu ý ở phía trên để có được hiệu quả cao nhất nhé.!
Với mỗi bức ảnh, chỉ có một vật thể có kích thước lớn bằng kích thước của bức ảnh, thì ta có quyền gán nhãn full diện tích của bức ảnh đó :D.

Khi đó, tập gán nhãn sẽ có dạng: <Class id> <0.500000> <0.500000> <0.999999> <0.999999> ( vì sao nó như thế này? mình đã có giải thich ở cuối phần 2 trong bài: Hướng dẫn cài LabelImg tool )
Các bạn sử dụng đoạn code này để gán nhãn tự động:
for image in glob.glob('*.PNG'): # Đổi '.PNG' sang định dạng ảnh mà bạn đang sử dụng name = image.split('.PNG')[0] # Đổi '.PNG' sang định dạng ảnh mà bạn đang sử dụng # Cắt tên ảnh để tạo file .txt print(name) # In tên ảnh with open(name+ '.txt', 'w+') as stream_out: # Tạo và mở file .txt stream_out.write('0 0.500000 0.500000 0.999999 0.999999') # Ghi giá trị vào file .txt stream_out.close() # Đong file
Đơn giản vậy thôi. Nếu lười, các bạn có thể tải đoạn code phục vụ data augmentation và auto label tại đây
Lưu ý: các bạn đặt code và ảnh vào chung một folder nhé.
Kết quả :

Bài viết tới đây là kết thúc. Chúc các bạn thực hiện thành công!
If you would like to get a good deal from this piece of writing then you have to apply these techniques
to your won website.