มีโครงงานหลายชิ้นที่ได้สอบทีมงาน LIL ว่าจะสามารถใช้ Raspberry Pi ในตรวจสอบว่ามีใบหน้าคนอยู่ในภาพที่ได้จาก webcam หรือไม่ ซึ่งจากการศึกษาค้นคว้าเบื้องต้นก็พบว่าสามารถทำได้ไม่ยากจึงได้นำมาเรียบเรียงไว้ดังนี้
อุปกรณ์ที่ต้องใช้
- Raspberry Pi
- กล้อง Web Cam ที่ใช้งานได้กับ Raspberry Pi – บทความนี้ใช้กล้อง Logitech C110 ซึ่งเป็นกล้องหาง่ายราคาถูก
ลงโปรแกรม python-opencv
แม้การตรวจสอบใบหน้ามนุษย์ในรูปภาพนั้นเป็นความาสมารถที่พบเห็นได้ทั่วไปในโทรศัพท์มือถือและกล้องถ่ายรูป แต่ความสามารถนี้ในทางเทคนิคยังถือเป็นความสามารถขั้นสูง การจะเขียนขึ้นมาเองต้องใช้ความรู้ด้านการประมวลผลรูปภาพที่ลึกซึ้ง ซึ่งเป็นทักษะที่ผู้ใช้งานเบื้องต้นมักเข้าไม่ถึง อย่างไรก็ดีปัจจุบันได้มีโปรแกรมที่ฝังความสามารถนี้มาให้ในตัวโดยที่สามารถเรียกใช้งานได้ไม่ยากนักและไม่ต้องเข้าใจรายละเอียดเชิงลึกของการประมวลผลที่เกิดขึ้นหลังฉาก ในตัวอย่างนี้เราจะใช้ความสามารถของ OpenCV ในการตรวจสอบใบหน้า โดยเรียกใช้จากโปรแกรม Python ขั้นแรกคือการติดตั้ง python-opencv
sudo apt-get install python-opencv
ทดสอบ OpenCV
ต่อไปคือทำการทดสอบกล้องว่าใช้งานได้หรือไม่ โดยให้ลองเรียกใช้โปรแกรมต่อไปนี้
import cv cv.NamedWindow("w1", cv.CV_WINDOW_AUTOSIZE) camera_index = 0 capture = cv.CaptureFromCAM(camera_index) def repeat(): global capture #declare as globals since we are assigning to them now global camera_index frame = cv.QueryFrame(capture) cv.ShowImage("w1", frame) c = cv.WaitKey(10) if(c=="n"): #in "n" key is pressed while the popup window is in focus camera_index += 1 #try the next camera index capture = cv.CaptureFromCAM(camera_index) if not capture: #if the next camera index didn't work, reset to 0. camera_index = 0 capture = cv.CaptureFromCAM(camera_index) while True: repeat()
หากเห็นภาพจาก webcam ก็เป็นอันว่าอุปกรณ์ที่จำเป็นทั้งหมดใช้ได้
ทดสอบการตรวจจับใบหน้า
ต่อไปก็ให้ลอง เรียกใช้งานโปรแกรมด้านล่าง ซึ่งจะทำการตรวจสอบใบหน้าในรูปภาพและตีกรอบสีแดงล้อมรอบหากตรวจพบ ก่อนเรียกใช้งานเราต้องโหลดไฟล์ข้อมูลที่ใช้รู้จำใบหน้าก่อน ไฟล์นี้ได้รับการฝึกหัดมาให้รู้จำใบหน้าจากมุมตรงเท่านั้น ไม่สามารถตรวจจับใบหน้าจากด้านข้างหรือด้านอื่นๆ ได้
ให้บันทึกไฟล์นี้ไว้ที่เดียวกับไฟล์ Python ต่อไปนี้
#!/usr/bin/python #The program finds faces in a camera image or video stream and displays a red box around them. import sys import cv2.cv as cv ##from optparse import OptionParser min_size = (20, 20) image_scale = 2 haar_scale = 1.2 min_neighbors = 2 haar_flags = 0 # return True if a face is found in an image def faceFound(img, cascade): # allocate temporary images gray = cv.CreateImage((img.width,img.height), 8, 1) small_img = cv.CreateImage((cv.Round(img.width / image_scale), cv.Round (img.height / image_scale)), 8, 1) # convert color input image to grayscale cv.CvtColor(img, gray, cv.CV_BGR2GRAY) # scale input image for faster processing cv.Resize(gray, small_img, cv.CV_INTER_LINEAR) cv.EqualizeHist(small_img, small_img) if(cascade): t = cv.GetTickCount() faces = cv.HaarDetectObjects(small_img, cascade, cv.CreateMemStorage(0), haar_scale, min_neighbors, haar_flags, min_size) t = cv.GetTickCount() - t if faces: return True else: return False # draws a rectangle on a discovered face def detect_and_draw(img, cascade): # allocate temporary images gray = cv.CreateImage((img.width,img.height), 8, 1) small_img = cv.CreateImage((cv.Round(img.width / image_scale), cv.Round (img.height / image_scale)), 8, 1) # convert color input image to grayscale cv.CvtColor(img, gray, cv.CV_BGR2GRAY) # scale input image for faster processing cv.Resize(gray, small_img, cv.CV_INTER_LINEAR) cv.EqualizeHist(small_img, small_img) if(cascade): t = cv.GetTickCount() faces = cv.HaarDetectObjects(small_img, cascade, cv.CreateMemStorage(0), haar_scale, min_neighbors, haar_flags, min_size) t = cv.GetTickCount() - t # print "time taken for detection = %gms" % (t/(cv.GetTickFrequency()*1000.)) if faces: print "Face found!" for ((x, y, w, h), n) in faces: # the input to cv.HaarDetectObjects was resized, so scale the # bounding box of each face and convert it to two CvPoints pt1 = (int(x * image_scale), int(y * image_scale)) pt2 = (int((x + w) * image_scale), int((y + h) * image_scale)) cv.Rectangle(img, pt1, pt2, cv.RGB(255, 0, 0), 3, 8, 0) else: print " - " cv.ShowImage("video", img) if __name__ == '__main__': cascade = cv.Load("face.xml") capture = cv.CreateCameraCapture(0) cv.NamedWindow("video", 1) #size of the video width = 160 height = 120 cv.SetCaptureProperty(capture,cv.CV_CAP_PROP_FRAME_WIDTH,width) cv.SetCaptureProperty(capture,cv.CV_CAP_PROP_FRAME_HEIGHT,height) frame_copy = None while True: frame = cv.QueryFrame(capture) if not frame: cv.WaitKey(0) break if not frame_copy: frame_copy = cv.CreateImage((frame.width,frame.height), cv.IPL_DEPTH_8U, frame.nChannels) if frame.origin == cv.IPL_ORIGIN_TL: cv.Copy(frame, frame_copy) else: cv.Flip(frame, frame_copy, 0) detect_and_draw(frame_copy, cascade) if cv.WaitKey(10) >= 0: break cv.DestroyWindow("video")
เมื่อเรียกใช้ตัวอย่างข้างต้นก็จะเห็นหน้าต่างแสดงภาพขนาด 160×120 จุด จากกล้อง webcam และจะเห็นสีเหลี่ยมสีแดงปรากฏขึ้นหากชี้กล้องไปยังหน้าคน ดังตัวอย่าง
เท่าที่ลองด้วยตนเองพบว่าระบบจะตรวจพบใบหน้าได้ดีหากมองตรงไปยังกล้อง ใบหน้าควรมีขนาดที่เหมาะสมในภาพ ไม่เล็กจนเกินไป หากมีปัญหาในการตรวจจับให้ลองถอดแว่นสายตา หรือทดลองกับผู้ที่ไม่มีหนวดเครามากจนเกินไป เมื่อยิ้มพบว่าตรวจได้ดีขึ้นเล็กน้อย ซึ่งอาจเป็นเพราะสภาพแสงขณะทดสอบมีเงาบนใบหน้า เมื่อยิ้มเห็นฟันจึงทำให้เค้าโครงหน้าชัดเจนขึ้น
การนำไปใช้
โปรแกรมตรวจสอบใบหน้าข้างต้นมีฟังก์ชันที่เรียกใช้งานได้สองตัวคือ
- detect_and_draw() – ฟังก์ชันนี้ใช้ในตัวอย่างข้างต้นจะวาดภาพและกรอบบนใบหน้า หากต้องการตั้งค่าตัวแปรให้เป็นจริงเมื่อตรวจพบใบหน้าก็ให้แทรกคำสั่งเข้าไปหลังบรรทัด print “Face found”
- faceFound() – ฟังก์ชันนี้จะคืนค่า True หรือ False ขึ้นอยู่กับว่าตรวจพบใบหน้าหรือไม่ โดยไม่มีการวาดใบหน้าบนจอภาพ ดังนั้นจะเหมาะนำไปใช้ในกรณีที่เพียงต้องการทราบสถานะโดยไม่ต้องการเห็นรูปภาพ
สรุป
บทความนี้ได้แสดงวิธีการใช้ Raspberry Pi กับกล้อง Web Cam เพื่อตรวจจับใบหน้าคนอย่างง่าย ซึ่งวิธีนี้จะตรวจได้เพียงว่ามีใบหน้าคนอยู่หรือไม่ โดยไม่สามารถรู้จำว่าใบหน้านั้นคือใคร ซึ่งจะเป็นขั้นตอนที่ซับซ้อนขึ้นไปอีก และหากได้พบตัวอย่างก็จะนำมาเขียนเพิ่มเติมอีกครัง
อ้างอิง
บทความนี้เป็นการประยุกต์ตัวอย่างที่เขียนโดย Oscar Liang จากบทความ Raspberry Pi Face Recognition Using OpenCV