Car Logo classification with HOG
Histogram of Oriented Gradients (HOG) and K-Nearest Neighbours (KNN)
กลับมาเขียนเกี่ยวกับ Computer vision หลังจากที่เขียนเกี่ยวกับ Credit risk มานาน เริ่มรู้สึกว่าเบื่อ อยากหาอะไรอย่างอื่นเขียนบ้าง Blog ตอนนี้เลยหยิบเอาเรื่องพื้นฐานในงาน Image คือการทำ Features extraction ด้วย HOG ซึ่งเป็นรากฐานของ Computer vision ในสมัยก่อน ที่ในปัจจุบันดโดน AI เก่ง ๆ แซงหน้าไปหมดแล้ว แต่ส่วนตัวแล้วรู้สึกว่าเป็นพื้นฐานที่ดีที่ควรรู้ไว้
เนื้อหาของ Blog ตอนนี้จึงเป็นการแยก Logo ของรถแบรนด์ต่าง ๆ ด้วย Features ที่สกัดออกมาด้วย HOG (Histogram of Oriented Gradients)
Histogram of Oriented Gradients (HOG)
Histogram of Oriented Gradients (HOG) เป็นวิธีการสกัด Features (Features extraction) ในงานที่เป็น Image processing รูปแบบนึง อาจดูย้อนหลังไปบ้างสำหรับ Model ในปัจจุบันนี้ แต่ HOG เป็นพื้นฐานของ Computer vision ในสมัยก่อน ๆ
การทำงานแบบ High-level ของ HOG มีขั้นตอนหลักประมาณ 4 ขั้นตอนคือ
- ต้องมีรูปภาพหรือ Areas ของ Object ที่ต้องการทำ Features extraction หลักการของ HOG คือต้องปรับสัดส่วน (Fix ratio) ของ Image หรือ Object ให้อยู่ในอัตราส่วน 2:1 หรือ 1:2 ตามรูปภาพว่าเป็นแนวนอนหรือแนวตั้ง
- จากนั้นแบ่งรูปหรือ Object ออกเป็น Grip โดยสามารถกำหนดได้ว่าใน 1 Grip (Cell) ให้บรรจุ Pixel จำนวนเท่าไหร่ เช่น 8x8 หรือ 10x10 เป็นต้น ดังนั้นใน 1 Cell ประกอบไปด้วยตัวเลขทั้งหมดเท่ากับผลคูณของ Pixel ตามที่กำหนด
- ในแต่ละ Cell มีการคำนวณค่า Feature vector จากทั้ง 2 Directions (X และ Y) ค่าที่ได้ออกมาคือ Gradient direction และ Gradient magnitude (มีสูตรในการคำนวณ) ค่า Gradient magnitude ถูกนำมากระจายเป็นฐาน Histogram โดยที่สามารถกำหนดความถี่ของ Bins ได้จาก Option ที่เรียกว่า
orientations
และค่า Gradient direction จะถูกนำใส่เข้าไปใน Histogram ตามความถี่ที่เกิดขึ้น เมื่อคำนวณทั้ง Cell แล้ว สิ่งได้ที่มาคือ Feature vector - ทำซ้ำตามขั้นตอนที่ 3 ด้วยการเคลื่อน Cell ไปทางขวาจนครบ จากนั้นให้เริ่มใหม่ทำซ้ำใหม่โดยเคลื่อน Block ลงด้านล่างและเริ่มต้นจากทางซ้าย จนครบทั่วทั้งรูปภาพ โดยที่ Block คือขนาดที่ต้องการบรรจุ Cell ลงไปในข้างใน สามารถกำหนดได้ด้วย Option
cells_per_block
สำหรับวิธีการคำนวณ HOG โดยละเอียด พร้อมตัวอย่างสามารถดูได้จาก Link ด้านล่าง เพื่อทำความเข้าใจเพิ่มเติม
Dataset and image processing
Dataset ที่ใช้ใน Blog ตอนนี้เป็น Logo ของรถยี่ห้อต่าง ๆ ที่แตกต่างกันทั้งหมด 8 แบรนด์ เช่น Toyota, Mercedes เป็นต้น สามารถ Download dataset ได้จาก Kaggle ตาม Link ที่อยู่ด้านล่าง
เนื่องจากรูปภาพใน Dataset อาจไม่ใช่เป็น Logo เดี่ยว ๆ เสมอไป บางครั้งอาจเป็นรูป Logo ที่มาพร้อมกับตัวหนังสือ หรือ Logo ที่อยู่บนล้อรถ ดังนั้นจึงต้องมี Image processing เพิ่มเข้ามาในการสร้าง Dataset ใหม่
หลังจาก Import libraries ที่ต้องใช้งานทั้งหมดแล้ว ขอยกตัวอย่างเป็นรูป 1 เพื่อให้เห็นเป็นขั้นตอนการทำ Image processing ว่ามีขั้นตอนเป็นอย่างไรบ้าง
จากรูปตัวอย่างเป็น Logo ของยี่ห้อ Hyundai แต่มีตัวหนังสือ HYUNDAI และ shutterstick.com 205266296 ติดมาด้วย ดังนั้นจึงจำเป็นลบข้อมูลที่ไม่จำเป็นเหล่านี้ออกก่อนทำ HOG Features extraction
ขั้นตอนแรกที่นิยมทำกันในงาน Computer vision คือลด 3-Channels RGB (รูปสี) ให้เป็น Gray scale ที่มี 1-Channels (ขาว-ดำ)
หลังจากนั้นให้สร้าง “ขอบ” ของรูปภาพด้วย imutils.auto_canny()
เมื่อได้ขอบทั้งหมดที่ปรากฎอยู่ในรูปภาพแล้ว ขั้นตอนต่อไปคือการ “หาเส้นขอบ” ที่มีในรูป ใช้ cv2.findContours()
ใช้ Option mode
เป็น cv2.RETR_EXTERNAL
หมายถึงให้พิจาณาเฉพาะกรอบ “ด้านนอก” เท่านั้น ต่อมาเป็นเรื่องของรายละเอียดของเส้นขอบใช้ method เป็น cv2.CHAIN_APPROX_SIMPLE
หมายถึงเก็บรายละเอียดเฉพาะส่วนที่จำเป็น เพราะใช้การประมวลผลน้อยกว่า
ใช้ imutils.grab_contours()
เพื่อเก็บ Array ของเส้นขอบทั้งหมด จากนั้นให้เก็บเฉพาะพื้นที่ใน Array ที่ใหญ่ที่สุด โดย Assume ว่าเป็นตำแหน่งของ Logo กรณีนี้อาจใช้ไม่ได้รูป Logo ที่อยู่ในล้อ เพราะพื้นที่อื่นของล้อควรมีขนาดใหญ่กว่า แต่ถ้า Dataset ส่วนมากไม่ได้มีรูปล้อ Assumption นี้ยังใช้ได้
จากนั้นสร้างตำแหน่งกรอบ (x, y, w, h) ขึ้นมาด้วย cv2.boundingRect()
และตัดเฉพาะพื้นใน [y:y + h, x:x + w]
ผลลัพธ์ที่ออกจะได้เป็นรูปที่มีเฉพาะ Logo โดยตัดส่วนอื่น ๆ เช่นตัวหนังสือออกไป
ตามที่ได้เคยอธิบายไว้ด้านบนว่า HOG ต้องการรูปภาพที่มีขนาด 2:1 ดังนั้นให้ Resize รูปภาพตามสัดส่วนดังกล่าว ใน Blog ตอนนี้ใช้ (200, 100)
หากต้องการภาพที่มีขนาดใหญ่มากกว่านี้ อาจใช้เป็น (400, 200)
โดยคงสัดส่วนเดิมที่ 2:1
ใช้ ้hog()
จาก Library Scikit-image เพื่อ Extract features จากรูปภาพออกมา หากต้องให้แสดงผลเป็นรูปภาพ HOG ให้ใส่ Option visualize = True
แต่ในตอนสร้าง Dataset อาจไม่จำเป็น
นำขั้นตอนทั้งหมดเขียนเป็น Iteration เพื่อสร้างเป็น List ที่มี HOG Features ของรูปภาพแต่ละรูปเก็บไว้ภายใน และ Labels เก็บเป็นชื่อของยี่ห้อรถ สามารถดึงมาจาก Folder name ได้
Processing car bard: volkswagen
Processing car bard: mazda
Processing car bard: hyundai
Processing car bard: mercedes
Processing car bard: opel
Processing car bard: toyota
Processing car bard: lexus
Processing car bard: skoda
ขั้นตอนสุดท้ายในการสร้าง Dataset คือการเปลี่ยนให้เป็น Numpy array สำหรับใช้ใน ML Model ต่อไป
K-Nearest Neighbours (KNN)
จาก Iteration ที่สร้างขึ้นเป็นการ Append data เข้าไปเรื่อย ๆ ดังนั้นให้ shuffle()
ข้อมูลก่อนเริ่มสร้าง Model เพื่อไม่ให้ข้อมูลไปกองที่ใดที่หนึ่ง และเนื่องจากต้องการใช้เทคนิค Cross-validation จึงไม่ได้เป็นข้อมูลออกเป็น Train/Test
KNN ไม่จำเป็นต้องเปลี่ยนค่าตัวแปร y ให้เป็นตัวเลข สามารถใส่เข้าไปใน ML ได้เลยตรง ๆ ทำ Hyperparameters tuning ง่าย ๆ เช่นการหา Number of neighbors ที่ต้องการใช้ในการ Build model โดยใช้ cross_val_score()
และแบ่ง Validation เป็นทั้งหมด 10 Sets วัดผลด้วย Accuracy matrix
การแบ่งด้วย n_neighbors = 5
ให้ Accuracy score สูงที่สุด
Model score: 76.87%
Result
วัดผล Prediction ด้วย Confusion matrix สามารถบอกได้ว่า Logo ยี่ห้อไหนที่ไปสลับกับแบรนด์อื่นบ้าง จากรูปด้านล่างสังเกตได้ว่า Mercedes, Lexus และ Mazda ค่อนข้างไปสลับกับแบรนด์อื่น ๆ แต่ส่วนใหญ่แล้วยัง Predict ได้ถูกตามแบรนด์
ผล Model ถือว่าเป็นที่น่าพอใจแล้ว สามารถ .dump()
โมเดลนี้เก็บไว้ได้ เพื่อที่ต่อไปไม่จำเป็นต้อง Training ใหม่
ขั้นตอนการ Prediction จำเป็นต้องเปลี่ยนรูปที่ใช้ทดสอบ ให้เหมือนกับใน Image processing ด้านบน แล้วจึงใช้ .predict()
เพื่อทำนายผลลัพธ์
นำ Function ที่เขียนมาใส่ใน Iteration เพื่อ Call ผลลัพธ์ออกมาทีละรูป
Conclusion
Blog ตอนนี้การนำเสนอรูปแบบการทำ Computer vision จากสมัยก่อน ถ้าคนอาจเรียกว่าเป็น Old school วิธีการนี้อาจไม่ค่อยได้พบเจอแล้วใน Model ปัจจุบัน แต่ถือว่าเป็นพื้นฐานที่ดีมาก สำหรับงาน Computer vision
สำหรับ Colab notebook ของเนื้อหาทั้งตอน สามารถดูได้ที่ Link ด้านบน