- Điều kiện tiên quyết
- Các bước liên quan đến Nhận dạng biển số bằng Raspberry Pi
- 1. Phát hiện biển số xe
- 2. Phân đoạn ký tự
- 3. Nhận dạng ký tự
- Các trường hợp thất bại trong nhận dạng biển số
- Các ví dụ thành công khác
An ninh luôn là mối quan tâm lớn của nhân loại. Ngày nay chúng ta có camera giám sát video trong trường học, bệnh viện và mọi nơi công cộng khác để làm cho chúng ta cảm thấy an toàn. Theo một cuộc khảo sát của HIS, ước tính có khoảng 245 triệu camera an ninh được lắp đặt và hoạt động trở lại vào năm 2014, giống như cứ 30 người trên hành tinh này thì có một camera an ninh. Với sự tiến bộ trong công nghệ, đặc biệt là trong Xử lý hình ảnh và Học máy, có thể làm cho những máy ảnh này thông minh hơn bằng cách đào tạo chúng để xử lý thông tin từ nguồn cấp dữ liệu Video.
Nguồn cấp dữ liệu video từ các máy ảnh này có thể được sử dụng để thực hiện nhận dạng khuôn mặt, phân tích mẫu, phân tích cảm xúc và nhiều hơn thế nữa để thực sự đưa nó đến gần với thứ gì đó như “Mắt thần” được trình chiếu trong phim FF7. Trên thực tế, các công ty giám sát như Hikvision và nhiều công ty khác đã bắt đầu triển khai các tính năng này trong các sản phẩm của họ. Trước đây chúng ta đã sử dụng MATLAB Xử lý ảnh để đọc biển số, hôm nay trong bài này chúng ta sẽ học cách nhận biết và đọc Biển số xe ô tô bằng Raspberry Pi và OpenCV. Chúng tôi sẽ sử dụng một số hình ảnh phương tiện ngẫu nhiên từ Google và viết một chương trình để nhận dạng biển số bằng OpenCV Contour Detection và sau đó đọc số từ biển số bằng Tesseract OCR. Nghe có vẻ thú vị đúng không !, hãy bắt đầu thôi.
Điều kiện tiên quyết
Như đã nói trước đó, chúng tôi sẽ sử dụng Thư viện OpenCV để phát hiện và nhận dạng khuôn mặt. Vì vậy, hãy đảm bảo cài đặt Thư viện OpenCV trên Raspberry Pi trước khi tiếp tục với hướng dẫn này. Cũng cấp nguồn cho Pi của bạn bằng bộ chuyển đổi 2A và kết nối nó với màn hình hiển thị để gỡ lỗi dễ dàng hơn.
Hướng dẫn này sẽ không giải thích chính xác cách thức hoạt động của OpenCV, nếu bạn quan tâm đến việc tìm hiểu Xử lý ảnh thì hãy xem hướng dẫn xử lý ảnh cơ bản và nâng cao về OpenCV này. Bạn cũng có thể tìm hiểu về các đường viền, Phát hiện khối, v.v. trong hướng dẫn Phân đoạn Hình ảnh này bằng OpenCV. Chúng tôi sẽ làm điều gì đó tương tự như thế này để phát hiện biển số của chiếc xe từ hình ảnh.
Các bước liên quan đến Nhận dạng biển số bằng Raspberry Pi
Nhận dạng Biển số Giấy phép hoặc viết tắt là LPR, bao gồm ba bước chính. Các bước thực hiện như sau
1. Phát hiện biển số xe : Bước đầu tiên là phát hiện biển số xe ô tô. Chúng tôi sẽ sử dụng tùy chọn đường bao trong OpenCV để phát hiện các đối tượng hình chữ nhật để tìm biển số. Độ chính xác có thể được cải thiện nếu chúng ta biết chính xác kích thước, màu sắc và vị trí gần đúng của biển số. Thông thường, thuật toán phát hiện được đào tạo dựa trên vị trí của camera và loại biển số được sử dụng ở quốc gia cụ thể đó. Điều này trở nên phức tạp hơn nếu hình ảnh thậm chí không có ô tô, trong trường hợp này chúng tôi sẽ thực hiện thêm một bước để phát hiện ô tô và sau đó là biển số.
2. Phân đoạn ký tự: Khi chúng tôi đã phát hiện được Biển số, chúng tôi phải cắt nó ra và lưu nó thành một hình ảnh mới. Một lần nữa điều này có thể được thực hiện dễ dàng bằng OpenCV.
3. Nhận dạng ký tự: Bây giờ, hình ảnh mới mà chúng ta thu được ở bước trước chắc chắn có một số ký tự (Số / Bảng chữ cái) được viết trên đó. Vì vậy, chúng tôi có thể thực hiện OCR (Nhận dạng ký tự quang học) trên nó để phát hiện số. Chúng tôi đã giải thích về Nhận dạng ký tự quang học (OCR) bằng Raspberry Pi.
1. Phát hiện biển số xe
Bước đầu tiên trong Trình đọc biển số Raspberry Pi này là phát hiện Biển số. Chúng ta hãy chụp ảnh mẫu của một chiếc ô tô và bắt đầu với việc phát hiện Biển số trên chiếc ô tô đó. Sau đó, chúng tôi cũng sẽ sử dụng cùng một hình ảnh cho Phân đoạn ký tự và Nhận dạng ký tự. Nếu bạn muốn chuyển thẳng vào mã mà không cần giải thích thì bạn có thể cuộn xuống cuối trang này, nơi mã hoàn chỉnh được cung cấp. Hình ảnh thử nghiệm mà tôi đang sử dụng cho hướng dẫn này được hiển thị bên dưới.
Bước 1: Thay đổi kích thước hình ảnh theo kích thước yêu cầu và sau đó chuyển sang thang độ xám. Mã cho cùng một được cung cấp dưới đây
img = cv2.resize (img, (620,480)) gray = cv2.cvtColor (img, cv2.COLOR_BGR2GRAY) #convert to gray scale
Thay đổi kích thước chúng tôi giúp chúng tôi tránh mọi vấn đề với hình ảnh có độ phân giải lớn hơn, đảm bảo biển số vẫn còn trong khung sau khi thay đổi kích thước. Tỷ lệ màu xám là phổ biến trong tất cả các bước xử lý ảnh. Điều này tăng tốc quá trình sin khác mà chúng ta không còn phải đối phó với các chi tiết màu khi xử lý hình ảnh. Hình ảnh sẽ được biến đổi như thế này khi bước này hoàn thành
Bước 2: Mỗi hình ảnh sẽ có thông tin hữu ích và vô ích, trong trường hợp này đối với chúng tôi chỉ có biển số xe là thông tin hữu ích còn lại là khá nhiều vô ích cho chương trình của chúng tôi. Thông tin vô ích này được gọi là nhiễu. Thông thường sử dụng bộ lọc hai bên (Làm mờ) sẽ loại bỏ các chi tiết không mong muốn khỏi ảnh. Mã cho cùng là
xám = cv2.bilateralFilter (xám, 11, 17, 17)
Cú pháp là destination_image = cv2.bilateralFilter (source_image, đường kính pixel, sigmaColor, sigmaSpace). Bạn có thể tăng màu sigma và không gian sigma từ 17 lên các giá trị cao hơn để làm mờ nhiều thông tin nền hơn, nhưng hãy cẩn thận để phần hữu ích không bị mờ. Hình ảnh đầu ra được hiển thị bên dưới, vì bạn có thể thấy các chi tiết nền (cây và tòa nhà) bị mờ trong hình ảnh này. Bằng cách này, chúng ta có thể tránh chương trình tập trung vào các vùng này sau này.
Bước 3: Bước tiếp theo rất thú vị khi chúng tôi thực hiện phát hiện cạnh. Có nhiều cách để thực hiện, cách dễ dàng và phổ biến nhất là sử dụng phương pháp canny edge từ OpenCV. Dòng để làm tương tự được hiển thị bên dưới
edged = cv2.Canny (xám, 30, 200) #Perform Edge phát hiện
Cú pháp sẽ là destination_image = cv2.Canny (source_image, Ngưỡng giá trị 1, Giá trị ngưỡng cửa 2). Ngưỡng Vale 1 và Giá trị ngưỡng 2 là các giá trị ngưỡng tối thiểu và tối đa. Chỉ các cạnh có gradient cường độ lớn hơn giá trị ngưỡng tối thiểu và nhỏ hơn giá trị ngưỡng tối đa mới được hiển thị. Hình ảnh kết quả được hiển thị bên dưới
Bước 4: Bây giờ chúng ta có thể bắt đầu tìm kiếm đường viền trên hình ảnh của mình, chúng ta đã tìm hiểu về cách tìm đường viền bằng OpenCV trong hướng dẫn trước của chúng ta nên chúng ta cứ tiến hành tương tự.
nts = cv2.findContours (edged.copy (), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) cnts = imutils.grab_contours (cnts) cnts = sorted (cnts, key = cv2.contourArea, reverse = True) screenCnt = None
Khi bộ đếm đã được phát hiện, chúng tôi sắp xếp chúng từ lớn đến nhỏ và chỉ xem xét 10 kết quả đầu tiên bỏ qua những kết quả khác. Trong hình ảnh của chúng tôi, quầy có thể là bất cứ thứ gì có bề mặt kín nhưng trong tất cả các kết quả thu được, biển số xe cũng sẽ ở đó vì nó cũng là một bề mặt đóng.
Để lọc hình ảnh biển số xe trong số các kết quả thu được, chúng tôi sẽ lặp lại tất cả các kết quả và kiểm tra xem hình ảnh nào có đường bao hình chữ nhật với bốn cạnh và hình khép kín. Vì biển số xe chắc chắn sẽ là một hình chữ nhật có bốn cạnh.
# vòng lặp qua đường bao của chúng ta cho c trong cnts: # ước lượng đường bao quanh = cv2.arcLength (c, True) xấp xỉ = cv2.approxPolyDP (c, 0,018 * peri, True) # nếu đường bao gần đúng của chúng ta có bốn điểm, thì # we có thể giả định rằng chúng ta đã tìm thấy màn hình của mình nếu len (khoảng) == 4: screenCnt = khoảng ngắt
Giá trị 0,018 là giá trị thực nghiệm; bạn có thể chơi xung quanh nó để kiểm tra xem cái nào phù hợp nhất với bạn. Hoặc đưa nó lên cấp độ tiếp theo bằng cách sử dụng máy học để đào tạo dựa trên hình ảnh ô tô và sau đó sử dụng giá trị phù hợp ở đó. Khi chúng tôi đã tìm thấy bộ đếm phù hợp, chúng tôi lưu nó vào một biến có tên là screenCnt và sau đó vẽ một hộp hình chữ nhật xung quanh nó để đảm bảo rằng chúng tôi đã phát hiện đúng biển số xe.
Bước 5: Bây giờ chúng ta đã biết biển số ở đâu, những thông tin còn lại khá nhiều vô ích đối với chúng ta. Như vậy chúng ta có thể tiến hành che toàn bộ bức tranh trừ chỗ để biển số. Mã để làm điều tương tự được hiển thị bên dưới
# Che phần không phải mặt nạ biển số = np.zeros (gray.shape, np.uint8) new_image = cv2.drawContours (mask,, 0,255, -1,) new_image = cv2.bitwise_and (img, img, mask = mặt nạ)
Hình ảnh mới có mặt nạ sẽ xuất hiện như bên dưới
2. Phân đoạn ký tự
Bước tiếp theo trong Nhận dạng biển số Raspberry Pi là phân đoạn biển số xe ra khỏi hình ảnh bằng cách cắt nó và lưu nó thành một hình ảnh mới. Sau đó, chúng tôi có thể sử dụng hình ảnh này để phát hiện ký tự trong đó. Mã để cắt hình ảnh roi (Vùng quan tâm) hình ảnh chính được hiển thị bên dưới
# Bây giờ crop (x, y) = np.where (mask == 255) (topx, topy) = (np.min (x), np.min (y)) (bottomx, bottomy) = (np.max (x), np.max (y)) Đã cắt = màu xám
Hình ảnh kết quả được hiển thị bên dưới. Thường được thêm vào để cắt hình ảnh, chúng tôi cũng có thể tô xám và tạo cạnh nếu cần. Điều này được thực hiện để cải thiện nhận dạng ký tự trong bước tiếp theo. Tuy nhiên, tôi thấy rằng nó hoạt động tốt ngay cả với hình ảnh gốc.
3. Nhận dạng ký tự
Bước cuối cùng trong Nhận dạng biển số Raspberry Pi này là thực sự đọc thông tin biển số từ hình ảnh được phân đoạn. Chúng tôi sẽ sử dụng gói pytesseract để đọc các ký tự từ hình ảnh, giống như chúng tôi đã làm trong hướng dẫn trước. Mã cho cùng một được cung cấp dưới đây
# Đọc bảng số text = pytesseract.image_to_string (Đã cắt, config = '- psm 11') print ("Số được Phát hiện là:", text)
Chúng tôi đã giải thích cách định cấu hình công cụ Tesseract, vì vậy, ở đây một lần nữa nếu cần, chúng tôi có thể định cấu hình Tesseract OCR để thu được kết quả tốt hơn nếu cần. Sau đó, ký tự được phát hiện sẽ được in trên bảng điều khiển. Khi biên dịch, kết quả được hiển thị như bên dưới
Như bạn có thể thấy hình ảnh gốc có số “HR 25 BR9044” trên đó và chương trình của chúng tôi đã phát hiện nó in cùng một giá trị trên màn hình.
Các trường hợp thất bại trong nhận dạng biển số
Bạn có thể tải xuống tệp hoàn chỉnh của dự án Raspberry Pi License Plate Recognition này từ đây, nó chứa chương trình và các hình ảnh thử nghiệm mà chúng tôi đã sử dụng để kiểm tra chương trình của mình. Không cần nói, cần nhớ rằng kết quả từ phương pháp này sẽ không chính xác . Độ chính xác phụ thuộc vào sự trong sáng của hình ảnh, định hướng, tiếp xúc với ánh sáng vv. Để có được kết quả tốt hơn, bạn có thể thử triển khai các thuật toán Máy học cùng với điều này.
Để có ý tưởng, hãy xem một ví dụ khác mà chiếc xe không đối diện trực tiếp với camera.
Như bạn có thể thấy, chương trình của chúng tôi có thể phát hiện biển số xe một cách chính xác và cắt nó. Nhưng thư viện Tesseract đã không thể nhận dạng các ký tự một cách chính xác. Thay vì "TS 08 UE 3396" thực tế, OCR đã nhận dạng nó là "1508 ye 3396". Các vấn đề như thế này có thể được khắc phục bằng cách sử dụng hình ảnh định hướng tốt hơn hoặc bằng cách định cấu hình công cụ Tesseract .
Một trường hợp xấu nhất khác là khi đường bao không phát hiện được biển số xe một cách chính xác. Hình ảnh dưới đây có quá nhiều thông tin cơ bản và ánh sáng xấu khiến chương trình thậm chí không thể xác định được biển số xe từ số. Trong trường hợp này, chúng tôi phải chuyển tiếp lại Máy học hoặc cải thiện chất lượng của hình ảnh.
Các ví dụ thành công khác
Hầu hết các lần chất lượng và hướng hình ảnh là chính xác, chương trình có thể xác định biển số xe và đọc số từ nó. Ảnh chụp nhanh dưới đây cho thấy một số kết quả thành công thu được. Một lần nữa, tất cả các hình ảnh thử nghiệm và mã được sử dụng ở đây sẽ có sẵn trong tệp ZIP được cung cấp tại đây.
Hy vọng bạn đã hiểu Nhận dạng biển số tự động bằng Raspberry Pi và thích tự mình xây dựng một thứ gì đó thú vị. Bạn nghĩ có thể làm gì khác với OpenCV và Tesseract ?, hãy cho tôi biết suy nghĩ của bạn trong phần bình luận. Nếu bạn có bất kỳ câu hỏi nào liên quan đến bài viết này, vui lòng để lại chúng trong phần bình luận bên dưới hoặc sử dụng diễn đàn cho các câu hỏi kỹ thuật khác.