<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Watasin</title>
    <description>The latest articles on DEV Community by Watasin (@watasin).</description>
    <link>https://dev.to/watasin</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1060886%2F91182e1a-1f52-4e1b-9cfc-9afe9b694fde.png</url>
      <title>DEV Community: Watasin</title>
      <link>https://dev.to/watasin</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/watasin"/>
    <language>en</language>
    <item>
      <title>ตรวจจับใบหน้า ใน 11 บรรทัด Python Face Detection</title>
      <dc:creator>Watasin</dc:creator>
      <pubDate>Fri, 07 Apr 2023 17:33:44 +0000</pubDate>
      <link>https://dev.to/watasin/trwcchcchabaibhnaa-ain-11-brrthad-python-face-detection-3a38</link>
      <guid>https://dev.to/watasin/trwcchcchabaibhnaa-ain-11-brrthad-python-face-detection-3a38</guid>
      <description>&lt;p&gt;&lt;strong&gt;Face Dectection คืออะไร?&lt;/strong&gt;&lt;br&gt;
การตรวจจับใบหน้าเป็นเทคนิคในสาขา computer vision ที่เน้นการพัฒนาโปรแกรมให้สามารถทำความเข้าใจ "ข้อมูล" ที่อยู่ในรูปภาพ โดยอาศัยการตรวจจับ classifier ที่เป็นส่วนย่อยของใบหน้า ที่อาจมีมากถึง 6000++ classifier ที่ใช้ระบุใบหน้าบุคคล&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;Haar Cascades คืออะไร?&lt;/strong&gt;&lt;br&gt;
เป็น 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 ที่ปรับแต่งสำหรับการจับใบหน้านั่นเอง&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Visualization การทำงานของ Haar Cascade : &lt;a href="https://youtu.be/hPCTwxF0qf4"&gt;https://youtu.be/hPCTwxF0qf4&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;วันนี้เราจะสร้าง Face Detection Model ที่ใช้ตรวจจับใบหน้าภายใน 10 บรรทัดโดยการใช้ Haar Cascades ที่เตรียมไว้แล้ว เพื่อทำแบบนี้&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s6hedR0T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fe1d7ghwcqcsulla117w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s6hedR0T--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/fe1d7ghwcqcsulla117w.png" alt="Image description" width="601" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;ไฟล์รูป&lt;/strong&gt;&lt;br&gt;
รูปตัวอย่าง PPg1.png ที่จะใช้เป็นตัวอย่าง&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--g_hKvPFh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/95ebrefg0oc0uzv5rngc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--g_hKvPFh--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/95ebrefg0oc0uzv5rngc.png" alt="Image description" width="600" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;ระบุตำแหน่งของไฟล์ไว้ใช้งาน&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In [1]:
imagePath = r'ig-cover-1.png'
cascPath = "haarcascade_frontalface_default.xml"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ติดตั้ง opencv&lt;/strong&gt;&lt;br&gt;
ในการติดตั้งเราจะใช้ชื่อ opencv-python กับคำสั่ง pip install&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In [1]:
!pip install opencv-python
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;นำเข้า opencv&lt;/strong&gt;&lt;br&gt;
ซึ่งใช้ชื่อว่า cv2 ในการนำเข้า&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In [2]:
import cv2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In [3]:
faceCascade = cv2.CascadeClassifier(cascPath)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In [4]:
image = cv2.imread(imagePath)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In [5]:
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In [6]:
faces = faceCascade.detectMultiScale(gray)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In [7]:
faces
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Out[7]:
array([[332, 272, 193, 193]], dtype=int32)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In [8]:
x, y, w, h = faces[0]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ตีกรอบใบหน้าที่เจอ&lt;/strong&gt;&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In [9]:
cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 2)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Out[9]:
array([[[228, 240, 243],         
[230, 242, 244],         
[230, 242, 244],         

...     

[127, 186, 192],         
[126, 184, 192],         
[126, 182, 192]]], 
dtype=uint8)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In [10]:
cv2.imshow("Faces found", image)
cv2.waitKey(0)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Out[10]:
-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v3_27j9c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d667f9ftlcdmwpduzdsc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v3_27j9c--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/d667f9ftlcdmwpduzdsc.png" alt="Image description" width="600" height="429"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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) 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;การแสดงผลจากคำสั่ง print&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;There are 22 faces found. 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Out[11]:
-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rrNw-S-m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iaqn9puysufq9ty0efu5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rrNw-S-m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/iaqn9puysufq9ty0efu5.png" alt="Image description" width="356" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://towardsdatascience.com/face-detection-in-2-minutes-using-opencv-python-90f89d7c0f81"&gt;https://towardsdatascience.com/face-detection-in-2-minutes-using-opencv-python-90f89d7c0f81&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>python</category>
      <category>tutorial</category>
      <category>machinelearning</category>
    </item>
  </channel>
</rss>
