Nhận diện biển số xe Việt Nam

1. Lời mở đầu 2. Chuẩn bị dataset pip install labelImg 3. Các bước thực hiện

Phương pháp mình giới thiệu lần này bao gồm 4 bước:

Xác định vùng chứa biển số xe sử dụng Yolo Tiny v3

Sử dụng thuật toán segment để tách từng kí tự trên biển số xe

Xây dựng một model CNN để phân loại các kí tự(characters classification)

Định dạng lại biển số xe xác định biển số xe gồm một hay hai dòng.

3.1 Xác định vùng chứa biển số xe sử dụng Yolo Tiny v3 from imutils import perspective LpRegion = perspective.four_point_transform(image_original, pts)

Ảnh 1: So sánh giữa phương pháp crop và bird’s eyes view transformation

3.2. Segment tách từng kí tự trên biến số xe

Đầu tiên ta sẽ chuyển màu ảnh từ BGR sang HSV. Ở một số lời giải khác cho bài toán này, mình thường thấy sử dụng màu GRAY thay cho HSV. Mình đã thử nhưng cho độ chính xác không cao vì HSV biểu diễn một màu dựa trên 3 số liệu:

H(Hue): vùng chứa màu sắc

S(Saturation): độ bão hòa

V(Value): độ sáng

nên khi ta muốn sử dụng một ngưỡng độ sáng của từng pixel để lọc ra các kí tự, thì với HSV ta dễ dàng dùng riêng rẽ giá trị độ sáng (V) còn với màu GRAY ta không thể làm việc đó vì nó biểu diễn màu dựa trên chung một giá trị.

Sau đó ta sử dụng adaptive threshold để làm nổi bật những phần mà ta muốn lấy(màu đen). Bạn tưởng tượng adaptive threshold sử dụng những cửa sổ nhỏ đi từ trái sang phải, trên xuống dưới và nó sẽ lấy những giá trị pixel nào lớn hơn giá trị trung bình(threshold) với một giá trị offset mà ta điều chỉnh. Khác với các kiểu threshold truyền thống áp dụng ngưỡng cho toàn bộ ảnh, adaptive threshold áp dụng cho từng vùng nhỏ nhờ đó hoạt động tốt hơn với điều kiện ánh sáng kém. Sau đó lấy những giá trị nào lớn hơn ngưỡng.

Và đây là kết quả của bước xử lý này trông cũng khá ngon lành đúng không?

Ảnh 2

Để tách từng kí tự ra khỏi biển số xe, ta sử dụng thuật toán Connected components analysis. Thuật toán này có ý tưởng đơn giản là nó sẽ kết nối tất cả pixel nào có cùng giá trị thành một khối và gắn cho nó một cái nhãn(label). Nhờ đó tất cả các pixel của cùng một kí tự do có cùng giá trị sẽ được kết nối và được tách ra khỏi biển số xe. Tuy nhiên để tiện xử lý thì mình convert toàn bộ màu trắng thành đen và ngược lại. Đồng thời cũng làm mờ ảnh để loại những nhiễu tròn vì có thể nó làm kí tự gắn liền với những bộ phận mình không mong muốn và thuật toán Connected components analysis (CCA) sẽ bị ảnh hưởng.

Sau khi thực hiện CCA, ta thu được một dãy các giá trị labels bao gồm các kí tự, các nhiễu không mong muốn(khung biển số xe, dấu gạch ngang, dấu chấm, …) và background(có label = 0 theo mặc định của hàm label ). Do đó đầu tiên chúng ta loại bỏ các label của background sau đó áp dụng hàm findContours để tạo các contours bao quanh các kí tự cũng như các nhiễu. Do ở bước này các giá trị thu được ngoài kí tự còn có cả nhiễu do đó ta thiết lập các giá trị ngưỡng để loại bỏ nhiễu. Ở đây ta sử dụng ngưỡng đối với ba đại lượng: aspect ratio(tỉ lệ rộng / dài), solidity(tỉ lệ diện tích phần contour bao quanh kí tự và hình chữ nhật bao quanh kí tự) và height ratio(tỉ lệ chiều dài kí tự / chiều dài biển số xe). Nếu sử dụng phương pháp deep learning phân loại thì tốn thời gian bởi lượng nhiễu là rất lớn. Chúng ta chỉ cần tinh chỉnh những tham biến này tùy tập dữ liệu đã có thể nhanh chóng loại bỏ phần lớn nhiễu một cách đơn giản, lấy ra ảnh kí tự trên biển số xe mong muốn. Sau đó ta đưa về dạng (28, 28, 1) là kích thước input đầu vào của mạng CNN bước 3 và ta cũng thêm tọa độ (x, y) của từng chữ cái để dùng tại bước 4.

Ảnh 3: Kết quả bước 2

3.3. Phân loại các kí tự sử dụng model CNN

Ở Việt Nam, trên biển số xe chấp nhận 31 ký tự bao gốm cả chữ và chữ số(0-9). Tuy nhiên, ở kết quả bước 2 mặc dù ta đã sử dụng ngưỡng để loại bỏ nhiễu nhưng vẫn có một số nhiễu vẫn lọt qua vì nó có kích thước hình dáng đủ tiêu chuẩn như kí tự thường. Do có số lượng ít nên ở bước này mình thêm một class là background để dùng model CNN phân loại đâu là ký tự đâu là nhiễu. Vậy tổng các class cần phân loại là 32.

Datasets để huấn luyện model ở đây mình gặp hai vấn đề. Thứ nhất là datasets có sẵn như MNIST thì quá đẹp nhưng khi vào môi trường thực tế với điều kiện ánh sáng yếu thì kí tự thu được sẽ bị méo mó chút như ảnh 3. Và vấn đề thứ hai là font chữ nước ngoài khác font chữ Việt Nam. Hai yếu tố này sẽ tác động đến chất lượng của model classification(phân loại). Do đó mình đã từ datasets có sẵn về biển số xe Việt Nam mình gen ra dữ liệu kí tự để đảm bảo chất lượng mô hình.

Sau đó mình xây dựng một model CNN đơn giản để tiến hành trích xuất đặc trưng và phân loại. Các bạn có thể xem file này tại file chúng tôi trên github của mình. Model này được thiết kế với các số filters tăng dần [32, 64, 64] để sao cho càng gần về output không gian đặc trưng giảm dần nhưng số lượng cách học (= số filters) tăng dần. Tùy độ phức tạp của dữ liệu mà chúng ta có thể thay đổi. Cuối cùng ta sử dụng một layer flatten và một activation softmax để phân loại. 32 ở đây chính là số class ta đề cập bên trên.

3.4 Xác định biển số xe gồm một hay hai dòng

Ở bước cuối cùng này, ta sử dụng tọa độ (x, y) trên mỗi kí tự ta đã đề cập ở bước 3. Bạn hãy tưởng tượng mặt phẳng tọa độ xOy trong đó x là trục ngang, y là trục dọc. Nếu biển số xe gồm một dòng thì tọa độ y (trục dọc)giữa các kí tự thu được sẽ nhỏ hơn một ngưỡng. Còn nếu biển hai dòng thì tọa độ y giữa các kí tự sẽ lớn hơn ngưỡng. Sau đó ta sử dụng giá trị x để xác định thứ tự trước sau sắp xếp các kí tự từ trái qua phải từ trên xuống dưới.

4. Kết quả

Project nhận diện biển số xe này của mình có thể hoạt động trên cả biển một dòng hoặc hai dòng. Thậm chí đôi khi biển số xe bị che khuất một chút vẫn đọc được.

Ảnh 4: Kết quả

Tuy nhiên, nó vẫn có một số nhược điểm:

Khi ảnh đầu vào bị đặt một góc quá nghiên thì một vài kí tự sẽ bị nhầm dòng. Có một cách giải quyết là dùng một mạng transformer xoay ảnh nghiêng về ảnh thẳng.

Đôi khi bị nhận dạng nhầm giữa 8 và B, 0 và D

Hoạt động kém khi bức ảnh quá mờ

All Rights Reserved