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)

txt
Nội dung file txt.

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:

Crop
Cắt từng đối tượng và lưu thành từng ảnh riêng biệt.

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:

Brightness
Kết quả tăng sáng cho ảnh.

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:

Kết quả sau khi zoom ảnh.

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:

Rotate
Kết quả xoay ảnh.

\

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.

label
Gán nhãn trên toàn ảnh

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ả :

autolabel
Kết quả gán nhãn bằng code.

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!

One thought on “Data augmentation images cho CNN model theo cách đơn giản và hiệu quả.

  • 25 Tháng Tư, 2021 at 18:24
    Permalink

    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.

    Reply

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *