Viết chương trình nhận diện khuôn mặt đơn giản với thư viện dlib

21
Le Hải Bang viết gần 6 năm trước

Chào các bạn, nhân đợt này đang ngâm cứu về hệ thống nhận diện khuôn mặt, mình sẽ giới thiệu với các bạn viết một chương trình nhận diện khuôn mặt đơn giản dùng ngôn ngữ Python với thư viện dlib. Chương trình của chúng ta sẽ nhận đầu vào là một bức ảnh và cần đánh dấu trên bức ảnh đâu là vùng có khuôn mặt (bằng các khung bao hình chữ nhật).

1. Cài đặt thư viện dlib

Trước tiên chúng ta sẽ cài đặt thư viện dlib. Dlib là một thư viện C++ cài đặt nhiều giải thuật xử lý ảnh cho các bài toán khác nhau, trong đó có bài toán nhận diện khuôn mặt.

Trên mạng có rất nhiều bài hướng dẫn cài đặt dlib trên các môi trường khác nhau các bạn có thể tham khảo, ví dụ như ở đây. Trong phần này mình sẽ chỉ hướng dẫn cách cài đặt dlib trên Ubuntu 16.04 với Python 3.5.

Lưu ý: Mình đã thử cài bản mới nhất của dlib hiện tại là bản 19.13, tuy nhiên khi import thư viện thì bị lỗi chưa giải quyết được (cụ thể thì là lỗi này). Nếu các bạn cài đặt với Python bản 3.6 hoặc mới hơn thì sẽ không bị vấn đề này, nên nếu các bạn muốn dlib bản mới nhất thì có thể cài với Python bản 3.6 hoặc mới hơn. Dưới đây mình sẽ hướng dẫn các bạn cài dlib bản 19.7 để có thể chạy được với Python 3.5.

Trước tiên chúng ta cài đặt các gói cần thiết

$ sudo apt-get  update
$ sudo apt-get  install build-essential cmake
$ sudo apt-get  install libopenblas-dev liblapack-dev
$ sudo apt-get  install libx11-dev libgtk-3-dev
$ sudo apt-get  install python3-dev python3-pip
$ sudo apt-get install libpng16-dev libjpeg9-dev libjpeg9

Tiếp theo các bạn tạo virtualenv mới và cài đặt dlib 19.7. Với các bạn chưa biết virtualenv thì nôm na nó là công cụ để tạo ra các môi trường ảo riêng rẽ giúp chúng ta quản lý các thư viện Python trên các dự án khác nhau dễ dàng hơn. Nếu bạn phát triển các dự án với Python thì việc tạo virtualenv riêng rẽ cho mỗi dự án luôn luôn là cần thiết.

$ virtualenv --system-site-packages -p /usr/bin/python3 ~/virtualenvs/dlib-test
$ source ~/virtualenvs/dlib-test/bin/activate
$  pip install mkl
$  pip install dlib==19.7

Tiếp theo chúng tá sửa biến môi trường $LD_LIBRARY_PATH :

$ export LD_LIBRARY_PATH=/usr/local/lib:$HOME/virtualenvs/dlib-test/lib:$LD_LIBRARY_PATH

Đến đây việc cài đặt dlib đã hoàn tất, các bạn có thể kiểm tra thông qua python cli:

$ source ~/virtualenvs/dlib-test/bin/activate
$ python
Python 3.5.2 (default, Nov 23 2017, 16:37:01) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dlib
>>> dlib.__version__
'19.7.0'

2. Viết chương trình nhận dạng khuôn mặt dùng thư viện dlib

Chương trình của chúng ta sẽ dùng thêm hai thư viện khác là numpyPillow, các bạn có thể cài đặt các thư viện này bằng pip:

$ source ~/virtualenvs/dlib-test/bin/activate
$ pip install numpy
$ pip install Pillow

Thư viện dlib cung cấp hai giải thuật cho bài toán nhận dạng khuôn mặt, một giải thuật dùng phương pháp học máy cổ điển và giải thuật mới hơn dùng deep learning. Phương pháp cổ điển có ưu điểm là cần ít phép tính toán hơn và do đó không yêu cầu phần cứng cấu hình cao, tuy nhiện độ chính xác thì kém hơn phương pháp dùng deep learning.

Phía dưới mình có viết đoạn code đơn giản các bạn có thể copy vào một file main.py để chạy thử và xem kết quả. Để sử dụng phương pháp cổ điển các bạn dùng lệnh:

$ source ~/virtualenvs/dlib-test/bin/activate
$ python main.py /path/to/your/image

Để sử dụng phương pháp deep learning, các bạn thêm tham số --use_cnn_detector. Chú ý là trước khi chạy các bạn phải tải về tệp mmod_human_face_detector.dat và nhập vào đường dẫn tương của file ở dòng 18 (ở đoạn code phía dưới thì mình đang lưu tệp ở thư mục ./model_data). Một lưu ý nữa là khi sử dụng phương pháp deep learning thì máy bạn nên có GPU, nếu không có thể treo máy khi chạy. Nếu máy các bạn có RAM từ 8Gb trở lên thì cũng có thể chạy được nhưng sẽ phải đợi khá lâu mới có kết quả do phương pháp deep learning cần lượng tính toán rất nhiều.

$ source ~/virtualenvs/dlib-test/bin/activate
$ python main.py /path/to/your/image --use_cnn_detector

Code mẫu

import dlib  
from PIL import Image  
import numpy  
import argparse  

parser = argparse.ArgumentParser()  
parser.add_argument('image_path', type=str, help='path to image file')  
parser.add_argument('--use_cnn_detector', help='Force to use CNN detector, default detector is the classical one', action='store_true')  

if __name__ == '__main__':  
    # Get path to image from arguments  
    args = parser.parse_args()  
    image_path = args.image_path  

    # Decide which detector to use, default is to use classical detector  
    if args.use_cnn_detector:  
        detector_model_path = './model_data/mmod_human_face_detector.dat'  
        face_detector = dlib.cnn_face_detection_model_v1(detector_model_path)  
    else:  
        face_detector = dlib.get_frontal_face_detector()  

    # Read image from file  
    image = numpy.array(Image.open(image_path))  

    # Run face detector and output bounding boxes  
    dets = face_detector(image, 1)  

    # Display results  
    win = dlib.image_window()  

    print("Number of faces detected: {}".format(len(dets)))  
    if args.use_cnn_detector:  
        for i, d in enumerate(dets):  
            print("Detection {}: Left: {} Top: {} Right: {} Bottom: {} Confidence: {}".format(  
                i, d.rect.left(), d.rect.top(), d.rect.right(), d.rect.bottom(), d.confidence))  

        rects = dlib.rectangles()  
        rects.extend([d.rect for d in dets])  
    else:  
        for i, d in enumerate(dets):  
            print("Detection {}: Left: {} Top: {} Right: {} Bottom: {}".format(  
                i, d.left(), d.top(), d.right(), d.bottom()))  

        rects = dets  

    win.clear_overlay()  
    win.set_image(image)  
    win.add_overlay(rects)  
    dlib.hit_enter_to_continue()

3. Một vài kết quả

Mình có thử 2 phương pháp với một vài ảnh trên mạng và được kết quả như dưới đây (Ảnh trên là kết quả khi dùng phương pháp cổ điển, ảnh dưới là kết quả khi dùng deep learning). Với 2 ảnh đầu thì 2 phương pháp đều cho ra kết quả tốt, mặc dù vị trí các khung bao có khác nhau một chút. Với ảnh thứ 3 thì kết quả có sự khác biệt, trong khi phương pháp cổ điển không phát hiện ra mặt anh chàng Neville Longbottom và bạn nữ phía bên trái Harry thì phương pháp deep learning lại tìm được, tuy nhiên với hai khuôn mặt ở phía sau thì phương pháp deep learning lạ không phát hiện được trong khi phương pháp cổ điển lại phát hiện ra. Điều này cũng khá bình thường với các giải thuật học máy, đó là không có phương pháp nào tốt hơn mọi phương pháp khác trong mọi trường hợp.

Ảnh 1 (https://secure.i.telegraph.co.uk/multimedia/archive/01645/emma-watson_1645925c.jpg)

emma
emma-cnn

Ảnh 2 (https://nerdist.com/wp-content/uploads/2017/09/harry-potter-promo-image.jpeg)

harry1
harry1-cnn

Ảnh 3 (https://hips.hearstapps.com/hmg-prod.s3.amazonaws.com/images/harry-potter-1513869637.jpg?crop=1xw:1xh;center,top&resize=768:*)

harry2
harry2-cnn

Tham khảo

Bình luận


White
{{ comment.user.name }}
Hay Bỏ hay
{{ comment.like_count}}
White

Le Hải Bang

51 bài viết.
0 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}

  Cùng một tác giả


{{like_count}}

kipalog

{{ comment_count }}

Bình luận


White
{{userFollowed ? 'Following' : 'Follow'}}
51 bài viết.
0 người follow

 Đầu mục bài viết

 Cùng một tác giả