Skip to content
Mì AI Mì AI Mì AI

Học AI theo cách Mì ăn liền!

Mì AI Mì AI Mì AI

Học AI theo cách Mì ăn liền!

  • Trang chủ
  • Kênh Youtube
  • Facebook Group
  • Nói về chủ tiệm Mì
  • Trang chủ
  • Kênh Youtube
  • Facebook Group
  • Nói về chủ tiệm Mì
Close

Search

  • Trang chủ
  • Kênh Youtube
  • Facebook Group
  • Nói về chủ tiệm Mì
Mì AI Mì AI Mì AI

Học AI theo cách Mì ăn liền!

Mì AI Mì AI Mì AI

Học AI theo cách Mì ăn liền!

  • Trang chủ
  • Kênh Youtube
  • Facebook Group
  • Nói về chủ tiệm Mì
  • Trang chủ
  • Kênh Youtube
  • Facebook Group
  • Nói về chủ tiệm Mì
Close

Search

  • Trang chủ
  • Kênh Youtube
  • Facebook Group
  • Nói về chủ tiệm Mì
Computer Vision

Phân loại biển báo giao thông bằng Deep Learning (CNN)

By Chủ tiệm Mì
August 3, 2020 7 Min Read
21

Chào tuần mới các member thân yêu, hôm nay anh em ta cùng nấu bát mì Phân loại biển báo giao thông nhé!

Hôm trước co một bạn trên Mì Ai yêu cầu viết về bài toán biển báo giao thông nên Mì AI đáp ứng liền. Về biển báo giao thông thì thường có 2 bài toán là:

  • Nhận diện biển báo
  • Phân loại biển báo

Với bài toán nhận diện biển báo thì bạn vừa phải detect biển báo trong hình và đồng thời nhận diện được đó là biển báo loại gì. Còn với bài Phân loại thì input đầu vào sẽ là các ảnh biển báo và chúng ta sẽ phân loại xem biển báo đó là biển gì? Ví dụ: giới hạn tốc độ, cấm rẽ trái, cấm quay đầu….

Hôm nay chúng ta sẽ làm bài toán Phân loại biển số trước nhé!

Let’s go!

Phần 1 – Phân tích bài toán

Bài toán của chúng ta như mình đã nói sẽ là input là 1 ảnh, output là ảnh đó là ảnh gì, hay cụ thể hơn là biển báo gì.

Về dữ liệu chúng ta sẽ sử dụng bộ dữ liệu biển báo giao thông nổi tiếng đó là German Traffic Sign.

phân loại biển số
Nguồn: Tại đây

Chúng ta sẽ sử dụng bộ dữ liệu training tải về tài link này .

Bộ dữ liệu này gồm khoảng gần 40k ảnh chia thành 43 folder là 43 loại biển báo khác nhau. Mỗi folder sẽ có 1 file CSV chứa thông tin các ảnh trong thư mục. Chúng ta chú ý vài thông tin sau:

  • ROI: là vùng ảnh chứa biển số với các thông tin X1, Y1, X2, Y2
  • ClassID: là nhãn của biển số (từ 1 đến 43)

Do đó, chúng ta sẽ train 1 model CNN để khi input là 1 ảnh thì sẽ predict ra 1 trong 43 class kia nhé.

Các bạn clone git của mình về bằng lệnh:

git clone https://github.com/thangnch/MiAi_Traffic_Sign_Classify

Sau đó tải data, giải nén và copy folder GTSRB vào thư mục gốc của project luôn nha.

Và bước cuối cùng là đừng quên cài thư viện nhé:

pip install -r setup.txt

Phần 2 – Đọc và xử lý dữ liệu

Việc đầu tiên là phải đọc dữ liệu từ thư mục GTSRB đã, chúng ta sẽ lặp qua các thư mục con, đọc và add vào các list.

Ở đây sẽ có 2 list là:

  • pixels: Chứa tất cả các ảnh trong bộ dữ liệu
  • labels: Chứa nhãn của các ảnh trong bộ dữ liệu

Để đọc dữ liệu ta dùng đoạn code:


def load_data(input_size = (64,64), data_path =  'GTSRB/Final_Training/Images'):

    pixels = []
    labels = []
    # Loop qua các thư mục trong thư mục Images
    for dir in os.listdir(data_path):
        if dir == '.DS_Store':
            continue

        # Đọc file csv để lấy thông tin về ảnh
        class_dir = os.path.join(data_path, dir)
        info_file = pd.read_csv(os.path.join(class_dir, "GT-" + dir + '.csv'), sep=';')

        # Lăp trong file
        for row in info_file.iterrows():
            # Đọc ảnh
            pixel = imread(os.path.join(class_dir, row[1].Filename))
            # Trích phần ROI theo thông tin trong file csv
            pixel = pixel[row[1]['Roi.X1']:row[1]['Roi.X2'], row[1]['Roi.Y1']:row[1]['Roi.Y2'], :]
            # Resize về kích cỡ chuẩn
            img = cv2.resize(pixel, input_size)

            # Thêm vào list dữ liệu
            pixels.append(img)

            # Thêm nhãn cho ảnh
            labels.append(row[1].ClassId)

    return pixels, labels

Xong con ong! Bây giờ sau khi đọc xong ta sẽ tiến hành chia dữ liệu train, test và val.

Như các bạn đã biết, với một bài toán Deep Learning thì với dữ liệu có được ta hay chia thành 3 bộ:

  • Train: Để train model
  • Val: Để validation model trong quá trình train
  • Test: Để kiểm thử model sau khi train xong
data split
Nguồn: Tại đây

Ở đây mình chia theo tỷ lệ 60% – 20% – 20%, nghĩa là 60% dữ liệu mình dùng để train, 20% cho validation và 20% còn lại để test. Việc chia dữ liệu test riêng rất cần thiết để xem model sẽ treat như nào với các dữ liệu unseen – chưa nhìn thấy bao giờ.

Để thực hiện việc đó mình sử dụng hàm sau:

def split_train_val_test_data(pixels, labels):

    # Chuẩn hoá dữ liệu pixels và labels
    pixels = np.array(pixels)
    labels = keras.utils.np_utils.to_categorical(labels)

    # Nhào trộn dữ liệu ngẫu nhiên
    randomize = np.arange(len(pixels))
    np.random.shuffle(randomize)
    X = pixels[randomize]
    print("X=", X.shape)
    y = labels[randomize]

    # Chia dữ liệu theo tỷ lệ 60% train và 40% còn lại cho val và test
    train_size = int(X.shape[0] * 0.6)
    X_train, X_val = X[:train_size], X[train_size:]
    y_train, y_val = y[:train_size], y[train_size:]

    val_size = int(X_val.shape[0] * 0.5) # 50% của phần 40% bên trên
    X_val, X_test = X_val[:val_size], X_val[val_size:]
    y_val, y_test = y_val[:val_size], y_val[val_size:]

    return X_train, y_train, X_val, y_val, X_test, y_test

Rồi! Sau bước này thì có đủ cả X và y cho các ông train, val và test rồi. Sang bước xây dựng model thôi.

Phần 3 – Xây dựng model phân loại biển báo

Bài này các bạn hoàn toàn có thể sử dụng Transfer Learning với các mạng nổi tiếng như VGG16, VGG19… nhưng ở đây mình xin demo việc tự xây một mạng đơn giản để các bạn hiểu từng bước cho dễ.

Nếu cần transfer learning, các bạn có thể đọc bài nhận diện tiền của mình tại đây

Ta cùng xây dựng model đơn giản:


def build_model(input_shape=(64,64,3), filter_size = (3,3), pool_size = (2, 2), output_size = 43):
    model = Sequential([
        Conv2D(16, filter_size, activation='relu', input_shape=input_shape, padding='same'),
        BatchNormalization(),
        Conv2D(16, filter_size, activation='relu', padding='same'),
        BatchNormalization(),
        MaxPooling2D(pool_size=pool_size),
        Dropout(0.2),
        Conv2D(32, filter_size, activation='relu', padding='same'),
        BatchNormalization(),
        Conv2D(32, filter_size, activation='relu', padding='same'),
        BatchNormalization(),
        MaxPooling2D(pool_size=pool_size),
        Dropout(0.2),
        Conv2D(64, filter_size, activation='relu', padding='same'),
        BatchNormalization(),
        Conv2D(64, filter_size, activation='relu', padding='same'),
        BatchNormalization(),
        MaxPooling2D(pool_size=pool_size),
        Dropout(0.2),
        Flatten(),
        Dense(2048, activation='relu'),
        Dropout(0.3),
        Dense(1024, activation='relu'),
        Dropout(0.3),
        Dense(128, activation='relu'),
        Dropout(0.3),
        Dense(output_size, activation='softmax')
    ])

    model.compile(loss='categorical_crossentropy', optimizer=Adam(lr=1e-4), metrics=['accuracy'])
    return model

Model này có mấy điểm các bạn cần chú ý:

  • Model có input size là 64x64x3, nghĩa là các ảnh đầu vào đều phải resize về 64×64.
  • Model có output = 43 – là số class biển báo ta có.
  • Model có sử dụng Dropout để tránh Overfit
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d_1 (Conv2D)            (None, 64, 64, 16)        448       
_________________________________________________________________
batch_normalization_1 (Batch (None, 64, 64, 16)        64        
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 64, 64, 16)        2320      
_________________________________________________________________
batch_normalization_2 (Batch (None, 64, 64, 16)        64        
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 32, 32, 16)        0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 32, 32, 16)        0         
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 32, 32, 32)        4640      
_________________________________________________________________
batch_normalization_3 (Batch (None, 32, 32, 32)        128       
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 32, 32, 32)        9248      
_________________________________________________________________
batch_normalization_4 (Batch (None, 32, 32, 32)        128       
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 16, 16, 32)        0         
_________________________________________________________________
dropout_2 (Dropout)          (None, 16, 16, 32)        0         
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 16, 16, 64)        18496     
_________________________________________________________________
batch_normalization_5 (Batch (None, 16, 16, 64)        256       
_________________________________________________________________
conv2d_6 (Conv2D)            (None, 16, 16, 64)        36928     
_________________________________________________________________
batch_normalization_6 (Batch (None, 16, 16, 64)        256       
_________________________________________________________________
max_pooling2d_3 (MaxPooling2 (None, 8, 8, 64)          0         
_________________________________________________________________
dropout_3 (Dropout)          (None, 8, 8, 64)          0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 4096)              0         
_________________________________________________________________
dense_1 (Dense)              (None, 2048)              8390656   
_________________________________________________________________
dropout_4 (Dropout)          (None, 2048)              0         
_________________________________________________________________
dense_2 (Dense)              (None, 1024)              2098176   
_________________________________________________________________
dropout_5 (Dropout)          (None, 1024)              0         
_________________________________________________________________
dense_3 (Dense)              (None, 128)               131200    
_________________________________________________________________
dropout_6 (Dropout)          (None, 128)               0         
_________________________________________________________________
dense_4 (Dense)              (None, 43)                5547      
=================================================================
Total params: 10,698,555
Trainable params: 10,698,107
Non-trainable params: 448

Tổng số tham số là 10,698,555!

Phần 4 – Train model phân loại biển báo và kiểm thử

Thôi thì nguyên vật liệu đã xong, nồi niêu xong chảo cũng đủ cả thì giờ nấu Mì thôi anh em!

Chúng ta sẽ train khoảng 10 epochs với batch_size là 16.


# Train model
epochs = 10
batch_size = 16

model.fit(X_train, y_train, epochs=epochs, batch_size=batch_size,
                               validation_data=(X_val, y_val))

model.save("traffic_sign_model.h5")

Sau khi train xong thì save lại file h5 để lần sau còn sử dụng 😀

Model đạt val_accuracy là 0.9939 sau 10 epochs, một kết quả khá tốt:


Train on 23525 samples, validate on 7842 samples
Epoch 1/10
23525/23525 [==============================] - 662s 28ms/step - loss: 2.5743 - accuracy: 0.3046 - val_loss: 1.2445 - val_accuracy: 0.6483
Epoch 2/10
23525/23525 [==============================] - 652s 28ms/step - loss: 1.0229 - accuracy: 0.6851 - val_loss: 0.2815 - val_accuracy: 0.9162
Epoch 3/10
23525/23525 [==============================] - 648s 28ms/step - loss: 0.3962 - accuracy: 0.8767 - val_loss: 0.1033 - val_accuracy: 0.9684
Epoch 4/10
23525/23525 [==============================] - 650s 28ms/step - loss: 0.1999 - accuracy: 0.9375 - val_loss: 0.0726 - val_accuracy: 0.9770
Epoch 5/10
23525/23525 [==============================] - 664s 28ms/step - loss: 0.1278 - accuracy: 0.9588 - val_loss: 0.0446 - val_accuracy: 0.9855
Epoch 6/10
23525/23525 [==============================] - 660s 28ms/step - loss: 0.0880 - accuracy: 0.9730 - val_loss: 0.0407 - val_accuracy: 0.9861
Epoch 7/10
23525/23525 [==============================] - 664s 28ms/step - loss: 0.0669 - accuracy: 0.9788 - val_loss: 0.0528 - val_accuracy: 0.9850
Epoch 8/10
23525/23525 [==============================] - 664s 28ms/step - loss: 0.0502 - accuracy: 0.9845 - val_loss: 0.0290 - val_accuracy: 0.9908
Epoch 9/10
23525/23525 [==============================] - 663s 28ms/step - loss: 0.0435 - accuracy: 0.9866 - val_loss: 0.0224 - val_accuracy: 0.9938
Epoch 10/10
23525/23525 [==============================] - 646s 27ms/step - loss: 0.0377 - accuracy: 0.9895 - val_loss: 0.0212 - val_accuracy: 0.9939

Bây giờ ta thử eval trên dữ liệu test – dữ liệu unseen- xem kết quả ra sao nhé:

# Kiểm tra model với dữ liệu mới
model.evaluate(X_test, y_test)

Kết quả eval với loss = 0.011 và accuracy khá cao 0.996:

7842/7842 [==============================] - 21s 3ms/step
[0.011262154533938626, 0.9968120455741882]

Như vậy là model cũng khá ổn rồi! Vui quá anh em ah!

OK! Như vậy mình đã guide anh em làm một model classify biển báo đơn giản. Anh em có thể modify, áp dụng transfer learning hay bơm dữ liệu biển báo Việt Nam vào cho thực tế!

Hẹn gặp lại các bạn trong các bài tiếp theo nhé!

Hãy join cùng cộng đồng Mì AI nhé!

Fanpage: http://facebook.com/miaiblog
Group trao đổi, chia sẻ: https://www.facebook.com/groups/miaigroup
Website: https://miai.vn/
Youtube: http://bit.ly/miaiyoutube

Cảm ơn bài tham khảo tuyệt vời tại đây.

Tags:

biển báobiển báo giao thôngCNNdeep learningdetectionnhận diện biển báophân loại biển báo giao thôngtraffic signtraffic sign classify
Author

Chủ tiệm Mì

Follow Me
Other Articles
Previous

[DA-DS] Triển khai mô hình dự báo đơn giản (Chương 1/2)

Next

[DA-DS] Triển khai mô hình dự báo đơn giản (Chương 2/2)

21 Comments
  1. Xây dựng hệ thống nhận diện biển báo giao thông bằng Retinanet - Mì AI says:
    April 1, 2021 at 9:07 am

    […] ví dụ về nhận diện biển báo giao thông, bài phân loại biển báo thì có rồi : Tại đây) nên hôm nay mình triển món này. Retinanet được đánh giá là khá ổn trong việc […]

    Reply
  2. Lê Anh says:
    May 10, 2021 at 12:09 am

    cho mình xin code hoàn chỉnh của bài toán phân loại biển báo giao thông bằng deep learning CNN, cảm ơn ad

    Reply
    1. Nguyễn Chiến Thắng says:
      May 10, 2021 at 11:38 am

      Code để ngay trong bài đó bạn!

      Reply
  3. medillo says:
    June 3, 2021 at 3:10 pm

    ảnh giải nén ra đuôi .ppm mình ko xem được ảnh ạ

    Reply
    1. Nguyễn Chiến Thắng says:
      June 12, 2021 at 11:33 pm

      Không, phải convert tiếp á! Trong code anh có!

      Reply
      1. Lê Minh says:
        June 7, 2023 at 4:45 pm

        cho mình xin địachỉ mail đc k?

        Reply
        1. Nguyễn Chiến Thắng says:
          July 28, 2023 at 10:12 am

          Email mình là thangnch@gmail.com nhé!

          Reply
  4. DuyTran says:
    October 1, 2021 at 10:51 am

    anh ơi có video hướng dẫn không anh

    Reply
    1. Nguyễn Chiến Thắng says:
      October 2, 2021 at 8:55 pm

      Bài này anh lại chưa có. Em cần gì hỗ trợ post lên Group trao đổi, chia sẻ: https://facebook.com/groups/miaigroup nhé!

      Reply
      1. Nguyễn Nhung says:
        December 1, 2021 at 3:57 pm

        để làm được bài này trên NVIDIA của Jetson TX2 cần chuẩn bị những gì, em là người mới toanh chưa biết gì, mong anh chỉ bảo!

        Reply
        1. Nguyễn Chiến Thắng says:
          December 3, 2021 at 8:54 pm

          Em post lên Group trao đổi, chia sẻ: https://facebook.com/groups/miaigroup trao đổi cho dễ nha!

          Reply
  5. thảo says:
    October 30, 2021 at 4:08 pm

    anh ơi, anh cho em hỏi có cách nào tình được khoảng cách từ biển báo đến camera không ạ

    Reply
    1. Nguyễn Chiến Thắng says:
      November 1, 2021 at 3:51 pm

      Ca này khoai đó, anh chưa ngâm cứu được. Em post lên Group trao đổi, chia sẻ: https://facebook.com/groups/miaigroup trao đổi thêm nhé!

      Reply
  6. Nguyễn Trọng Kính says:
    November 29, 2022 at 6:51 pm

    anh có bài nào làm về nhận diện kí tự quang học ứng dụng mạng nơ ron nhân tạo koo ạ

    Reply
    1. Nguyễn Chiến Thắng says:
      January 16, 2023 at 5:38 pm

      Anh chưa. Sắp tới nhé! Nhiều bạn đã làm rồi đó, em post lên Group trao đổi, chia sẻ: https://facebook.com/groups/miaigroup tìm xem!

      Reply
  7. Đinh Hào says:
    March 19, 2023 at 10:35 am

    Anh ra video hướng dẫn bài này được không ạ

    Reply
    1. Nguyễn Chiến Thắng says:
      May 9, 2023 at 11:02 am

      Ok để anh ngâm cứu nhé!

      Reply
  8. Đinh Hào says:
    March 24, 2023 at 9:57 pm

    a cho em hỏi là bài này a làm trên gg colab hay pycharm ạ

    Reply
    1. Nguyễn Chiến Thắng says:
      May 9, 2023 at 11:02 am

      Làm ở đâu cũng được em.Nếu làm trên Colab thì phải upoload dữ liệu lên!

      Reply
  9. Tháiii says:
    May 10, 2024 at 10:45 am

    anh ơi cái tensorflow==1.15.0 nó không hỗ trợ nữa và keras==2.3.1 không tương thích với tensorflow mới nhất.. Vậy em nên chỉnh keras thành mấy chấm để tương thích hả anh

    Reply
    1. Nguyễn Chiến Thắng says:
      May 30, 2024 at 9:23 am

      Em post lên Group trao đổi, chia sẻ: https://facebook.com/groups/miaigroup nhé!

      Reply
Show Comments

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • Tìm hiểu và cài đặt OpenClaw – trợ lý ảo 24/7 thông minh đa chức năng – Mì Ai
  • Dùng thử Pika – robot học Tiếng Anh cho trẻ cực đỉnh – Mì AI
  • TopView.AI 4.0 – nền tảng tạo AI video cộng tác bá đạo – Mì AI
  • Storm MCP – giải pháp nhanh gọn nhẹ để có MCP Server trong 5 phút – Mì AI
  • VoxCPM thử voice cloning với checkpoint finetune Tiếng Việt – Mì AI

Recent Comments

  1. Chủ tiệm Mì on Thử xây dựng hệ thống Agentic AI với LangGraph – Mì AI
  2. Nguyễn Chiến Thắng on [Nhận diện biển số xe] Chương 3 – Phát hiện biển số bằng OpenCV thuần
  3. Trần Sơn Dương on [Nhận diện biển số xe] Chương 3 – Phát hiện biển số bằng OpenCV thuần
  4. Salomon on [CV] Thử làm model cảnh báo ngủ gật cho tài xế oto bằng Dlib và Resnet
  5. khang on Xây dựng hệ thống nhận diện thủ ngữ – ngôn ngữ ký hiệu tay – để giao tiếp với người khuyết tật

Categories

  • Basic
  • Computer Vision
  • Data Science – Data Analysis
  • Generative AI
  • MÌ ÚP
  • Natural Language Processing
  • RNN-LSTM-GRU
  • Share Data

Là người đi trước, hãy biết đưa tay lại phía sau.

Nguyễn Chiến Thắng
Cảm ơn các bạn đã ủng hộ Mì AI!