mở đầu, chương này sẽ đưa ra các vấn đề thực tiễn, những thứ còn tồn đọng trong một bãi giữ xe thông thường từ đó đưa ra các cách giải quyết khác nhau, vận dụng những kiến thức đã học để áp dụng vào các bài toán thực tế. Chương 2: Cơ sở lý thuyết: Chương tiếp theo sẽ trình bày chi tiết các khái niệm cơ bản nhất để người đọc có thể hình dung được, lượng kiến thức được đưa ra trong chương này là nền tảng để nắm rõ được các quy trình, thiết kế trong chương tiếp theo, các cơ sở lý thuyết được trình bày rất cơ bản, tổng quan cho người đọc về xử lý ảnh sử dụng thư viện OpenCV, QR Code và các luồng xử lý khi thực hiện mã hóa và giải mã một QR Code, tiếp đến sẽ là các khái niệm cơ bản về cơ sở dữ liệu, về khái niệm của các giao thức HTTP và HTTPS và thiết kế API theo chuẩn Restful API để giao tiếp đọc và trả dữ liệu từ server về bộ xử lý ở bãi giữ xe. Chương 3: Thiết kế mô hình: Mô hình là một phần không thể thiếu khi xây dựng một hệ thống dù lớn hay nhỏ, chương này sẽ đưa đến cho người đọc một cái nhìn tổng quan về cách hệ thống xử lý như thế nào, luồng đi của dữ liệu, luồng đi của API, thiết kế hệ thống, thiết kế server, thiết kế giao tiếp raspberry pi 4 với esp32 cam, sử dụng API để giao tiếp với server. Chương 4: Kết quả: 18 Nhóm thực hiện sẽ đánh giá mô hình thông qua mục tiêu đề tài đã được đề ra ở chương đầu tiên, các chức năng, phần cứng và phần mềm có hoạt động tốt hay không.
Đưa ra nhận xét và xác định những vấn đề đã được giải quyết ở chương đầu tiên nêu ra. Chương 5: Kết luận và hướng phát triển: Từ chương 4 nối tiếp đến chương này nhóm thực hiện sẽ đưa ra kết luận mô hình có thực hiện hóa được ở ngoài đời thực không, các sai số liệu có ảnh hưởng đến quá trình giữ xe của bãi hay không. 19 CHƯƠNG 2 CƠ SỞ LÝ THUYẾT 2.1 TỔNG QUAN VỀ THƯ VIỆN OPENCV 2.1 OpenCV là gì? OpenCV là một mã nguồn mở (open source) về thị giác máy tính. Mã nguồn này được viết bằng ngôn ngữ lập trình C và C++, nó được chạy được với cả ba hệ điều hành hiện nay là Linux, Windows và Mac OS X.
Đã có nhưng phiên bản được phát triển cho các ngôn ngữ lập trình khác như Python, Ruby, Matlab và các loại ngôn ngữ khác, trong đề tài này nhóm thực hiện việc đọc biển số sử dụng ngôn ngữ lập trình Python. Các mã nguồn liên quan sẽ được đề cập ở chương 3 phần thiết kế phần mềm. OpenCV được thiết kế để tối ưu hiệu quả tính toán và tập trung mạnh vào phần xử lý thời gian thực (real-time applications). OpenCV được tối ưu với ngôn ngữ C và xử lý được đa lõi (multicore processors).
Một trong những thành công của OpenCV chính là cung cấp những thứ cần thiết và dễ sử dụng để giúp người sử dụng xây dựng một ứng dụng thị giác phức tạp một cách nhanh chóng. OpenCV cung cấp gần 500 hàm tổng quát hết cách lĩnh vực thị giác máy tính bao gồm việc giám sát sản phẩm của nhà máy, y tế, an ninh, giao diện người dùng (user interface), hiệu chỉnh máy ảnh, v.v… Hiện nay thì thị giác máy tính (Computer Vision) và máy học (Machine Learning) sẽ đi đôi với nhau nên OpenCV có đầy đủ các chức năng với các mục đích cơ bản về máy học [1].2 Kiến trúc của OpenCV OpenCV được chia thành 5 phần cấu trúc chính, 4 trong 5 phần chính sẽ được thể hiện qua hình 2.1 bên dưới: 20 Hình 2.1: Kiến trúc cơ bản của OpenCV [1] Hình 2.1 thể hiện kiến trúc cơ bản của OpenCV. Đầu tiên là phần CV chứa những thứ cơ bản về xử lý ảnh và các thuật toán cao cấp về thị giác máy tính. Thứ hai, MLL là thư viện về máy học (Machine learning library) trong thư viện này chứa các công cụ phân loại và thống kê.
Phần tử kế tiếp sẽ là HighGUI, phần này sẽ chứa những quy trình và hàm sử dụng ngoại vi (I/O – Input/Output) để chứa và tải các hình ảnh, videos và cuối cùng sẽ là CXCore chứa những cấu trúc dữ liệu cơ bản và nội dung của nó.1 sẽ không bao gồm phần tử CvAux, phần này chủ yếu liên quan về nhận diện khuôn mặt, các phông nền nên nhóm thực hiện sẽ không nêu chi tiết quá về phần này [1].2 XỬ LÝ ẢNH VỚI OPENCV 2.1 Tổng quan OpenCV được viết bằng C++ và các phần trình bày tiếp theo sẽ đi sâu vào từng hàm bên trong để phân tích cũng như hiểu rõ hơn cấu trúc giải thuật của OpenCV viết bằng C sẽ như thế nào, qua đến chương tiếp theo nhóm sẽ sử dụng OpenCV nhưng ở ngôn ngữ Python để rút gọn thời gian viết mã lại cũng như các thư viện của OpenCV ở ngôn ngữ Python đều cung cấp đầy đủ các hàm giống như OpenCV viết bằng C++, Python OpenCV chứa bên trong là Engine gốc của OpenCV (tức là viết dưới tầng sâu là ngôn ngữ C++) và các hàm sẽ gọi nhau 21 thông qua API để giao tiếp giữa hai ngôn ngữ cũng như rút ngắn được thời gian viết mã.2 Đọc hình ảnh từ đầu vào OpenCV cung cấp cho những tính năng như đọc hình ảnh từ video và camera. Những tính năng này là một phần được cài đặt sẵn ở bên trong gói OpenCV. Đối với ngôn ngữ C một ví dụ đơn giản được trình bày dưới đây.2: Hàm đọc hình ảnh đầu vào [1] Khi biên dịch và chạy chương trình, hệ thống sẽ nhận đầu vào là hình ảnh và hiển thị nó trên màn hình. Sau đấy sẽ đợi tác động phím bấm bất kỳ từ bàn phím của người dùng, thì lúc này chương trình sẽ tắt cửa sổ và thoát chương trình.
Hàm cvLoadImage() là một hàm cấp cao xác định được nội dung sẽ tải lên dựa vào tên của file, nó cũng tự động cấp phát vùng bộ nhớ cho cấu trúc dữ liệu của hình ảnh. Lưu ý rằng cvLoadImage() có thể xử lý đọc được nhiều loại định dạng hình ảnh như BMP, DIB, JPEG, JPE, PNG, PBM, PGM, PPM, SR, RAS và TIFF. Một con trỏ (pointer) trỏ tới phần vùng chứa của cấu trúc dữ liệu hình ảnh đó. Cấu trúc này được gọi là IplImage, đây sẽ là thứ sẽ gặp thường xuyên trong OpenCV.
OpenCV sửa dụng hầu hết các cấu trúc này để xử lý tất cả các loại hình ảnh. Một hàm cao cấp tiếp theo đó là cvNamedWindow() là mở một cửa sổ ở trên màn và nội dung trong đấy sẽ chứa hình ảnh vừa được đọc. Tiếp ở trường hợp sau, cửa sổ sẽ tự điều chỉnh tự cân bằng với độ rộng của màn hình thông qua hàm cvShowImage(). Tiếp đến hàm cvWaitKey(0) yêu cầu chương trình sẽ dừng lại và đợi tác động ngoại vi (ở đây là bàn phím hoặc nhấp chuột).
Tham số có thể truyền vào khi gọi hàm có thể là số âm hoặc dương, đối với số dương truyền vào thì chương trình sẽ đợi theo đơn vị ms theo số dương đã truyền vào và sẽ tiếp túc chạy 22 chương trình nếu không có phím nào được tác động, còn đối với số 0 hoặc số âm, chương trình sẽ dừng hẵn đợi khi nào có tác động từ bàn phím thì mới tiếp tục chạy những chức năng sau. Sau khi đã đọc được hình ảnh và muốn không hiện nữa thì việc giải phóng bộ nhớ là cần thiết, OpenCV cung cấp cho ta hàm để thực hiện điều đó là hàm cvReleaseImage(&img), sau khi truyền chiếu đến tham số img và gọi hàm thì giá trị con trỏ lúc này là IplImage* sẽ được chuyển thành NULL. Việc đóng cửa sổ window giờ chỉ cần gọi hàm cvDestroyWindow() để đóng lại cửa sổ và sẽ hủy cấp phát bộ nhớ mà chương trình đã sử dụng bao gồm cả cấp phát bộ nhớ cho cấu trúc dữ liệu hình ảnh.3 Smoothing Smoothing hay còn gọi là làm mịn, hoặc có thể gọi là blurring (làm mờ) là một kỹ thuật đơn giản và sử dụng thường xuyên trong quá trình xử lý ảnh. Có rất nhiều lý do để làm mịn ảnh nhưng thường thì kỹ thuật này sẽ được dùng để loại bỏ nhiễu (noise) hoặc lỗi sọc từ camera ảnh.
Làm mịn cũng là một phần quan trọng nếu chúng ta muốn cải thiện chất lượng của ảnh theo một cách có nguyên tắc. Ở đề tài này sẽ tập trung vào làm mờ ảnh bằng bộ lọc Gaussian. Bộ lọc Gaussian (CV_GAUSSIAN), là một bộ lọc rất hữu dụng nhưng tốc độ lọc không phải là nhanh nhất. Bộ lọc Gaussian sẽ thực hiện bằng cách tích chập mỗi điểm ở ngõ vào của một cấu trúc mảng với nhân kernel của Gaussian và sau đó tổng hợp lại để tạo thành một mảng đầu ra.
Cú pháp gọi hàm theo ngôn ngữ Python là cv.3: Bộ lọc Gaussian mảng 1 chiều. [1] Hình trên thể hiện bộ lọc Gaussian ở mảng pixel một chiều, phương pháp làm mờ sửa dụng Gaussian, hai tham số đầu vào sẽ là độ rộng và cao của bộ lọc cửa sổ và một tham số tùy chọn thứ ba đó là giá trị sigma (một nữa độ rộng ở giữa giá trị tối đa) của nhân kernel Gaussian. Nếu tham số thứ 3 không có thì Gaussian sẽ tự động xác định kích thước của window thông qua công thức: 𝑛𝑥 𝜎𝑥 = ( − 1) × 0.80, 𝑛𝑦 = 𝑝𝑎𝑟𝑎𝑚2 2 Nếu muốn nhân Kernel đối xứng, có thể thêm một tham số thứ 4 để làm việc đó, trong trường hợp này thì tham số thứ 3 và tham số thứ 4 sẽ là giá trị của sigma ở trục hoành và trục tung. Nếu trong trường hợp tham số 3 và 4 được xác định giá trị nhưng tham số 1 và 2 thì không thì kích thước của cửa sổ sẽ được xác định tự động dựa trên giá trị từ sigma theo công thức ở trên.
Triển khai bộ lọc Gausian thông qua OpenCV cũng tối ưu hóa hiệu suất hơn cho nhân kernels, 3 với 3, 5 với 5 và 7 với 7, với một tham số 3 đầu vào mặc định là (0.0) sẽ cho một hiệu suất tốt hơn những nhân kernels thực hiện cách khác. Bộ lọc Gaussian hỗ trợ từ chạy từ một đến ba channel hình ảnh cho dù hình 24 ảnh có là định dạng 8-bit, 32-bit hoặc có định dạng floating-point (một định dạng biểu diễn giá trị thập phân gần đúng).4: Hình ảnh đã qua xử lý bộ lọc Gaussian. [1] Ở hình trên bên tay trái là hình ảnh gốc trước khi xử lý qua bộ lọc Gaussian, hình bên tay phải là hình ảnh sau khi đã xử lý thông qua bộ lọc Gaussian và cho ra được kết quả.