ESPIno32CAM : ตรวจจับใบหน้า
ตัวอย่างการใช้งาน ESPIno32CAM เพื่อถ่ายภาพ และ ตรวจหาพิกัดของใบหน้ามนุษย์ภายในภาพ
เริ่มต้นการทดลอง
– เปิดโปรแกรม Arduino IDE
– เปิดตัวอย่าง File > Example >ESPIno32CAM > EX_FaceDetect

– ตั้งค่า Arduino IDE ให้ใช้งานกับ ESPIno32CAM --> (Link)
– Upload Program ลงไปยัง ESPIno32CAM

-เปิด Program JPG Serial Streaming
1 เลือก Comport ให้ตรงกับ Comport ของบอร์ด ESPIno32
2 เลือก Baudrate ให้ตรงกับ Baudrate ใน Code Arduino (Default =2000000 )
3 กด Button Connect
!!! ก่อนกด Button Connect จะต้องปิด Program อื่นๆ ที่ใช้งาน Comport อยู่ เช่น หน้าต่าง Serial Monitor ของ ArduinoIDE เป็นต้น

– โปรแกรม JPG Serial Streaming จะแสดงรูปภาพที่ถ่ายจากบอร์ด ESPIno32CAM บน PictureBox และ ถ้าหากสามารถตรวจจับใบหน้าภายในภาพได้ จะแสดงกรอบล้อมรอบใบหน้า และ แสดงพิกัดจุด landmark 5 จุด
ภายในส่วนแสดงข้อความก็จะแสดงข้อมูล จำนวนใบหน้าที่พบ , ID ของใบหน้า , พิกัดเริ่มต้นของใบหน้า และ ขนาด กว้าง,ยาว ของกรอบ
หลักการทำงาน
Face Detection ของ ESP32 นั้นใช้โมเดลการตรวจจับใบหน้าที่ชื่อว่า MTMN ซึ่งเป็นโมเดลที่ใช้ทรัพยากรณ์ในการประมวลผลตรวจจับใบหน้าน้อย ออกแบบมาสำหรับใช้งานบน Embedded Device ซึ่งมีการทำงานแบ่งออกเป็น 3 ส่วนหลักๆได้แก่
– Proposal Network (P-Net)
นำเสนอ bounding box ที่เป็นตัวเลือกส่งต่อไปยัง R-Net
– Refine Network (R-Net)
คัดเลือก bounding box ที่ P-Net ส่งมา
– Output Network (O-Net)
ส่งผลลัพธ์ออกมา เป็นค่า bounding box ที่ถูกต้องแม่นยำ ค่าความน่าเชื่อถือ และจุดกำหนดตำแหน่ง 5 จุด

การกำหนดค่าให้ MTMN จะต้องทำการตั้งค่า threshold ต่างๆผ่าน structure mtmn_config_t โดยภายใน structure mtmn_config_t จะประกอบด้วย ตัวแปร และ structure ภายในดังนี้

– float min_face
คือ ตัวแปรสำหรับกำหนดขนาดภาพใบหน้าที่มีขนาดเล็กที่สุดที่จะนำประมวลผล ซึ่งสามารถกำหนดค่าได้น้อยที่สุดคือใบหน้าขนาด 12 โดย min_face จะเป็นค่าที่วัดจากค่าความยาวของด้านที่สั้นที่สุดของภาพ input ผลของการตั้งค่า min_face เมื่อกำหนดให้ยิ่งมีค่าน้อยก็จะยิ่งทำให้ใช้เวลาในการปนะมวลผลมากขึ้นตามขนาดที่น้อยลง แต่จะส่งผลให้เกิดตรวจจับใบหน้าที่มีขนาดแตกต่างกันได้มากขึ้น ยกตัวอย่างเช่น ตรวจสอบใบหน้าที่อยู่ไกลจากตัวกล้องได้มากขึ้น (หน้าที่ภาพเล็กลง)
– float pyramid
คือ ตัวแปรสำหรับกำหนดสเกลการ Resize ภาพ สามารถกำหนดได้ตั้งแต่ 0.0 – 1.0 โดยถ้าหากกำหนดค่า pyramid มากขึ้นก็จำทำให้เกิดความละเอียดในการ ย่อรูปภาพมากขึ้น ส่งผลให้มีภาพทีต้องประมวลผลมากขึ้น เกิดการตรวจจับภาพใบหน้ามากขึ้น เวลาในการประมวลผลก็จะมากขึ้นเช่นกัน

– p_threshold , r_threshold , o_threshold
คือ ค่า threshold สำหรับกำหนดการคัดกรอง ของ P-Net, R-Net, O-Net โดย
P-Net คือ ส่วนตรวจสอบและตีกรอบ พิกัดในภาพที่คาดว่าน่าจะเป็นส่วนที่มีใบหน้าอยู่ แล้วส่งไปยัง R-Net
R-Net คือ ส่วนที่คัดกรองข้อมูลที่ได้รับ P-Net กรองเอาเฉพาะข้อมูลที่ควนจะเป็นใบหน้า
O-Net คือ ส่วนที่นำเอาข้อมูลที่คัดกรองแล้วจาก R-Net มาหาค่าที่ถูกต้องแม่นยำ ค่าความน่าเชื่อถือ และจุดกำหนดตำแหน่ง 5 จุด (Landmark)

Structure threshold_config_t

– score
คือค่า threshold ของ confidence coefficient (สัมประสิทธิ์ความ เชื่อมัน)ถ้า candidate bounding box มีค่าความน่าเชื่อถือน้อยกว่าค่าที่กำหนดไว้ จะถูกคัดกรองออกไป
– ช่วงค่าที่กำหนดได้ 0.0 – 1.0
– nms
คือค่า threshold ของ NMS ถ้า candidate bounding box มี overlapping ratio สูงกว่าค่าที่กำหนดไว้จะถูกคัดกรองออกไป
– ช่วงค่าที่กำหนดได้ 0.0 – 1.0
– Candidate
คือค่า จำนวนมากที่สุดของ bounding box ที่ให้มีได้แต่จะมีเพียงหมายเลขแรกเท่านั้นที่จะถูกเก็บค่าไว้
– ช่วงค่าที่กำหนดได้
R-Net กำหนดได้ 1-4
O-Net กำหนดได้ 1-2
P-Net กำหนดได้ 4 เท่านั้น (ยังไม่ให้ผู้ใช้ปรับค่าได้ในตอนนี้)
ตัวอย่างโปรแกรมที่ใช้
#include "ESPino32CAM.h" ESPino32CAM cam; static mtmn_config_t mtmn_config = {0}; void setup() { Serial.begin(2000000); Serial.println("\r\nESPino32CAM"); if (cam.init() != ESP_OK) { cam.printDebug(F("Init Fail")); while (1); } sensor_t *s = cam.sensor(); s->set_framesize(s, FRAMESIZE_QVGA); mtmn_config.min_face = 80; mtmn_config.pyramid = 0.7; mtmn_config.p_threshold.score = 0.6; mtmn_config.p_threshold.nms = 0.7; mtmn_config.r_threshold.score = 0.7; mtmn_config.r_threshold.nms = 0.7; mtmn_config.r_threshold.candidate_number = 4; mtmn_config.o_threshold.score = 0.7; mtmn_config.o_threshold.nms = 0.4; mtmn_config.o_threshold.candidate_number = 2; } void loop() { camera_fb_t *fb = cam.capture(); if (!fb) { cam.printDebug("Camera capture failed"); return; } dl_matrix3du_t *rgb888; if (cam.jpg2rgb(fb,&rgb888)) { cam.clearMemory(fb); box_array_t *net_boxes = cam.faceDetect(rgb888, &mtmn_config); if (net_boxes) { cam.printDebug(""); cam.printfDebug("Found %d face",net_boxes->len); int x, y, w, h, i; for (i = 0; i < net_boxes->len; i++) { x = (int)net_boxes->box[i].box_p[0]; y = (int)net_boxes->box[i].box_p[1]; w = (int)net_boxes->box[i].box_p[2] - x + 1; h = (int)net_boxes->box[i].box_p[3] - y + 1; cam.printfDebug("Face:%d\r\nOrigin: (x:%d,y:%d)\r\nWide: %d\r\nHigh: %d",i,x,y,w,h); } cam.drawFaceBoxes(rgb888, net_boxes, true); cam.clearMemory(net_boxes); } } uint8_t *jpgout; size_t jpglen; if (cam.rgb2jpg(rgb888,&jpgout, &jpglen)) Serial.write(jpgout, jpglen); cam.clearMemory(jpgout); cam.clearMemory(rgb888); }
คำอธิบาย Code Program
บรรทัดที่ 1: ประกาศใช้ Library ESPIno32CAM
บรรทัดที่ 2: สร้าง Object cam
บรรทัดที่ 3: สร้าง Structure mtmn_config ชื่อ mtmn_config
บรรทัดที่ 7: Initial โมดูลกล้อง
บรรทัดที่ 13: กำหนดให้ถ่ายภาพขนาด QVGA (320×240 Pixel)
บรรทัดที่ 16-23: กำหนดค่า threshold ให้กับ mtmn เพิ่มเติม
บรรทัดที่ 27: ถ่ายรูปแล้วเก็บ JPG File ยัง fb
บรรทัดที่ 34: แปลง JPG File ให้อยู่ในรูปแบบ RGB (R 8 bits , G 8 bits , B 8 bits) แล้วเก็บลงใน dl_matrix3du_t *rgb888
บรรทัดที่ 36: คืนค่า Memory ตัวแปล fb ที่เก็บ jpg ให้ส่วนกลาง
บรรทัดที่ 37: นำภาพที่แปลงเป็น RGB 888 และ ค่า mtmn_config_t เข้าไปประมวลผลหาใบหน้าในภาพ แล้วเก็บผลลัพธ์ลงใน net_boxes
บรรทัดที่ 38: ถ้าหากตรวจพบใบหน้า net_boxes จะมีค่ามากกว่า 0
บรรทัดที่ 41: แสดงค่า จำนวนใบหน้าที่สามารถตรวจเจอจาก net_boxes->len
บรรทัดที่ 43-48: หาขนาดกว้าง,ยาว ของกรอบสี่เหลี่ยมรอบใบหน้าโดยตัวแปร box_p[0],box_p[1] คือ พิกัด x,y ของจุดเริ่มต้น และ box_p[2],box_p[3] คือพิกัดสิ้นสุด

บรรทัดที่ 49: แสดงผล พิกัดจุดเริ่มต้น และ ความกว้างยาวของกรอบปิดล้อมใบหน้า
บรรทัดที่ 51: ใช้ function drawFaceBoxes เขียนกรอบ สี่เหลี่ยมปิดล้อมใบหน้าลงไปยัง รูปภาพในตัวแปร rgb888
บรรทัดที่ 52: คือค่า Memory net_boxes
บรรทัดที่ 58: ใช้ function rgb2jpg แปลงรูปภาพ RGB 888 กลับไปเป็น JPG File
บรรทัดที่ 59: ส่งรูปภาพ JPG File ออกไปทาง Serial เพื่อไปแสดงผลยังโปรแกรม JPG Serial Streaming
บรรทัดที่ 60-61: คืน Memory