+6

Xây Dựng WebApp Đọc Biển Số Xe Sử Dụng YOLOv6 + Tesseract OCR + Streamlit

Giới thiệu bài toán

Phát hiện biển số xe là công nghệ thị giác máy tính cho phép tự động nhận dạng biển số xe trong hình ảnh hoặc luồng video. Nó có nhiều ứng dụng khác nhau trong quản lý giao thông, thực thi bãi đậu xe, thực thi pháp luật và thu phí. Các thuật toán phát hiện biển số xe sử dụng các kỹ thuật máy học để xác định vị trí của biển số xe trong hình ảnh và trích xuất các ký tự chữ và số từ biển số. Quá trình phát hiện biển số xe bao gồm một số bước, bao gồm tiền xử lý hình ảnh, phát hiện đối tượng, phân đoạn ký tự và nhận dạng ký tự quang học. Các bước này có thể được thực hiện bằng nhiều thuật toán và kỹ thuật khác nhau, tùy thuộc vào các yêu cầu cụ thể của dự án. Hệ thống phát hiện biển số xe thường được thiết kế để xử lý các điều kiện môi trường khác nhau, chẳng hạn như điều kiện ánh sáng thay đổi, khoảng cách khác nhau giữa máy ảnh và xe cũng như bối cảnh đa dạng. Hiệu suất của hệ thống phát hiện biển số xe có thể được đánh giá dựa trên các chỉ số như độ chính xác, độ chính xác, thu hồi và tốc độ xử lý. Nhìn chung, phát hiện biển số xe là một công nghệ quan trọng trong lĩnh vực thị giác máy tính, với nhiều ứng dụng trong thế giới thực. Độ chính xác và tốc độ của nó đã được cải thiện đáng kể trong những năm gần đây nhờ những tiến bộ trong thuật toán máy học và phần cứng.

Bài viết này được tài trợ bởi DevUP

DevUP tự hào khi được cung cấp các khóa học chuyên sâu, sự kiện, cơ hội về ngành Công nghệ thông tin tới quý khách hàng với sứ mệnh tiên phong, kiến tạo, nâng cao năng lực công nghệ tại Việt Nam!

Triển khai

Để xây dựng WebApp đọc biển số xe thì Chúng Ta cần thực hiện các bước sau:

  • Bước 1: Huấn luyện dữ liệu với YOLOv6
  • Bước 2: Nhận diện thông tin biển số xe với Tesseract OCR
  • Bước 3: Triển khai với Web app

Nào cùng bắt đầu nhé !

Bước 1: Huấn luyện dữ liệu với YOLOv6

Chuẩn bị dữ liệu

Có khác nhiều các bộ dataset về phát hiện biển số xe trong bài viết này Mình sẽ sử dụng bộ dữ liệu của Kaggle. Các bạn download tại đây nhé!

# BibTeX
@misc{make ml,
title={Car License Plates Dataset},
url={https://makeml.app/datasets/cars-license-plates},
journal={Make ML}}

Huấn luyện mô hình YOLOv6

Bộ dữ liệu này được gán nhãn theo định dạng VOC. Nên Mình đã fork lại YOLOv6 để viết hàm chuyển đổi định dạng VOC labels sang YOLO. Các bạn làm theo hướng dẫn trong file car_detection.ipynb nhé!

# Thực thi voc2yolo custom dataset
%cd /content/drive/MyDrive/manhquang/devup/bien_so_xe/YOLOv6
!python yolov6/data/voc2yolo_custom_dataset.py --path_yaml /content/drive/MyDrive/manhquang/devup/bien_so_xe/YOLOv6/data/dataset.yaml
# train
%cd /content/drive/MyDrive/manhquang/devup/bien_so_xe/YOLOv6
!python tools/train.py --batch 32 \
--conf /content/drive/MyDrive/manhquang/devup/bien_so_xe/YOLOv6/configs/yolov6s.py \
--data /content/drive/MyDrive/manhquang/devup/bien_so_xe/YOLOv6/data/dataset.yaml --device 0
# Inference 
%cd /content/drive/MyDrive/manhquang/devup/bien_so_xe/YOLOv6
!python tools/infer.py \
--weights /content/drive/MyDrive/manhquang/devup/bien_so_xe/YOLOv6/runs/train/exp2/weights/best_ckpt.pt \
--source /content/drive/MyDrive/manhquang/devup/bien_so_xe/custom_dataset/images/val/Cars404.png \
--device 0 \
--yaml /content/drive/MyDrive/manhquang/devup/bien_so_xe/YOLOv6/data/dataset.yaml \
--save-txt

Sau khi train thì các bạn hãy lưu lại weights của mô hình nhé !

Tham khảo weight mình tự train tại đây.

Bước 2: Nhận diện thông tin biển số xe với Tesseract OCR

Tesseract là một nền tảng nhận dạng ký tự quang học (OCR) mã nguồn mở. OCR trích xuất văn bản từ hình ảnh và tài liệu mà không có lớp văn bản và xuất tài liệu thành tệp văn bản có thể tìm kiếm mới, PDF hoặc hầu hết các định dạng phổ biến khác. Tesseract có khả năng tùy biến cao và có thể hoạt động bằng hầu hết các ngôn ngữ, bao gồm cả tài liệu đa ngôn ngữ và văn bản dọc. Mặc dù phần mềm có thể được sử dụng trên Windows hoặc Linux, hướng dẫn này sẽ dựa trên hệ điều hành Mac được thực hiện thông qua ứng dụng đầu cuối.

Chỉ với 1 dòng code với pytesseract bạn đã có thể đọc được thông tin của biển số xe.

def segment_image(plate):
    # # Chuyen anh bien so ve gray
    # plate = cv2.cvtColor(plate, cv2.COLOR_RGB2GRAY)
    #
    # # # Ap dung threshold de phan tach so va nen
    # ret, threshold = cv2.threshold(plate, 255, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)

    text = pytesseract.image_to_string(plate, lang="eng", config="--psm 7")
    # text = fine_tune(text)
    return text

Bước 3: Triển khai với WebApp Streamlit

Streamlit là một khung ứng dụng web dựa trên ngôn ngữ Python để trực quan hóa dữ liệu và phân tích kết quả một cách hiệu quả và linh hoạt hơn.

Đầu tiên thì Mình sẽ Implement lại hàm infer của yolov6 để trả về kết quả như mong muốn:

def infer(self, source, conf_thres=0.25, iou_thres=0.45, classes=None, agnostic_nms=False, max_det=1000, obj_name="car_licence"):
	img, img_src = self.precess_image(source, self.img_size, self.stride, self.half)
	img = img.to(self.device)

	if len(img.shape) == 3:
        img = img[None]
	# expand for batch dim
	pred_results = self.model(img)
	det = non_max_suppression(pred_results, conf_thres, iou_thres, classes, agnostic_nms, max_det=max_det)[0]
	img_frame_ori, crop_objs = img_src.copy(), []
	if len(det):
        det[:, :4] = self.rescale(img.shape[2:], det[:, :4], img_src.shape).round()
        for *xyxy, conf, cls in reversed(det):
            class_num = int(cls)  # integer class
            label = f'{self.class_names[class_num]} {conf:.2f}'
            self.plot_box_and_label(img_src, max(round(sum(img_src.shape) / 2 * 0.003), 2), xyxy, label, color=(255,0,0))
            if self.class_names[class_num] == obj_name:
                box = torch.tensor(xyxy).view(1, 4).view(-1).tolist()
                x1, y1, x2, y2 = int(box[0]), int(box[1]), int(box[2]), int(box[3])
                crop_img = img_frame_ori[y1:y2, x1:x2]
                dim = (90, 40)
                crop_img_resize = cv2.resize(crop_img, dim, interpolation=cv2.INTER_LINEAR)
                crop_objs.append(crop_img_resize)
        img_src = np.asarray(img_src)
    return len(det), img_src, np.array(crop_objs)

Tiếp theo mình sẽ xây dựng giao diện cho WebApp:

def back_ground():
    st.title("NHẬN DIỆN BIỂN SỐ XE - DEVUP")
    image_data, image_bytes = get_upload_file(title="Chọn tệp đầu vào")

    with st.form("display_video_form"):
        submitted = st.form_submit_button("Bắt Đầu Xử Lý")
        if submitted:
            # xu ly detection
            sta_res, frame_res, objs_res = yolov6_model.infer(image_data, conf_thres=0.6, iou_thres=0.45)
            if sta_res != 0:
                st.subheader("Kết quả chuẩn đoán")
                st.image(frame_res)
                for obj in objs_res:
                    st.image(obj)
                    result = segment_image(obj)
                    st.write("BIỂN SỐ XE : ", result)
        pass

Hình ảnh demo giao diện hệ thống:

image

Vậy là Mình đã hướng dẫn các bạn làm hệ thống phát hiện biển số xe đơn giản, hi vọng các bạn sẽ học được điều gì đó từ bài viết này 😄

Tài liệu tham khảo


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.