ตรวจสอบใบหน้าโดยใช้ Raspberry Pi + Webcam


มีโครงงานหลายชิ้นที่ได้สอบทีมงาน LIL ว่าจะสามารถใช้ Raspberry Pi ในตรวจสอบว่ามีใบหน้าคนอยู่ในภาพที่ได้จาก webcam หรือไม่ ซึ่งจากการศึกษาค้นคว้าเบื้องต้นก็พบว่าสามารถทำได้ไม่ยากจึงได้นำมาเรียบเรียงไว้ดังนี้

อุปกรณ์ที่ต้องใช้

  1. Raspberry Pi
  2. กล้อง 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_ex

เท่าที่ลองด้วยตนเองพบว่าระบบจะตรวจพบใบหน้าได้ดีหากมองตรงไปยังกล้อง ใบหน้าควรมีขนาดที่เหมาะสมในภาพ ไม่เล็กจนเกินไป หากมีปัญหาในการตรวจจับให้ลองถอดแว่นสายตา หรือทดลองกับผู้ที่ไม่มีหนวดเครามากจนเกินไป เมื่อยิ้มพบว่าตรวจได้ดีขึ้นเล็กน้อย ซึ่งอาจเป็นเพราะสภาพแสงขณะทดสอบมีเงาบนใบหน้า เมื่อยิ้มเห็นฟันจึงทำให้เค้าโครงหน้าชัดเจนขึ้น

การนำไปใช้

โปรแกรมตรวจสอบใบหน้าข้างต้นมีฟังก์ชันที่เรียกใช้งานได้สองตัวคือ

  • detect_and_draw() – ฟังก์ชันนี้ใช้ในตัวอย่างข้างต้นจะวาดภาพและกรอบบนใบหน้า หากต้องการตั้งค่าตัวแปรให้เป็นจริงเมื่อตรวจพบใบหน้าก็ให้แทรกคำสั่งเข้าไปหลังบรรทัด print “Face found”
  • faceFound() – ฟังก์ชันนี้จะคืนค่า True หรือ False ขึ้นอยู่กับว่าตรวจพบใบหน้าหรือไม่ โดยไม่มีการวาดใบหน้าบนจอภาพ ดังนั้นจะเหมาะนำไปใช้ในกรณีที่เพียงต้องการทราบสถานะโดยไม่ต้องการเห็นรูปภาพ

สรุป

บทความนี้ได้แสดงวิธีการใช้ Raspberry Pi กับกล้อง Web Cam เพื่อตรวจจับใบหน้าคนอย่างง่าย ซึ่งวิธีนี้จะตรวจได้เพียงว่ามีใบหน้าคนอยู่หรือไม่ โดยไม่สามารถรู้จำว่าใบหน้านั้นคือใคร ซึ่งจะเป็นขั้นตอนที่ซับซ้อนขึ้นไปอีก และหากได้พบตัวอย่างก็จะนำมาเขียนเพิ่มเติมอีกครัง

อ้างอิง

บทความนี้เป็นการประยุกต์ตัวอย่างที่เขียนโดย Oscar Liang  จากบทความ Raspberry Pi Face Recognition Using OpenCV