Thứ tư, 27/03/2019 | 00:00 GMT+7

Cách phát hiện và trích xuất khuôn mặt từ một image bằng OpenCV và Python

Hình ảnh chiếm một lượng lớn dữ liệu được tạo ra mỗi ngày, điều này làm cho khả năng xử lý những hình ảnh này trở nên quan trọng. Một phương pháp xử lý hình ảnh là thông qua nhận diện khuôn mặt . Nhận diện khuôn mặt là một nhánh của xử lý hình ảnh sử dụng máy học để phát hiện khuôn mặt trong hình ảnh.

Haar Cascade là một phương pháp phát hiện đối tượng được sử dụng để định vị đối tượng quan tâm trong hình ảnh. Thuật toán được đào tạo trên một số lượng lớn các mẫu âm và dương, trong đó các mẫu dương là hình ảnh có chứa đối tượng quan tâm. Mẫu âm bản là hình ảnh có thể chứa bất kỳ thứ gì ngoại trừ đối tượng mong muốn. Sau khi được đào tạo, bộ phân loại sau đó có thể định vị đối tượng quan tâm trong bất kỳ hình ảnh mới nào.

Trong hướng dẫn này, bạn sẽ sử dụng mô hình Haar Cascade được đào tạo trước từ OpenCVPython để phát hiện và extract khuôn mặt từ hình ảnh. OpenCV là một thư viện lập trình open-souce được sử dụng để xử lý hình ảnh.

Yêu cầu

Bước 1 - Cấu hình Môi trường local

Trước khi bạn bắt đầu viết mã của bạn , trước tiên bạn sẽ tạo một không gian làm việc để chứa mã và cài đặt một số phụ thuộc.

Tạo một folder cho dự án bằng mkdir :

  • mkdir face_scrapper

Thay đổi vào folder mới tạo:

  • cd face_scrapper

Tiếp theo, bạn sẽ tạo một môi trường ảo cho dự án này. Môi trường ảo cô lập các dự án khác nhau để các phụ thuộc khác nhau sẽ không gây ra bất kỳ gián đoạn nào. Tạo một môi trường ảo có tên face_scrapper để sử dụng với dự án này:

  • python3 -m venv face_scrapper

Kích hoạt môi trường bị cô lập:

  • source face_scrapper/bin/activate

Đến đây bạn sẽ thấy rằng dấu nhắc của bạn có tiền tố là tên môi trường ảo của bạn:

Đến đây bạn đã kích hoạt môi trường ảo của bạn, bạn sẽ sử dụng nano hoặc soạn thảo văn bản yêu thích của bạn để tạo ra một requirements.txt file . Tệp này chỉ ra các phụ thuộc Python cần thiết:

  • nano requirements.txt

Tiếp theo, bạn cần cài đặt ba phụ thuộc để hoàn thành hướng dẫn này:

  • numpy : numpy là một thư viện Python bổ sung hỗ trợ cho các mảng lớn, nhiều chiều. Nó cũng bao gồm một bộ sưu tập lớn các hàm toán học để hoạt động trên các mảng.
  • opencv-utils : Đây là thư viện mở rộng cho OpenCV bao gồm các hàm trợ giúp.
  • opencv-python : Đây là module OpenCV cốt lõi mà Python sử dụng.

Thêm các phần phụ thuộc sau vào file :

request.txt
numpy  opencv-utils opencv-python 

Lưu và đóng file .

Cài đặt các phụ thuộc bằng cách truyền requirements.txt file cho người quản lý gói Python, pip . Các -r cờ xác định vị trí của requirements.txt file .

  • pip install -r requirements.txt

Trong bước này, bạn cài đặt một môi trường ảo cho dự án của bạn và cài đặt các phụ thuộc cần thiết. Đến đây bạn đã sẵn sàng để bắt đầu viết mã để phát hiện khuôn mặt từ hình ảnh đầu vào trong bước tiếp theo.

Bước 2 - Viết và chạy Tập lệnh dò tìm khuôn mặt

Trong phần này, bạn sẽ viết mã lấy một hình ảnh làm đầu vào và trả về hai thứ:

  • Số lượng khuôn mặt được tìm thấy trong hình ảnh đầu vào.
  • Hình ảnh mới với ô hình chữ nhật xung quanh mỗi khuôn mặt được phát hiện.

Bắt đầu bằng cách tạo một file mới để giữ mã của bạn:

  • nano app.py

Trong file mới này, hãy bắt đầu viết mã của bạn bằng lệnh các thư viện cần thiết trước. Bạn sẽ nhập hai module ở đây: cv2sys . Mô-đun cv2 nhập thư viện OpenCV vào chương trình và sys nhập các hàm Python phổ biến, chẳng hạn như argv , mà mã của bạn sẽ sử dụng.

app.py
import cv2 import sys 

Tiếp theo, bạn sẽ chỉ định rằng hình ảnh đầu vào sẽ được chuyển làm đối số cho tập lệnh trong thời gian chạy. Cách Pythonic để đọc đối số đầu tiên là gán giá trị được trả về bởi hàm sys.argv[1] cho một biến:

app.py
... imagePath = sys.argv[1] 

Một thực tế phổ biến trong xử lý hình ảnh là trước tiên chuyển hình ảnh đầu vào sang thang màu xám. Điều này là do việc phát hiện độ sáng, trái ngược với màu sắc, nói chung sẽ mang lại kết quả tốt hơn trong việc phát hiện đối tượng. Thêm mã sau để lấy hình ảnh đầu vào làm đối số và chuyển nó thành thang độ xám:

app.py
... image = cv2.imread(imagePath) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) 

Hàm .imread() nhận hình ảnh đầu vào, được chuyển làm đối số cho tập lệnh và chuyển đổi nó thành một đối tượng OpenCV. Tiếp theo, .cvtColor() của OpenCV chuyển đổi đối tượng hình ảnh đầu vào thành một đối tượng thang độ xám.

Đến đây bạn đã thêm mã để tải hình ảnh, bạn sẽ thêm mã phát hiện khuôn mặt trong hình ảnh được chỉ định:

app.py
... faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml") faces = faceCascade.detectMultiScale(         gray,         scaleFactor=1.3,         minNeighbors=3,         minSize=(30, 30) )   print("Found {0} Faces!".format(len(faces)))  

Đoạn mã này sẽ tạo một đối tượng faceCascade sẽ tải file Haar Cascade với phương thức cv2.CascadeClassifier . Điều này cho phép Python và mã của bạn sử dụng Haar Cascade.

Tiếp theo, mã áp dụng phương thức .detectMultiScale() của OpenCV trên đối tượng faceCascade . Điều này tạo ra một danh sách các hình chữ nhật cho tất cả các khuôn mặt được phát hiện trong hình ảnh. Danh sách các hình chữ nhật là tập hợp các vị trí pixel từ hình ảnh, ở dạng Rect(x,y,w,h) .

Dưới đây là tóm tắt về các thông số khác mà mã của bạn sử dụng:

  • gray : Điều này chỉ định việc sử dụng đối tượng hình ảnh thang độ xám OpenCV mà bạn đã tải trước đó.
  • scaleFactor : Tham số này chỉ định tỷ lệ giảm kích thước hình ảnh ở mỗi tỷ lệ hình ảnh. Mô hình của bạn có tỷ lệ cố định trong quá trình đào tạo, vì vậy hình ảnh đầu vào có thể được thu nhỏ để cải thiện khả năng phát hiện. Quá trình này dừng lại sau khi đạt đến giới hạn ngưỡng, được xác định bởi maxSizeminSize .
  • minNeighbors : Tham số này chỉ định số lượng lân cận hoặc phát hiện, mỗi hình chữ nhật ứng viên phải có để giữ lại nó. Giá trị cao hơn có thể dẫn đến ít dương tính giả hơn, nhưng giá trị quá cao có thể loại bỏ dương tính thực.
  • minSize : Điều này cho phép bạn xác định kích thước đối tượng tối thiểu có thể được đo bằng pixel. Các đối tượng nhỏ hơn tham số này bị bỏ qua.

Sau khi tạo một danh sách các hình chữ nhật, các mặt sẽ được đếm bằng hàm len . Sau đó, số lượng khuôn mặt được phát hiện sẽ được trả lại dưới dạng kết quả sau khi chạy tập lệnh.

Tiếp theo, bạn sẽ sử dụng phương thức .rectangle() của OpenCV để vẽ một hình chữ nhật xung quanh các khuôn mặt được phát hiện:

app.py
... for (x, y, w, h) in faces:     cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)  

Mã này sử dụng vòng lặp for để lặp qua danh sách các vị trí pixel được trả về từ phương thức faceCascade.detectMultiScale cho mỗi đối tượng được phát hiện. Phương thức rectangle sẽ nhận bốn đối số:

  • image cho mã để vẽ các hình chữ nhật trên hình ảnh đầu vào ban đầu.
  • (x,y), (x+w, y+h) là bốn vị trí pixel cho đối tượng được phát hiện. rectangle sẽ sử dụng chúng để định vị và vẽ các hình chữ nhật xung quanh các đối tượng được phát hiện trong hình ảnh đầu vào.
  • (0, 255, 0) là màu của hình dạng. Đối số này được chuyển như một bộ giá trị cho BGR. Ví dụ, bạn sẽ sử dụng (255, 0, 0) cho màu xanh lam. Ta đang sử dụng màu xanh lá cây trong trường hợp này.
  • 2 là độ dày của đường được đo bằng pixel.

Đến đây bạn đã thêm mã để vẽ các hình chữ nhật, hãy sử dụng phương thức .imwrite() của OpenCV để ghi hình ảnh mới vào hệ thống file local của bạn dưới dạng faces_detected.jpg . Phương thức này sẽ trả về true nếu ghi thành công và false nếu không thể ghi hình ảnh mới.

app.py
... status = cv2.imwrite('faces_detected.jpg', image) 

Cuối cùng, thêm mã này để in trả về trạng thái true hoặc false của hàm .imwrite() cho console . Điều này sẽ cho bạn biết nếu ghi thành công sau khi chạy tập lệnh.

app.py
... print ("Image faces_detected.jpg written to filesystem: ",status) 

Tệp đã hoàn thành sẽ giống như sau:

app.py
import cv2 import sys  imagePath = sys.argv[1]  image = cv2.imread(imagePath) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml") faces = faceCascade.detectMultiScale(     gray,     scaleFactor=1.3,     minNeighbors=3,     minSize=(30, 30) )  print("[INFO] Found {0} Faces!".format(len(faces)))  for (x, y, w, h) in faces:     cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)  status = cv2.imwrite('faces_detected.jpg', image) print("[INFO] Image faces_detected.jpg written to filesystem: ", status) 

Khi bạn đã xác minh mọi thứ đã được nhập chính xác, hãy lưu file .

Lưu ý: Mã này được lấy từ tài liệu OpenCV có sẵn công khai.

Mã của bạn đã hoàn tất và bạn đã sẵn sàng chạy tập lệnh.

Bước 3 - Chạy tập lệnh

Trong bước này, bạn sẽ sử dụng một hình ảnh để kiểm tra tập lệnh của bạn . Khi bạn tìm thấy hình ảnh bạn muốn sử dụng để kiểm tra, hãy lưu hình ảnh đó vào cùng folder với tập lệnh app.py của bạn. Hướng dẫn này sẽ sử dụng hình ảnh sau:

Hình ảnh đầu vào của bốn người nhìn vào điện thoại

Nếu bạn muốn kiểm tra với cùng một hình ảnh, hãy sử dụng lệnh sau để download :

  • curl -O /image_static/mg_sid_64/586c/6c60/586c6c60696968/586c6c60696968.png

Khi bạn có hình ảnh để kiểm tra tập lệnh, hãy chạy tập lệnh và cung cấp đường dẫn hình ảnh làm đối số:

  • python app.py path/to/input_image

Khi tập lệnh chạy xong, bạn sẽ nhận được kết quả như sau:

Output
[INFO] Found 4 Faces! [INFO] Image faces_detected.jpg written to filesystem: True

Đầu ra true cho bạn biết rằng hình ảnh cập nhật đã được ghi thành công vào hệ thống file . Mở hình ảnh trên máy local của bạn để xem các thay đổi trên file mới:

Đầu ra hình ảnh với các khuôn mặt được phát hiện

Bạn sẽ thấy rằng tập lệnh của bạn đã phát hiện bốn khuôn mặt trong hình ảnh đầu vào và vẽ các hình chữ nhật để đánh dấu chúng. Trong bước tiếp theo, bạn sẽ sử dụng các vị trí pixel để extract khuôn mặt từ hình ảnh.

Bước 4 - Extract khuôn mặt và lưu chúng local (Tùy chọn)

Trong bước trước, bạn đã viết mã để sử dụng OpenCV và Haar Cascade để phát hiện và vẽ các hình chữ nhật xung quanh các khuôn mặt trong một hình ảnh. Trong phần này, bạn sẽ sửa đổi mã của bạn để extract các khuôn mặt được phát hiện từ hình ảnh thành các file của riêng chúng.

Bắt đầu bằng cách mở lại file app.py bằng editor của bạn:

  • nano app.py

Tiếp theo, thêm các dòng được đánh dấu dưới dòng cv2.rectangle :

app.py
... for (x, y, w, h) in faces:     cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)     roi_color = image[y:y + h, x:x + w]      print("[INFO] Object found. Saving locally.")      cv2.imwrite(str(w) + str(h) + '_faces.jpg', roi_color)  ... 

Đối tượng roi_color vẽ các vị trí pixel từ danh sách các faces trên hình ảnh đầu vào ban đầu. Các biến x , y , hw là vị trí pixel cho mỗi đối tượng được phát hiện từ phương thức faceCascade.detectMultiScale . Sau đó, mã in ra thông báo rằng một đối tượng đã được tìm thấy và sẽ được lưu local .

Sau khi hoàn tất, mã lưu âm mưu dưới dạng hình ảnh mới bằng phương thức cv2.imwrite . Nó nối chiều rộng và chiều cao của âm mưu với tên của hình ảnh được ghi vào. Điều này sẽ giữ cho tên duy nhất trong trường hợp có nhiều khuôn mặt được phát hiện.

Tập lệnh app.py được cập nhật sẽ trông giống như sau:

app.py
import cv2 import sys  imagePath = sys.argv[1]  image = cv2.imread(imagePath) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)  faceCascade = cv2.CascadeClassifier(cv2.data.haarcascades + "haarcascade_frontalface_default.xml") faces = faceCascade.detectMultiScale(     gray,     scaleFactor=1.3,     minNeighbors=3,     minSize=(30, 30) )  print("[INFO] Found {0} Faces.".format(len(faces)))  for (x, y, w, h) in faces:     cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)     roi_color = image[y:y + h, x:x + w]     print("[INFO] Object found. Saving locally.")     cv2.imwrite(str(w) + str(h) + '_faces.jpg', roi_color)  status = cv2.imwrite('faces_detected.jpg', image) print("[INFO] Image faces_detected.jpg written to filesystem: ", status) 

Tóm lại, mã được cập nhật sử dụng các vị trí pixel để extract các khuôn mặt từ hình ảnh thành một file mới. Khi bạn đã cập nhật xong mã, hãy lưu file .

Đến đây bạn đã cập nhật mã, bạn đã sẵn sàng chạy tập lệnh :

  • python app.py path/to/image

Bạn sẽ thấy kết quả tương tự sau khi tập lệnh của bạn xử lý xong hình ảnh:

Output
[INFO] Found 4 Faces. [INFO] Object found. Saving locally. [INFO] Object found. Saving locally. [INFO] Object found. Saving locally. [INFO] Object found. Saving locally. [INFO] Image faces_detected.jpg written to file-system: True

Tùy thuộc vào số lượng khuôn mặt trong hình ảnh mẫu của bạn, bạn có thể thấy kết quả nhiều hơn hoặc ít hơn.

Nhìn vào nội dung của folder làm việc sau khi thực thi tập lệnh, bạn sẽ thấy các file cho ảnh chụp đầu của tất cả các khuôn mặt được tìm thấy trong hình ảnh đầu vào.

Danh sách folder

Đến đây bạn sẽ thấy ảnh chụp đầu được extract từ hình ảnh đầu vào được thu thập trong folder làm việc:

Khuôn mặt được   extract

Trong bước này, bạn đã sửa đổi tập lệnh của bạn để extract các đối tượng được phát hiện từ hình ảnh đầu vào và lưu chúng local .

Kết luận

Trong hướng dẫn này, bạn đã viết một tập lệnh sử dụng OpenCV và Python để phát hiện, đếm và extract các khuôn mặt từ hình ảnh đầu vào. Bạn có thể cập nhật tập lệnh này để phát hiện các đối tượng khác nhau bằng cách sử dụng Haar Cascade khác được đào tạo trước từ thư viện OpenCV hoặc bạn có thể tìm hiểu cách đào tạo Haar Cascade của riêng mình .


Tags:

Các tin liên quan

Cách tạo bộ phân loại học máy bằng Python với Scikit-learning
2019-03-24
Cách thiết lập sổ tay Jupyter cho Python 3
2019-03-21
Cách viết chương trình Python 3 đầu tiên của bạn
2019-02-22
Cách cài đặt Python 3 và thiết lập môi trường lập trình cục bộ trên Ubuntu 18.04
2019-02-22
Cách thiết lập notebook Jupyter với Python 3 trên Ubuntu 18.04
2018-11-28
Cách thực hiện chuyển kiểu neural với Python 3 và PyTorch
2018-09-13
Cách thực hiện chuyển kiểu neural với Python 3 và PyTorch
2018-09-13
Cách cài đặt Python 3 và thiết lập môi trường lập trình cục bộ trên Windows 10
2018-09-11
Cách cài đặt Python 3 và thiết lập môi trường lập trình cục bộ trên Windows 10
2018-09-11
Cách thiết lập một sổ ghi chép Jupyter với Python 3 trên Debian 9
2018-09-07