DEV Community

Watasin
Watasin

Posted on

ตรวจจับใบหน้า ใน 11 บรรทัด Python Face Detection

Face Dectection คืออะไร?
การตรวจจับใบหน้าเป็นเทคนิคในสาขา computer vision ที่เน้นการพัฒนาโปรแกรมให้สามารถทำความเข้าใจ "ข้อมูล" ที่อยู่ในรูปภาพ โดยอาศัยการตรวจจับ classifier ที่เป็นส่วนย่อยของใบหน้า ที่อาจมีมากถึง 6000++ classifier ที่ใช้ระบุใบหน้าบุคคล

Cascades คืออะไร?
การที่คอมพิวเตอร์จะหาใบหน้าบนรูปเจอ มันจะต้องเข้าไปดูในส่วนย่อยของภาพ เข้าไปเช็ค classifier ที่อาจะมีหลายพัน หลายหมื่นตัว เทียบกับข้อมูลใบหน้าที่มันเรียนรู้มา แล้วหากมีองค์ประกอบที่ตรงกับสิ่งที่เรียนรู้มาในระดับที่รับได้จึงแจ้งว่ามีการตรวจจับใบหน้า วิธีการทำงานนี้ทำให้เกิดงานหนักในการคำนวนได้อย่างมหาศาล จึงเกิดสิ่งที่เรียกว่า cascades ขึ้นมา ซึ่ง cascades หากแปลเป็นภาษาไทยแปลว่าน้ำตกขั้นบันได และเช่นเดียวกัน cascades อาศัยการทำงานที่ดูคล้ายๆ กัน Cascades จะแบ่งการตรวจจับออกเป็น stages ที่ประกอบไปด้วยส่วนหนึ่งของการตรวจจับ classifier ที่ต้องการใช้ เมื่อตรวจ stages หนึ่งเสร็จก็จะตรวจจับ stages ถัดไป และทำงานเป็นขั้นบันไดอย่างงี้ไปเรื่อยจนมีความมั่นใจในการเจอใบหน้า หากข้อมูลใดไม่สามารถแสดงให้เห็นลักษณะของใบหน้าได้ใน stages ที่ตรวจเช็ค ข้อมูลนั้นจะถูกข้ามไป และไปคำนวนในภาพส่วนถัดไปทันที ซึ่ง cascades อาจมี 30 -50 stages การทิ้งการคำนวนโดยที่ไม่ต้องตรวจเช็ค Classifier ทั้งหมด ทำให้การคำนวนมีประสิทธิภาพมากยิ่งขึ้น และระบบการทำงานแบบนี้เรียกว่า cascades นั่นเอง

Haar Cascades คืออะไร?
เป็น Object Detection Algorithm ใช้ในการตรวจจับวัตถุแบบ real-time อ้างอิงจากงานวิจัยของ Paul Viola และ Michael Jones ชื่อ “Rapid Object Detection using a Boosted Cascade of Simple Features” published in 2001 โดยหลักการทำงานของ Haar Cascades จะอ่านข้อมูล pixel ของรูป และนำมาเปรียบเทียบกับ feature ที่มีอยู่บนใบหน้าซึ่ง Haar Cascades สามารถปรับแต่งเพื่อตรวจจับวัตถุได้หลายอย่าง และเก็บข้อมูลในการตรวจ และโปรแกรมที่ถูกปรับแต่งเพื่อค้นหาวัตถุต่างๆ เก็บไว้ในรูปของไฟล์ xml ซึ่งหากเราต้องการตรวจจับใบหน้า เราต้องนำไฟล์ cascades ที่ปรับแต่งสำหรับการจับใบหน้านั่นเอง

Visualization การทำงานของ Haar Cascade : https://youtu.be/hPCTwxF0qf4

วันนี้เราจะสร้าง Face Detection Model ที่ใช้ตรวจจับใบหน้าภายใน 10 บรรทัดโดยการใช้ Haar Cascades ที่เตรียมไว้แล้ว เพื่อทำแบบนี้
Image description

ข้อมูลที่ใช้
เราจะใช้รูปที่มีใบหน้าคนอยู่ และไฟล์ xml ที่เก็บข้อมูล haar cascades ที่ใช้เพื่อระบุใบหน้า

ไฟล์รูป
รูปตัวอย่าง PPg1.png ที่จะใช้เป็นตัวอย่าง
Image description

ไฟล์ cascade
สำหรับโปรแกรมที่ใช้ตรวจจับเราจะใช้โปรแกรมที่ทำสำเร็จไว้แล้วชื่อ haarcascade_frontalface_default.xml ที่เตรียมไว้ให้เรียบร้อย

ระบุตำแหน่งของไฟล์ไว้ใช้งาน

In [1]:
imagePath = r'ig-cover-1.png'
cascPath = "haarcascade_frontalface_default.xml"
Enter fullscreen mode Exit fullscreen mode

ติดตั้ง opencv
ในการติดตั้งเราจะใช้ชื่อ opencv-python กับคำสั่ง pip install

In [1]:
!pip install opencv-python
Enter fullscreen mode Exit fullscreen mode

นำเข้า opencv
ซึ่งใช้ชื่อว่า cv2 ในการนำเข้า

In [2]:
import cv2
Enter fullscreen mode Exit fullscreen mode

การเปิดใช้
เราใช้คำสั่ง cv2.CascadeClassifier() ที่รับ path ไฟล์ของไฟล์ xml ที่เก็บ haar cascades ที่ใช้ระบุใบหน้า

In [3]:
faceCascade = cv2.CascadeClassifier(cascPath)
Enter fullscreen mode Exit fullscreen mode

นำเข้าข้อมูล
เราจะนำเข้าข้อมูลผ่านคำสั่ง cv2.imread() ที่รับ path ไฟล์รูป

In [4]:
image = cv2.imread(imagePath)
Enter fullscreen mode Exit fullscreen mode

แปลงรูปเป็นขาวดำ
ในกรณีนี้ cascade ของเราทำงานกับไฟล์รูปขาวดำ ซึ่งค่อนข้างปกติในการใช้กับโปรแกรมตรวจจับวัตถุ โดยเราจะใช้คำสั่ง cv2.cvtColor() รับค่า ภาพที่ต้องการเปลี่ยนค่าสี และ ตัวแปลงค่าสี เราจะใช้ cv2.COLOR_BGR2GRAY

In [5]:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
Enter fullscreen mode Exit fullscreen mode

ใช้ haar cascade ตรวจจับใบหน้า
โดยใช้คำสั่ง .detectMultiScale() ที่ทำงานร่วมกับข้อมูลที่ได้จากการเปิด cascade ด้วยคำสั่ง .CascadeClassifier() และรับข้อมูลรูปขาวดำ ซึ่งเราจะได้ตำแหน่งของใบหน้าที่ตรวจเจอมาอยู่ใน array ของ array

In [6]:
faces = faceCascade.detectMultiScale(gray)
Enter fullscreen mode Exit fullscreen mode

ข้อมูลที่ได้
เราจะได้ตำแหน่งของใบหน้าที่ตรวจเจอโดยการระบุ ตำแหน่ง x, ตำแหน่ง y, ความกว้าง, ความสูงของ "กรอบ" ที่ใช้ระบุตำแหน่งใบหน้า ตามลำดับ

In [7]:
faces
Enter fullscreen mode Exit fullscreen mode
Out[7]:
array([[332, 272, 193, 193]], dtype=int32)
Enter fullscreen mode Exit fullscreen mode

Unpacking
เราจะเก็บข้อมูลที่ได้มาแยกออกเป็นแต่ละตัวแปรแยกกันเพื่อให้นำไปใช้งานได้สะดวกยิ่งขึ้น

In [8]:
x, y, w, h = faces[0]
Enter fullscreen mode Exit fullscreen mode

ตีกรอบใบหน้าที่เจอ

การตีกรอบ
ใช้คำสั่ง cv2.rectangle() ที่รับค่า ภาพที่ต้องการตีกรอบ, tuple จุดเริ่มต้นที่จุดซ้ายบน (x,y), tuple จุดสิ้นสุดที่จุดขวาล่าง หรือ (x+w,y+h), tuple ค่าสี BGR สีเขียวใช้ (0,255,0), และความหนาของกรอบที่ต้องการ เมื่อรันคำสั่งภาพดังกล่าวจะถูกตีเส้นลงไป สามารถดูผลลัพธ์ได้จากคำสั่งการแสดงผลถัดไปในบทความ

In [9]:
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
Enter fullscreen mode Exit fullscreen mode
Out[9]:
array([[[228, 240, 243],         
[230, 242, 244],         
[230, 242, 244],         

...     

[127, 186, 192],         
[126, 184, 192],         
[126, 182, 192]]], 
dtype=uint8)
Enter fullscreen mode Exit fullscreen mode

การแสดงผลลัพธ์
ใช้คำสั่ง cv2.imshow() ที่รับค่า string ที่ใช้ตั้งชื่อหน้าต่างที่ใช้แสดงผลรูป และรับค่ารูปภาพที่ต้องการแสดง (รูปภาพที่ผ่านการตีกรอบ) ซึ่งการใช้งาน cv2.imshow() โดยจะต้องใช้คำสั่ง cv2.waitKey(0) ตามเข้าไปเพื่อป้องกันโปรแกรม crash ซึ่งเป็นคำสั่งที่ใช้หยุดการแสดงผลเมื่อมีการกดคีย์บอร์ดเมื่อเลือก pop-up หรือการกดปิด pop-up

In [10]:
cv2.imshow("Faces found", image)
cv2.waitKey(0)
Enter fullscreen mode Exit fullscreen mode

ผลลัพธ์ที่ได้จากการปิด pop-up
ถ้ากดปิดที่ x ด้านขวาบน จะได้ return value -1 หรือถ้ากดคีย์บอร์ดอื่นๆ ตอนเลือก pop-up อยู่จะได้ค่าตามคีย์ต่างๆ

Out[10]:
-1
Enter fullscreen mode Exit fullscreen mode

การค้นหาหลายใบหน้า
ชุดคำสั่ง cv2.CascadeClassifier() จะค้นหาใบหน้าทุกคนในรูป โดยจะให้ข้อมูลของตำแหน่งใบหน้าแต่ละใบมา ในการแสดงผล เราจะต้องนำตำแหน่งของทุกใบหน้ามาตีกรอบ โดยการใช้ for loop

ไฟล์รูป
faces.png ที่จะใช้เป็นตัวอย่างในการค้นหาใบหน้าหลายคน

Image description

In [11]:
imagePath = r'faces.jpg'
cascPath = "haarcascade_frontalface_default.xml"
​
image = cv2.imread(imagePath)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
​
faceCascade = cv2.CascadeClassifier(cascPath)
faces = faceCascade.detectMultiScale(gray)
​
print(f'There are {len(faces)} faces found.')
​
for (x, y, w, h) in faces:
 cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
​
cv2.imshow("Faces found", image)
cv2.waitKey(0) 
Enter fullscreen mode Exit fullscreen mode

การแสดงผลจากคำสั่ง print

There are 22 faces found. 
Enter fullscreen mode Exit fullscreen mode

ผลลัพธ์ที่ได้จากการปิด pop-up
ถ้ากดปิดที่ x ด้านขวาบน จะได้ return value -1 หรือถ้ากดคีย์บอร์ดอื่นๆ ตอนเลือก pop-up อยู่จะได้ค่าตามคีย์ต่างๆ

Out[11]:
-1
Enter fullscreen mode Exit fullscreen mode

สรุปผลลัพธ์ที่ได้บน pop-up
แสดงผลการตรวจจับใบหน้าโดยการตีกรอบใบหน้าที่เจอ ด้วยตำแหน่งที่ได้จากการตรวจจับด้วย Haar Cascades

Image description

References
https://towardsdatascience.com/face-detection-in-2-minutes-using-opencv-python-90f89d7c0f81

Top comments (0)