7. Kết cấu của đề tài
2.4. Tiến hành cho học máy
Khi học máy, chương trình sẽ thực hiện 2 công việc: Tiến hành training thông qua tập hình ảnh training. Kiểm tra độ chính xác thông qua tập hình ảnh test.
Chương trình học máy này được tác giả nghiên cứu [7] và áp dụng vào nghiên cứu để cho máy học.
Để tiến hành học máy, thực hiện câu lệnh sau:
python /home/serverb304/NCKHK13/MinhTien/facenet/src/classifier.py TRAIN /home/serverb304/NCKHK13/MinhTien/facenet/CASIA/Output_train /home/serverb304/NCKHK13/MinhTien/facenet/CASIA/model/201705 11-185253.pb /home/serverb304/NCKHK13/MinhTien/facenet/CASIA/result/my_clas sifier.pkl
- Cấu trúc của câu lệnh trên như sau:
python path_python_file mode path_to_image path_to_model
path_save_result
python: lệnh để thực thi chương trình python.
path_python: đường dẫn tới file python sẽ thực thi.
mode: Có 2 chế độ: TRAIN là chế độ học. CLASSIFY là chế độ
kiểm tra.
path_to_image: Đường dẫn tới thư mục hình ảnh chô máy học.
path_to_model: đường dẫn tới file model cần sử dụng.
path_save_result: đường dẫn tới thư mục lưu kết quả.
Để kiểm tra tra độ chính xác trên tập dữ liệu ngẫu nhiên thực thi lệnh sau:
python /home/serverb304/NCKHK13/MinhTien/facenet/src/classifier.py CLASSIFY /home/serverb304/NCKHK13/MinhTien/facenet/CASIA/Output_test /home/serverb304/NCKHK13/MinhTien/facenet/CASIA/model/201705 11-185253.pb /home/serverb304/NCKHK13/MinhTien/facenet/CASIA/result/my_clas sifier.pkl
- Cấu trúc của câu lệnh trên như sau:
python path_python_file mode path_to_image path_to_model
path_save_result
python: lệnh để thực thi chương trình python.
mode: Có 2 chế độ: TRAIN là chế độ học. CLASSIFY là chế độ
kiểm tra.
path_to_image: Đường dẫn tới thư mục hình kiểm tra.
path_to_model: đường dẫn tới file model sẽ sử dụng.
path_save_result: đường dẫn tới file kết quả sau khi cho máy học. 2.5. Thử nghiệm nhận diện trên camera
Quy trình nhận diện khuôn mặt:
Để kiểm tra trực tiếp kết quả thông qua camera, tiến hành chạy lệnh sau:
(Tensorflow)
serverb304@serverb304:~/NCKHK13/MinhTien/facerecognition$ pyth on facerecognition.py
Câu lệnh trên có chức năng thực thi chương trình có chức năng kiểm tra trong một video hoặc hình ảnh truyền từ camera có những khuôn mặt nào máy đã học được, đồng thời sẽ chụp và lưu lại những khuôn mặt có trong video hoặc hình ảnh lấy từ camera. Kết quả như Hình 2-9: Kết quả sau khi chạy chương trình nhận diện khuôn mặt sau khi học máy.
Hình 2-8: Quy trình nhận diện khuôn mặt
Input Detect Face Crop Face
Rút trích đặc trưng
Phân loại Dataset
Ngoài ra tác giả còn chia tập học ra 3 tập học với số lượng hình ảnh lần lượt là 16, 32 và 48 hình ảnh. Sau đó kiểm tra so với tập test và đạt được kết quả như sau:
Bảng 2-3: Kết quả so sánh độ chính xác trên các tập học có số lượng ảnh khác nhau
Số lượng hình 16 32 48 Độ chính xác 89,2% 89,7% 89,7%
Từ Bảng 2-3: Kết quả so sánh độ chính xác trên các tập học có số lượng ảnh khác nhau, tác giả nhận thấy rằng, với tập dữ liệu học thu thập tại phòng B304 với điều kiện ánh sáng tương tự nhau nên độ tương đồng của các ảnh là như nhau, với số lượng ảnh học là 32 ảnh và 48 ảnh thì phần trăm đúng không thay đổi. Vì vậy để nâng cao được độ chính xác của phương pháp học này, cần phải thu thập ảnh ở nhiều môi trường và thời gian khác nhau. Dưới đây là hình ảnh kết quả lúc thử kết quả trên tập test với số lượng ảnh học là 48 ảnh (Hình 2-10: Kết quả thử nghiệm trên tập học 48 hình ảnh với tập test 12 hình).
Hình 2-9: Kết quả sau khi chạy chương trình nhận diện khuôn mặt sau khi học máy
…
2.6. Tiểu kết
Qua chương 2, tác giả đã xây dựng được hệ thống học máy nhận diện khuôn mặt, từ thu thập dữ liệu, cho học máy và cuối cùng là tiến hành kiểm tra thực nghiệm. Sang chương 3, tác giả sẽ tiến hành ứng dụng việc nhận diện khuôn mặt vào Robot NAO để có thể cho Robot NAO trở thành một người máy thông minh hơn.
Chương 3 : Xây dựng ứng dụng nhận diện khuôn mặt trên Robot NAO
Từ kết quả nhận diện khuôn mặt sau khi thực hiện quá trình học máy, tác giả đi đến việc kết hợp kết quả trả về đó với Robot NAO để giúp Robot NAO có thể thông minh hơn. Ý tưởng của tác giả là sẽ cho Robot NAO chào những người mà hệ thống đã được học trước đó. Mỗi ngày Robot chỉ chào mỗi người một lần. Để thực hiện việc xây dựng hệ thống này, tác giả có hai giải pháp:
Sử dụng NAOqi API để điều khiển Robot chào. Ưu điểm của giải pháp này là tốc độ nhanh. Nhưng điểm yếu của cách xử lý này là Robot NAO vẫn chưa thể thực hiện việc chào một người bằng tiếng Việt vì phần mềm của Robot chưa hỗ trợ.
Lựa chọn hai, tác giả sẽ kết hợp giữa thư viện NAOqi API và Google Text
To Speech để giúp Robot có thể chào được tiếng Việt. Ưu điểm của giải pháp này
là Robot có thể nói tiếng Việt nhưng nhược điểm của nó là sẽ chậm hơn phương pháp đầu tiên vì phụ thuộc nhiều vào tốc độ đường truyền Internet.
Trước khi đi vào xây dựng chương trình, có một lưu ý là NAOqi API chỉ hỗ trợ lập trình trên Python 2.7.x, còn bộ công cụ học máy lại được tác giả xây dựng trên nên tảng Python 3.6.3. Vì vậy, để xây dựng chương trình này, tác giả sẽ kết hợp cả hai phiên bản Python 2.7.x và Python 3.6.3.
Bây giờ tác giả xin trình bày quá trình xây dựng hai giải pháp trên.
3.1. Sử dụng NAOqi API để điều khiển Robot chào.
3.1.1. Xây dựng module truyền hình ảnh từ Robot NAO lên server
Để xây dựng hương trình thực hiện chức năng này, tác giả sử dụng
ALProxy để kết nối tới Robot NAO, sau đó dùng module ALVideoDevice
để sử dụng được camera trên Robot NAO. Dưới đây là code của chương trình:
# vim: set fileencoding=utf-8 :
import sys
import numpy as np
import cv2
from naoqi import ALProxy
# Kiểm tra các tham số đầu vào khi chạy chương trình trên command # Lệnh chạy chương trình đúng là: python tenfile.py ip_address_nao port_nao
if(len(sys.argv)<=2):
print"parameter error"
print"python "+ sys.argv[0]+" <ipaddr> <port>"
# Nhận các tham số IP và Port của NAO để kết nối server với Robot NAO
ip_addr = sys.argv[1]
port_num = int(sys.argv[2])
# get NAOqi module proxy
videoDevice = ALProxy(' ', ip_addr, port_num)
# Sử dụng topcamera của Robot NAO AL_kTopCamera =0
AL_kQVGA =1 # Độ phân giải camera sử dụng là 320x240 AL_kBGRColorSpace =13
captureDevice = videoDevice.subscribeCamera(
"sessionName", AL_kTopCamera, AL_kQVGA,
AL_kBGRColorSpace,10)
#Tạo hình ảnh có kích thước 320x240 width =320
height =240
image = np.zeros((height, width,3), np.uint8)
whileTrue:
# Lấy hình ảnh về server
result = videoDevice.getImageRemote(captureDevice);
if result ==None:
print'cannot capture.'
elif result[6]==None:
print'no image data string.'
else:
# Chuyển các giá trị về ma trận values = map(ord, list(result[6]))
i =0
for y in range(0, height):
for x in range(0, width):
image.itemset((y, x,0), values[i +0])
image.itemset((y, x,1), values[i +1])
image.itemset((y, x,2), values[i +2])
i +=3
cv2.imshow("NAO-TOP-CAMERA-320x240", image)
Hình 3-1: Code xử lý kết nối camera Robot NAO với server
Sau khi chạy chương trình trên, kết quả của chương trình là hình ảnh từ camera của Robot NAO đã được truyền trực tiếp lên server.
3.1.2. Xây dựng module chụp hình và lưu khi phát hiện có một khuôn mặt
Vì phạm vi đề tài của tác giả chỉ nằm trong phạm vi một khuôn mặt nên để tăng độ chính xác tác giả chỉ cho Robot NAO chụp hình khi trước camera chỉ có một khuôn mặt. Để xây dựng module này tác giả thực hiện tiếp trên đoạn code (Hình 3-1: Code xử lý kết nối camera Robot NAO với server).
Bước 1: Xác định bộ giải mã khởi tạo đối tượng VideoWriter để ghi video và khởi tạo đối tượng chứa dữ liệu mặt người. Các dữ liệu này được lưu trong file: haarcascade_frontalface_default.xml do OpenCV cung cấp
sẵn.
detector=cv2.CascadeClassifier('haarcascade_frontalface_default.x
ml')
out =
cv2.VideoWriter(video.avi',cv2.VideoWriter_fourcc('M','J','P','G'), 10, (width,height))
Hình 3-3: Xác định bộ giải mã khởi tạo đối tượng VideoWriter để ghi video và khởi tạo đối tượng chứa dữ liệu mặt người.
Bước 2: Xác định khuôn mặt và đếm số khuôn mặt trong khung hình đó. Nếu số khuôn mặt trong khung hình đó bằng một thì tiến hành ghi khung hình đó vào video. Đến khi thu được ba khung hình chứa khuôn mặt thì chương trình dừng. Ở đây tác giả chọn số khung hình là ba để có thể nâng cao độ chính xác trong các trường hợp khung hình thu vào bị nhòe.
faces = detector.detectMultiScale(image,1.3,5)
if len(faces)==1:
framecount = framecount+1
dt_current = datetime.datetime.now()
cv2.imwrite(str(dt_current).replace(":", "").replace(".",
"").replace("-","").replace(" ","") +".jpg", image)
out.write(image)
if framecount ==3:
videoDevice.releaseImage(session)
out.release()
cv2.destroyAllWindows()
break
Hình 3-4: Kiểm tra điều kiện và tiến hành lưu video
3.1.3. Xác định khuôn mặt từ video thu được từ Robot NAO
Để xác định được khuôn mặt trong video mà Robot NAO thu được, tác giả sẽ dùng chương trình xác thực khuôn mặt mà tác giả đã nói ở chương 2. Sau khi chương trình xác thực xong khuôn mặt trong video, kết quả thu được là tên của một người.
Trong chương trình có sử dụng hai file có đuôi .txt để lưu trữ kết quả thu được. Một file sẽ lưu tên của người mà Robot nhận diện được để có thể kiểm tra điều kiện và chào người đó một lần một ngày. File này mỗi ngày sẽ được tạo một file với định dạng là DD-MM-YYYY. Một file sẽ lưu chuỗi mà Robot sẽ nói khi có kết quả nhận diện khuôn mặt. Khi khuôn mặt được nhận diện là một người mới trong ngày, chuỗi lưu trữ sẽ là: “Hello” + tên nhận diện được + “! Nice to meet
you!”. Khi khuôn mặt nhận diện là một người đã gặp trong ngày thì chuỗi lưu trữ
là: “Good to see you again” + tên nhận được. Khi gặp một người mà Robot
không biết thì chuỗi lưu trữ sẽ là: “Sory! I don’t know who are you!”.
import datetime
dt_now = datetime.datetime.now()
date_dmy = dt_now.strftime("%d-%m-%Y")
dt = str(date_dmy)+".txt"
print(dt)
ifnot dt in os.listdir("."):
system("echo.>"+dt)
Hình 3-5: Code kiểm tra và tạo file lưu trữ danh sách tên Robot NAO gặp trong ngày
result_names ="" #Biến chứa tên để xử lý
flag =0 #Biến lưu trạng thái người nao nhận diện đã biết hay chưa
for H_i in HumanNames:
if HumanNames[best_class_indices[0]] == H_i and
predictions[0][best_class_indices[0]]>0.50:
result_names = HumanNames[best_class_indices[0]]
flag= 1 #Biến lưu trạng thái người nao nhận diện được NAO biết hay không
flag_exist =0 #Biến lưu trạng thái đã gạp một ngày nào đó trong ngày chưa
ten = result_names.replace('_', ' ') #Nếu tên đặt theo định dạng Cao_Minh_Tiên thì chuyển về Cao Minh Tiên
with open(dt, encoding="utf-8")as fp: #Mở file có tên là ngày hiện tại lên để kiểm tra tên đã tồn tại hay chưa
for line in fp:
if line==ten: #Nếu tên đã tồn tại thì thay đổi trạng thái của biến lưu trạng thái
flag_exist = 1 fp.close()
if flag_exist == 0: #Nếu nguoiqd này chưa gặp trong ngày thì chào và lưu tên vào danh sách người đã gặp trong ngày
f_result= open("result.txt",'w', encoding="utf-8") f_result.write("Hello "+ ten +"“! Nice to meet you!")
f_result.close()
ff_result= open(dt,'a', encoding="utf-8")
ff_result.write("\n"+ten)
ff_result.close()
flag=0
else: # Nếu người được nhận diện là đã gặp trong ngày rồi thì chào với kết quả này
f_result= open("result.txt",'w', encoding="utf-8")
f_result.write("Good to see you again "+ ten)
f_result.close()
flag=0
flag_exist =0 #Hiển thị tên lên video
cv2.putText(frame, result_names, (text_x, text_y),
cv2.FONT_HERSHEY_COMPLEX_SMALL,
1,(0,0,255), thickness=1, lineType=2)
if flag ==0: #Khi không nhận ra ai thì thực hiện những lên này str_result ="Sory! I don’t know who are you!"
f_result= open("result.txt",'w', encoding="utf-8")
f_result.write(str_
Hình 3-6: Code xử lý để đưa ra lời chào cho Robot NAO
3.1.4. Xây dựng module cho Robot NAO chào
Để cho Robot NAO chào, tác giả sử dụng ALProxy để kết nối với Robot NAO và dùng module ALTextToSpeech để lập trình cho Robot đọc kết quả chào.
import sys
from naoqi import ALProxy
#Cấu hình tham số truyền vào command line là địa chỉ IP Robot NAO
if (len(sys.argv)<2):
print "Usage: 'python texttospeech_setparameter.py IP [PORT]'" sys.exit(1)
IP = sys.argv[1]
PORT =9559 # Port là 9559
if (len(sys.argv)>2):
PORT = sys.argv[2]
try:
tts = ALProxy("ALTextToSpeech", IP, PORT)
except Exception,e:
print "Could not create proxy to ALTextToSpeech" sys.exit(1)
#Applies a pitch shifting to the voice
tts.setParameter("pitchShift",0.0)
#Tăng tốc đọ nói
tts.setParameter("doubleVoice",0.0)
#Mở và đọc kết quả lưu trong file .txt
f = open('result.txt','r')
stri = ""
while 1:
line = f.readline()
if not line:break
stri += line f.close()
Hình 3-7: Code xử lý module cho Robot NAO chào
Sau khi xây dựng xong các module trên, tác giả tiến hành ghép các module đó lại với nhau và tiến hành chạy chương trình. Khi chạy chương trình, hình ảnh trên camera được gửi trực tiếp về server. Khi chương trình phát hiện có một khuôn mặt nào đó trước camera thì hệ thống sẽ xác định xem kết quả của khuôn mặt đó và Robot NAO tiến hành chào như chương trình đã quy định.
3.2. Kết hợp giữa thư viện NAOqi API và Google Text To Speech để giúp Robot có thể chào được tiếng Việt có thể chào được tiếng Việt
Ở giải pháp này, việc xây dựng các module như truyền hình ảo từ camera
Robot NAO lên server, xây dựng module chụp hình và lưu khi phát hiện có một khuôn mặt sẽ thực hiện tương giống các mục trong phần 3.1.1, 3.1.2. Còn
phần đưa ra kết quả lời chào và cho NAO đọc kết quả sẽ thực hiện như sau:
3.2.1. Xác định khuôn mặt từ video thu được từ Robot NAO
Việc xác thực khuôn mặt từ Robot NAO được thực hiện tương tự như phần 3.1.3, nhưng kết quả lưu lại để chào sẽ là như sau: Khi khuôn mặt được nhận diện là một người mới trong ngày, chuỗi lưu trữ sẽ là: “Chào” + tên nhận diện được. Khi khuôn mặt nhận diện là một người đã gặp trong ngày thì chuỗi lưu trữ là: “Rất
vui khi gặp lại” + tên nhận được. Khi gặp một người mà Robot không biết thì
chuỗi lưu trữ sẽ là: “Xin lỗi. Rô bốt NAO không biết bạn là ai. Mình làm quen
nhé! A Hihi”.
3.2.2. Xây dựng module tạo ra file âm thanh chào bằng tiếng Việt
Để xây dựng chức năng này, tác giả sử dụng thư viện 1.4.8 API Googe Text To Speech để tạo ra đoạn âm thanh từ kết quả trả về từ việc nhận diện khuôn mặt trên Robot NAO. Yêu cầu của thư viện này là yêu cầu phải có internet.
from gtts import gTTS
import os
f = open('result.txt','r', encoding="utf-8")
stri =""
while 1:
line = f.readline()
ifnot line:break
stri += line f.close()
print(stri)
tts = gTTS(text= stri , lang='vi')
tts.save("naonoi.mp3")
3.2.3. Xây dựng module gửi file âm thanh từ Robot NAO lên server
Để có thể gửi được file lên server, tác giả sử dụng module SCP trên thư viện Paramiko. Dưới đây là code xử lý.
import paramiko
from paramiko import SSHClient
from scp import SCPClient # Hàm tạo két nối SSh
defcreateSSHClient(server, port, user, password):
client = SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(server, port, user, password)
return client
# Kết nối ssh từ Server đến Robot NAO
ssh = createSSHClient('192.168.1.11',22,'nao','nao')
scp = SCPClient(ssh.get_transport())
#Gửi một một đường dẫn trên server đến một đường dẫn trên Robot NAO scp.put("Đường dẫn tới file âm thanh trên server",'Đường dẫn tới thư mục lưu file âm thanh trên Robot NAO')
scp.close()
Hình 3-9: Code gửi file âm thanh từ server về Robot NAO
3.2.4. Xây dựng module đọc file âm thanh cho Robot NAO
Để thực hiện chức năng này, tác giả sử dụng ALProxy để kết nối với Robot NAO và dùng module ALAudioPlayer để kết nối tới Robot NAO và cho Robot phát âm thanh mà Robot đã nhận được từ server.
import qi
import argparse
import sys
import time
#Xây dựng hàm thực hiện chức năng đọc file âm thanh từ một đường dẫn tên Robot NAO
defmain(session):
# Sử dụng dịch vụ ALAudioPlayer.
audio_player_service = session.service("ALAudioPlayer")
audio_player_service.playFile("đường dẫn tới file âm thanh trên Robot
NAO")
if __name__ =="__main__":
parser = argparse.ArgumentParser()
#Khai báo tham số đầu vào là IP và Port của Robot NAO trên command line
# Lúc chạy nếu có tham số thì chương trình sẽ nhận tham số đó, còn không sẽ nhận giá trị mặc định
parser.add_argument("--ip", type=str, default="192.168.1.11",