Cân bằng histogram

Một phần của tài liệu Xây dựng trung tâm xử lý cho tòa nhà thông minh trên hệ thống nhúng linux (Trang 69 - 81)

Ta có thể dễ dàng thực hiện cân bằng histogram để cải thiện độ tương phản và độ sáng của ảnh, bằng cách sử dụng hàm equalizeHist(). Đôi khi việc

cân bằng này sẽ làm cho ảnh đầu ra trông rất lạ, nhưng nói chung nó sẽ cải thiện độ sáng và độ tương phản và giúp nhận dạng khuôn mặt được tốt hơn. Hàm equalizeHist() có thể được sử dụng như sau:

3.1.2.4 Phát hiện khuôn mặt

Bây giờ ta đã chuyển đổi ảnh sang ảnh xám, thu nhỏ ảnh, và cân bằng biểu đồ histogram, và sẵn sàng để phát hiện những khuôn mặt bằng cách sử dụng hàm CascadeClassifier::detectMultiScale(). Có rất nhiều thông số

mà chúng ta cần đưa vào hàm này:

 minFeatureSize: Tham số này xác định kích thước khuôn mặt tối thiểu mà ta quan tâm, thông thường là 20 x 20 hoặc 30 x 30 pixel nhưng điều này phụ thuộc vào trường hợp và kích thước ảnh. Do ta thực hiện để

Trang 62

nhận dạng ở nơi khuôn mặt rất gần với hệ thống chụp ảnh của Raspi, nên ta có thể để giá trị là 80x80 để việc phát hiện nhanh hơn

 searchScaleFactor: Các tham số xác định có bao nhiêu kích thước khuôn mặt khác nhau cần tìm kiếm, thường sẽ là 1.1 để phát hiện tốt hơn, hoặc 1.2 để phát hiện nhanh hơn nhưng cũng có thể là không tìm được khuôn mặt nào.

 minNeighbors: tham số này xác định việc chắc chắn rằng đã phát hiện ra một khuôn mặt, thường giá trị của nó là 3 nhưng ta có thể thiết lập nó cao hơn nếu muốn khuôn mặt phát hiện được là đáng tin cậy hơn, thậm chí ngay cả khi nhiều gương mặt có thể không được phát hiện.

 flags: Tham số này cho phép ta xác định xem là tìm tất cả các khuôn mặt (mặc định) hoặc chỉ tìm kiếm những khuôn mặt lớn nhất (CASCADE_FIND_BIGGEST_OBJECT). Nếu chỉ tìm kiếm các gương mặt lớn nhất, thì nó sẽ thực hiện nhanh hơn. Có một số thông số khác ta có thể thêm để làm cho việc phát hiện nhanh hơn khoảng một phần trăm đến hai phần trăm, chẳng hạn như CASCADE_DO_ROUGH_SEARCH hoặc CASCADE_SCALE_IMAGE.

Đầu ra của hàm detectMultiScale() sẽ là giá trị std::vector của loại đối

tượng cv::Rect. Ví dụ, nếu phát hiện ra hai khuôn mặt thì khi đó nó sẽ lưu một mảng 2 cv::Rect ở đầu ra. Hàm detectMultiScale() được sử dụng như sau:

Chúng ta có thể biết được nếu có khuôn mặt nào đã được phát hiện bằng cách nhìn vào số phần tử được lưu trữ trong vector, bằng cách sử dụng các hàm objects.size()

Trang 63

Như đã đề cập trước đó, nếu chúng ta thu ảnh nhỏ lại để phát hiện khuôn mặt, thì kết quả cũng sẽ được thu hẹp lại, vì vậy ta cần phải phóng to nó nếu muốn biết các vùng của khuôn mặt so với ảnh ban đầu. Ta cũng cần phải chắc chắn rằng khuôn mặt trên biên ảnh hoàn toàn ở trong ảnh:

Bây giờ chúng ta có một khuôn mặt nằm trong hình chữ nhật, ta có thể sử dụng nó với nhiều cách, chẳng hạn như là trích xuất hoặc cắt ảnh chứa khuôn mặt từ ảnh ban đầu. đoạn mã sau đây cho phép ta truy cập vào khuôn mặt đã được phát hiện ra:

Hình 3.2 cho thấy các hình chữ nhật điển hình có được từ bộ phát hiện khuôn mặt:

Trang 64

Hình 3.2. Ô vuông màu đỏ đánh dấu khuôn mặt được phát hiện

3.1.3 Xử lý dữ liệu khuôn mặt

Như đã đề cập ở phần trước, việc nhận dạng khuôn mặt là rất dễ bị ảnh hướng bởi điều kiện ánh sáng, tư thế của khuôn mặt, biểu cảm của khuôn mặt, và vv…, vì thế việc giảm những khác biệt này là rất quan trọng. Nếu không các thuật toán nhận dạng khuôn mặt thường sẽ cho rằng có sự giống nhau giữa khuôn mặt của hai người khác trong cùng điều kiện hơn là giữa hai mặt của cùng một người.

Hình thức đơn giản nhất của tiền xử lý khuôn mặt là áp dụng việc cân bằng biểu đồ histogram bằng cách sử dụng hàm equalizeHist(), giống với trong

việc phát hiện khuôn mặt. Phương pháp này có thể là phù hợp với một số chương trình nhận dạng mà ở đó ánh sáng và các điều kiện về vị trí không có sự thay đổi nhiều. Nhưng về độ tin cậy trong điều kiện thực tế, ta cần nhiều kỹ thuật phức tạp hơn, bao gồm việc phát hiện các đặc trưng của khuôn mặt (ví dụ, phát hiện đôi mắt, mũi, miệng và lông mày). Để đơn giản, trong phần này sẽ chỉ cần sử dụng phát hiện mắt và bỏ qua mặt tính năng khác như miệng và mũi vì 2 đặc trưng này ít quan trọng hơn. Hình

Trang 65

dưới đây mô tả một cái nhìn rộng hơn của một khuôn mặt điển hình đã được xử lý, bằng cách sử dụng kỹ thuật sẽ được đề cập trong phần này:

Hình 3.3. Khuôn mặt sau khi tiền xử lý

3.1.3.1 Phát hiện đôi mắt

Việc phát hiện đôi mắt có thể có ích cho việc tiền xử lý khuôn mặt, bởi vì đối với khuôn mặt nhìn thẳng thì ta luôn có đôi mắt của người đó phải nằm ngang và đối xứng với khuôn mặt và phải có một vị trí và kích thước khá chuẩn trong khuôn mặt, cho dù có những thay đổi trong nét mặt, điều kiện ánh sáng, đặc tính máy ảnh, khoảng cách đến máy ảnh, vv… Việc phát hiện ra đôi mắt cũng rất có ích để loại bỏ đi những phát hiện giả khi khuôn mặt phát hiện được là một thứ gì khác. Việc phát hiện sai ra khuôn mặt và đôi mắt cùng một lúc là rất hiếm.

Một số bộ phát hiện đôi mắt đã được huấn luyện trước được đi kèm với OpenCV v2.4 có thể phát hiện một mắt cho dù là mắt nhắm hay mở.

Bộ phát hiện đôi mắt cho cả trường hợp nhắm mắt và mở mắt:

 haarcascade_mcs_lefteye.xml (và haarcascade_mcs_righteye.xml)  haarcascade_lefteye_2splits.xml (và haarcascade_righteye_2splits.xml) Bộ phát hiện đôi mắt cho trường hợp mở mắt:

Trang 66  haarcascade_eye.xml

 haarcascade_eye_tree_eyeglasses.xml.

Do các bộ phát hiện đôi mắt nhắm hoặc mở chỉ xác định được mắt mà nó đã được huấn luyện, nên ta cần phải sử dụng bộ phát hiện mắt khác nhau cho mắt trái và mắt phải, trong khi đó các bộ phát hiện mắt chỉ mở có thể sử dụng để phát hiện ra cả hai mắt.

Với haarcascade_eye_tree_eyeglasses.xml có thể phát hiện ra mắt nếu người đó được đeo kính, nhưng nếu người đó không đeo kính thì bộ phát hiện này không đáng tin cậy. Nếu tên tập tin XML có ghi "mắt bên trái", có nghĩa là nó sẽ tìm mắt trái thực tế trên khuôn mặt của người, do đó, ảnh trong camera sẽ thường xuất hiện ở phía bên tay phải của khuôn mặt chứ không phải ở phía bên trái!

Danh sách các bộ phát hiện đôi mắt như đã trình bày được sắp xếp theo độ tin cậy từ cao xuống thấp, vì vậy nếu ta biết ta không cần phải tìm những người có đeo kính thì bộ phát hiện đầu tiên có lẽ là lựa chọn tốt nhất.

3.1.3.2 Các vùng tìm kiếm đôi mắt

Để phát hiện ra mắt trên khuôn mặt, điều quan trọng đó là ta nên cắt ảnh đầu vào chỉ để hiển thị các khu vực xung quanh mắt nhất đối với cả mắt trái và mắt phải, giống như với việc phát hiện khuôn mặt. Nếu ta thực hiện việc phát hiện mắt trên toàn bộ khuôn mặt hoặc trên toàn bộ ảnh thì khi đó việc phát hiện ra đôi mắt sẽ chậm hơn và ít tin cậy hơn nhiều. Các bộ phát hiện mắt khác nhau sẽ phù hợp hơn so với các vùng khác nhau trên khuôn mặt, ví dụ như haarcascade_eye.xml hoạt động tốt nhất nếu nó chỉ tìm kiếm trong khu vực xung quanh mắt thực tế nhất, trong khi

Trang 67

haarcascade_mcs_lefteye.xml và haarcascade_lefteye_2splits.xml sẽ làm việc hiệu quả nhất trên vùng rộng lớn xung quanh mắt.

Bảng 3.1 liệt kê một số vùng tìm kiếm tốt nhất trên khuôn mặt cho các bộ phát hiện mắt khác nhau (khi sử dụng mặt phát hiện LBP), bằng cách sử dụng các tọa độ của hình chữ nhật tương đối trên khuôn mặt đã được phát hiện:

Bảng 3.1. Các vùng tìm kiếm mắt tốt nhất đối với các bộ phát hiện khuôn mặt khác nhau

Bộ phân loại Cascade EYE_SX EYE_SY EYE_SW EYE_SH

haarcascade_eye.xml 0.16 0.26 0.30 0.28

haarcascade_mcs_lefteye.xml 0.10 0.19 0.40 0.36

haarcascade_lefteye_2splits.xml 0.12 0.17 0.37 0.36

Dưới đây là đoạn mã dùng để trích xuất các khu vực bên trái mắt và bên phải mắt từ trên một khuôn mặt đã được phát hiện:

Hình bên dưới cho thấy các khu vực tìm kiếm lý tưởng của các bộ phát hiện mắt khác nhau, trong đó haarcascade_eye.xml và haarcascade_eye_tree_eyeglasses.xml là tốt nhất với khu vực tìm kiếm nhỏ, trong khi haarcascade_mcs_*eye.xml và haarcascade_* eye_2splits.xml là tốt nhất với các khu vực tìm kiếm lớn hơn. Chú ý là khuôn mặt hình chữ nhật được phát hiện cũng được hiển thị, để biết được

Trang 68

các vùng tìm kiếm mắt trên khuôn mặt lớn như thế nào so với khuôn mặt được phát hiện:

Hình 3.4. Ảnh khuôn mặt được phát hiện cùng với đôi mắt

Khi sử dụng các vùng tìm kiếm mắt được liệt kê ở Bảng 3.2, đây là một số thuộc tính gần đúng của các bộ phát hiện mắt khác nhau:

Bảng 3.2. So sánh độ tin cậy và tốc độ giữa các bộ phát hiện đôi mắt

Bộ phân loại Cascade Độ tin cậy* Tốc độ** Tìm mắt khi Đeo kính

haarcascade_mcs_lefteye.xml 80% 18 msec Nhắm hoặc mở không

haarcascade_lefteye_2splits.xml 60% 7 msec Nhắm hoặc mở không

haarcascade_eye.xml 40% 5 msec Chỉ mở không

haarcascade_eye_tree_eyeglasses.xml 15% 10 msec Chỉ mở có

* Các giá trị tin cậy cho thấy mức độ thường xuyên mà cả hai mắt sẽ được phát hiện sau khi phát hiện khuôn mặt (nhìn thẳng) theo phương pháp LBP

Trang 69

khi không có kính và hai mắt đều đang mở. Nếu nhắm mắt (có kính hoặc không) thì độ tin cậy cũng như tốc độ sẽ bị giảm xuống.

** Các giá trị tốc độ có đơn vị là mili giây đối với ảnh được thu nhỏ với kích thước 320 x 240 điểm ảnh trên bộ xử lý Intel Core i7 2.0 GHz (trung bình trên 1.000 ảnh). Tốc độ thường đạt nhanh hơn nhiều khi đôi mắt được tìm thấy hơn so với khi đôi mắt không được tìm thấy, vì khi đó nó phải quét toàn bộ ảnh, nhưng haarcascade_mcs_lefteye.xml vẫn còn chậm hơn nhiều so với các bộ phát hiện mắt khác.

Ví dụ, nếu ta thu nhỏ một ảnh 320 x 240 pixel và thực hiện cân bằng biểu đồ histogram cho nó, sử dụng bộ phát hiện khuôn mặt nhìn thẳng LBP, sau đó lấy ra vùng mắt trái, vùng mắt phải sử dụng các giá trị của haarcascade_mcs_lefteye.xml, rồi thực hiện cân bằng histogram trên từng vùng mắt. Sau đó, nếu ta sử dụng haarcascade_mcs_lefteye.xml để tìm mắt trái (vùng phía trên bên phải của ảnh) và sử dụng haarcascade_mcs_ righteye.xml để tìm mắt phải (phần trên bên trái của ảnh), thì mỗi bộ phát hiện mắt phải làm việc trong khoảng 90% các bức ảnh với phương pháp phát hiện khuôn mặt phía trước LBP.

Như ở trên ta nói rằng nên thu nhỏ ảnh trước khi phát hiện khuôn mặt, thì khi đó, ta sẽ phát hiện đôi mắt ở độ phân giải máy ảnh ban đầu bởi vì đôi mắt rõ ràng sẽ nhỏ hơn nhiều so với khuôn mặt, vì vậy ta cần có ảnh với độ phân giải càng cao càng tốt.

Dựa theo bảng, dường như khi lựa chọn bộ phát hiện mắt để sử dụng thì ta nên quyết định xem ta muốn phát hiện mắt nhắm hoặc chỉ phát hiện mở mắt. Và nhớ rằng, nếu bộ phát hiện mắt trước không thực hiện được thì ta có thể sử dụng bộ phát hiện khác phù hợp hơn.

Trang 70

Đối với nhiều nhiệm vụ, việc phát hiện ra đôi mắt là rất có ích cho dù mắt đang mở hoặc nhắm, vì vậy nếu tốc độ là không quan trọng thì tốt nhất là ta nên dùng bộ phát hiện mcs_*eye trước tiên, và nếu không được thì khi đó sẽ dùng đến bộ phát hiện eye_2splits.

Nhưng đối với việc nhận dạng khuôn mặt, một người sẽ xuất hiện hoàn toàn khác nếu mắt của họ nhắm lại, vì vậy tốt nhất là nên sử dụng haarcascade_eye để tìm trước, và nếu không được thì tìm kiếm với haarcascade_eye_tree_eyeglasses.

Chúng ta có thể sử dụng hàm detectLargestObject() tương tự với khi sử

dụng để nhận dạng khuôn mặt cho tìm kiếm đôi mắt, nhưng thay vì phải thu nhỏ ảnh trước khi bộ phát hiện mắt, chúng ta nên xác định chiều rộng vùng mắt đầy đủ để phát hiện đôi mắt được tốt hơn. việc tìm kiếm mắt trái sử dụng bộ phát hiện là rất dễ, và nếu không được thì khi đó ta có thể sử dụng bộ phát hiện khác (tương tự cho mắt phải). Việc phát hiện đôi mắt được thực hiện như sau:

Với khuôn mặt và cả hai mắt đã được phát hiện, ta sẽ thực hiện mặt tiền xử lý bằng cách kết hợp:

Trang 71

 Chuyển đổi hình học và cắt hình: Quá trình này sẽ bao gồm thay đổi tỉ lệ, xoay hình để ảnh có đôi mắt được nằm ngang, tiếp theo là việc cắt bỏ phần trán, cằm, tai, và phông nền ra khỏi khuôn mặt.

 Thực hiện cân bằng biểu đồ histogram một cách riêng biệt cho mặt trái và phải: Quá trình này là tiến hành chuẩn hóa độ sáng và độ tương phản trên cả bên trái và bên phải của khuôn mặt một cách độc lập.

 Làm mịn: Quá trình này làm giảm nhiễu ảnh bằng cách sử dụng một bộ lọc kép bilateral.

 Mặt nạ hình eclipse: Mặt nạ hình eclipse loại bỏ một số tóc và phông nền còn lại ra khỏi khuôn mặt.

Hình 3.5. Quá trình tiền xử lý khuôn mặt

Hình 3.5 cho thấy việc tiền xử lý khuôn mặt từ bước 1 đến bước 4 áp dụng cho một khuôn mặt đã được phát hiện. Chú ý ảnh cuối cùng có độ sáng và độ tương phản tốt trên cả hai phía của của khuôn mặt, trong khi ảnh gốc thì không.

3.1.3.3 Chuyển đổi hình học

Việc làm cho tất cả các khuôn mặt được sắp xếp, canh đều nhau là rất quan trọng, nếu không thì các thuật toán nhận dạng khuôn mặt có thể sẽ thực

Trang 72

hiện so sánh một phần của mũi với một phần của mắt. Để có sự sắp xếp, cân chỉnh tốt, ta sẽ sử dụng bộ phát hiện mắt để sắp xếp các khuôn mặt sao cho vị trí của hai mắt nằm hoàn hảo ở các vị trí mong muốn. ta sẽ làm việc chuyển đổi hình học bằng cách sử dụng hàm warpAffine(), hàm này sẽ thực hiện các việc sau:

 Xoay mặt để hai mắt đều nằm theo phương ngang.

 Biến đổi khuôn mặt lớn nhỏ để khoảng cách giữa hai mắt luôn luôn là như nhau.

 Dịch chuyển khuôn mặt để đôi mắt luôn nằm giữa theo chiều ngang và ở cùng độ cao mong muốn.

 Cắt các phần rìa của khuôn mặt, vì ta muốn cắt đi phông nền, mái tóc, trán, tai, và cằm.

Affine Warping dùng một ma trận affine để biến đổi vị trí hai điểm của mắt trên khuôn mặt sang vị trí hai điểm mong muốn, và sau đó tiến hàng cắt ảnh theo kích thước và vị trí mong muốn. Để tạo ra ma trận affine này, chúng ta sẽ lấy điểm giữa hai mắt, tính toán góc mà điểm của hai mắt phát hiện được so với phương ngang:

Trang 73

Bây giờ chúng ta có thể chuyển đổi khuôn mặt (xoay, phóng to thu nhỏ, và dịch chuyển) để vị trí của 2 mắt đã phát hiện nằm ở các vị trí mong muốn như sau:

Một phần của tài liệu Xây dựng trung tâm xử lý cho tòa nhà thông minh trên hệ thống nhúng linux (Trang 69 - 81)

Tải bản đầy đủ (PDF)

(106 trang)