ตรวจจับใบหน้า ใน 11 บรรทัด Python Face Detection
Watasin
Posted on April 7, 2023
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 ที่เตรียมไว้แล้ว เพื่อทำแบบนี้
ข้อมูลที่ใช้
เราจะใช้รูปที่มีใบหน้าคนอยู่ และไฟล์ xml ที่เก็บข้อมูล haar cascades ที่ใช้เพื่อระบุใบหน้า
ไฟล์รูป
รูปตัวอย่าง PPg1.png ที่จะใช้เป็นตัวอย่าง
ไฟล์ cascade
สำหรับโปรแกรมที่ใช้ตรวจจับเราจะใช้โปรแกรมที่ทำสำเร็จไว้แล้วชื่อ haarcascade_frontalface_default.xml ที่เตรียมไว้ให้เรียบร้อย
ระบุตำแหน่งของไฟล์ไว้ใช้งาน
In [1]:
imagePath = r'ig-cover-1.png'
cascPath = "haarcascade_frontalface_default.xml"
ติดตั้ง opencv
ในการติดตั้งเราจะใช้ชื่อ opencv-python กับคำสั่ง pip install
In [1]:
!pip install opencv-python
นำเข้า opencv
ซึ่งใช้ชื่อว่า cv2 ในการนำเข้า
In [2]:
import cv2
การเปิดใช้
เราใช้คำสั่ง cv2.CascadeClassifier() ที่รับ path ไฟล์ของไฟล์ xml ที่เก็บ haar cascades ที่ใช้ระบุใบหน้า
In [3]:
faceCascade = cv2.CascadeClassifier(cascPath)
นำเข้าข้อมูล
เราจะนำเข้าข้อมูลผ่านคำสั่ง cv2.imread() ที่รับ path ไฟล์รูป
In [4]:
image = cv2.imread(imagePath)
แปลงรูปเป็นขาวดำ
ในกรณีนี้ cascade ของเราทำงานกับไฟล์รูปขาวดำ ซึ่งค่อนข้างปกติในการใช้กับโปรแกรมตรวจจับวัตถุ โดยเราจะใช้คำสั่ง cv2.cvtColor() รับค่า ภาพที่ต้องการเปลี่ยนค่าสี และ ตัวแปลงค่าสี เราจะใช้ cv2.COLOR_BGR2GRAY
In [5]:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
ใช้ haar cascade ตรวจจับใบหน้า
โดยใช้คำสั่ง .detectMultiScale() ที่ทำงานร่วมกับข้อมูลที่ได้จากการเปิด cascade ด้วยคำสั่ง .CascadeClassifier() และรับข้อมูลรูปขาวดำ ซึ่งเราจะได้ตำแหน่งของใบหน้าที่ตรวจเจอมาอยู่ใน array ของ array
In [6]:
faces = faceCascade.detectMultiScale(gray)
ข้อมูลที่ได้
เราจะได้ตำแหน่งของใบหน้าที่ตรวจเจอโดยการระบุ ตำแหน่ง x, ตำแหน่ง y, ความกว้าง, ความสูงของ "กรอบ" ที่ใช้ระบุตำแหน่งใบหน้า ตามลำดับ
In [7]:
faces
Out[7]:
array([[332, 272, 193, 193]], dtype=int32)
Unpacking
เราจะเก็บข้อมูลที่ได้มาแยกออกเป็นแต่ละตัวแปรแยกกันเพื่อให้นำไปใช้งานได้สะดวกยิ่งขึ้น
In [8]:
x, y, w, h = faces[0]
ตีกรอบใบหน้าที่เจอ
การตีกรอบ
ใช้คำสั่ง 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)
Out[9]:
array([[[228, 240, 243],
[230, 242, 244],
[230, 242, 244],
...
[127, 186, 192],
[126, 184, 192],
[126, 182, 192]]],
dtype=uint8)
การแสดงผลลัพธ์
ใช้คำสั่ง cv2.imshow() ที่รับค่า string ที่ใช้ตั้งชื่อหน้าต่างที่ใช้แสดงผลรูป และรับค่ารูปภาพที่ต้องการแสดง (รูปภาพที่ผ่านการตีกรอบ) ซึ่งการใช้งาน cv2.imshow() โดยจะต้องใช้คำสั่ง cv2.waitKey(0) ตามเข้าไปเพื่อป้องกันโปรแกรม crash ซึ่งเป็นคำสั่งที่ใช้หยุดการแสดงผลเมื่อมีการกดคีย์บอร์ดเมื่อเลือก pop-up หรือการกดปิด pop-up
In [10]:
cv2.imshow("Faces found", image)
cv2.waitKey(0)
ผลลัพธ์ที่ได้จากการปิด pop-up
ถ้ากดปิดที่ x ด้านขวาบน จะได้ return value -1 หรือถ้ากดคีย์บอร์ดอื่นๆ ตอนเลือก pop-up อยู่จะได้ค่าตามคีย์ต่างๆ
Out[10]:
-1
การค้นหาหลายใบหน้า
ชุดคำสั่ง cv2.CascadeClassifier() จะค้นหาใบหน้าทุกคนในรูป โดยจะให้ข้อมูลของตำแหน่งใบหน้าแต่ละใบมา ในการแสดงผล เราจะต้องนำตำแหน่งของทุกใบหน้ามาตีกรอบ โดยการใช้ for loop
ไฟล์รูป
faces.png ที่จะใช้เป็นตัวอย่างในการค้นหาใบหน้าหลายคน
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)
การแสดงผลจากคำสั่ง print
There are 22 faces found.
ผลลัพธ์ที่ได้จากการปิด pop-up
ถ้ากดปิดที่ x ด้านขวาบน จะได้ return value -1 หรือถ้ากดคีย์บอร์ดอื่นๆ ตอนเลือก pop-up อยู่จะได้ค่าตามคีย์ต่างๆ
Out[11]:
-1
สรุปผลลัพธ์ที่ได้บน pop-up
แสดงผลการตรวจจับใบหน้าโดยการตีกรอบใบหน้าที่เจอ ด้วยตำแหน่งที่ได้จากการตรวจจับด้วย Haar Cascades
References
https://towardsdatascience.com/face-detection-in-2-minutes-using-opencv-python-90f89d7c0f81
Posted on April 7, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.