ตรวจจับใบหน้า ใน 11 บรรทัด Python Face Detection
Tags: ai, python, tutorial, machinelearning
Published: 2023-04-07 17:33:44

**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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fe1d7ghwcqcsulla117w.png)

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

**ไฟล์รูป**
รูปตัวอย่าง PPg1.png ที่จะใช้เป็นตัวอย่าง
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/95ebrefg0oc0uzv5rngc.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 ที่จะใช้เป็นตัวอย่างในการค้นหาใบหน้าหลายคน

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d667f9ftlcdmwpduzdsc.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

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iaqn9puysufq9ty0efu5.png)

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