AI
[Project] 2D Cephologram ai landmark detection and segmentation internship
สรุปโปรเจค 2D Cephologram ai landmark detection and segmentation internship
.png&w=3840&q=75)
Overview
โปรเจคนี้เกิดจากกการฝึกงาน6สัปดาห์ที่คลินิกSingdent (Singapodent Digital)ในเวียดนาม เป้าหมายคือช่วยวิเคราะห์ภาพcephalogramซึ่งปกติแพทย์ต้องทำด้วยมือ
- เริ่มตั้งแต่การsetup CVATสำหรับแพทย์annotationข้อมูล โดยมีlandmark 10จุด, segmentation 3 โครงสร้าง (และผมannotateเองสำหรับเส้นไม้บรรทัด 30mmในภาพcephสำหรัยcalibration)
- ด้านMLผมใช้YOLOหาพื้นที่ของฟันก่อนแล้วcropส่งต่อให้HRNet-W32ที่ทำ ensemble 5 folds เพื่อหาlandmark, ส่วนsegmentationใช้nnU-Net ensemble 5 folds เพื่อแยกกระดูกฟันกับตัวฟัน
- หลังจากได้ส่วนที่ต้องการจะนำไปคำนวณหาระยะห่างและองศา U1-PPเพื่อนำไปสร้างคำแนะนำสำหรับการรักษาคนไข้ต่อไป (เป็นrue-basedที่อิงตามคลินิกกำหนดมา)
- เชื่อมทั้งหมดด้วยFastAPI สร้างdashboardด้วย Astro, React และ Konva เพื่อให้แพทย์แก้ landmark, segmentationได้ หากมีการแก้ระบบจะคำนวณผลลัพท์ใหม่
Architecture


ML Part
Annotation Schema
จากdata 382รูป โดยจะแบ่งงานให้แพทย์annotateซึ่งหากภาพมีวัตถุบังฟันบริเวณที่เราสนใจ(เช่น มีเหล็กบัง) หรือภาพดังกล่าวแพทย์มองว่ามีความเบลอหรือในมุมมองหมอมองยาก จะQuality Rejectออกทำให้เหลือ 278ภาพ โดยannotationจากCVATจะประกอบด้วย
Landmark 10 จุด
- Upper_tip
- Upper_apex
- Labial_midroot
- Labial_crest
- Palatal_midroot
- Palatal_crest
- ANS (Anterior Nasal Spine)
- PNS (Posterior Nasal Spine)
- LB (Labial bone level)
- PB (Palatal bone level)
Segmentation 3 class
- Upper_incisor
- Labial_bone
- Palatal_bone
Calibration
แต่ละภาพจะมีเส้น Calibration_30mm สองจุด

หลังจากนั้นเอาทุกภาพมาเฉลี่ยกันจนได้ค่าcallibration (ไม่ได้มีโมเดลที่ใช้detectไม้บรรทัดเนื่องจากออกแบบให้ใช้กับเครื่องเดียว)
Landmark Detection
YOLO
ใช้เพื่อหาbounding boxของmaxilla/incisor region โดยมีขั้นตอน
- ส่งภาพrawเข้า YOLO
- เลือกbounding boxแรก (หากหาไม่เจอจะใช้ภาพraw)
- เพิ่ม padding 10%
- clamp ให้อยู่ในขอบภาพ
- cropแล้วresizeเป็น512 * 512 (สำหรับHRNet)
HRNet-W32
HRNet เป็น1ในโมเดลที่ทำคะแนนได้อันดับต้นๆในงานประเภทนี้ และยังรักษาhigh-resolution featureตั้งแต่ต้นจนจบ(ตามชื่อ)

https://www.mathworks.com/help/vision/ug/hrnetarchitecture.png
Step:
- เรียก HRNet 5 folds
- แต่ละโมเดลทำนายheatmap
- ใช้hard argmax หา coordinate x, y
- เฉลี่ย coordinate และ confidence ของทั้ง5โมเดล
- remap จากที่cropมาเป็นสเกลภาพปกติ

Segmentation / nnU-Net
โดยเริ่มต้นจากการแบ่งclasses
- background
- upper incisor
- labial bone
- palatal bone
Step:
- แปลงภาพเป็นgrayscale
- จัดtensor/array เป็น shape ที่nnU-Netต้องการ (Batch size, Channels, H, W)
- เรียก nnU-Netทั้ง 5 folds
- interference ด้วย Gaussian tillingก(มันคือsliding window ที่เพิ่มweightเข้าไป) และ mirroring
- ได้class map
- แยกเป็นbinary masks 1, 2, 3
- หา largest valid contour
- simplify contour แล้วส่ง polygon ไป frontend
Clinical Output
หลังจากที่เราได้ coordinate และ class ก็เหลือเพียงแค่การวัดระยะห่างและมุมที่คลินิกต้องการ ซึ่งส่วนใหญ่จะเป็นrule-basedตามที่แพทย์กำหนดมาทั้งหมด
- U1-PP angle
- U1 axis: Upper_tip → Upper_apex
- Palatal plane: ANS → PNS
- นำvectorมา dot product → arccosine เพื่อให้ได้มุมองศาและนำไป classification ผลลัพท์ที่คลินิกต้องการอีกที
- Bone distances
โดยทั่วไปทางการแพทย์จะแบ่งเป็น 4 types หลักๆเพียงแค่วัดระยะระหว่าง labial และpalatalเทียบกับฟัน แปลงเป็นmm แล้วclassificationผลลัพท์เช่นเดิม - Treatment recommend
นำผลจาก
ไปclassificationที่คลินิกกำหนดเช่นเดิม - U1-PPP angle
- Root apex position
- labial/palatal bone availability
Dashboard Part
เนื่องจากเวลามีน้อยมากๆตรงส่วนนี้ รวมถึงfullstackเป็นงานที่ผมค่อนข้างไม่ถนัด จึงใช้Minimax M3คู่กับ Pi Agent ในการช่วยจัดการส่วนนี้เป็นหลัก
Frontend
ใช้
- Astro
- React
- Tailwind
- Konva
Workflow:
- เลือกภาพ
- preview ด้วย browser object URL
- POST
/api/v1/analyze - แปลง API landmarks/polygons เป็น Konva objects
- วาด overlay บนภาพ
- แพทย์แก้ไข landmark หรือ polygon vertex
- undo ได้สูงสุด 20 snapshots
- autosave annotations ลง localStorage
- กด Confirm ส่ง POST
/api/v1/recalculate
(backend ไม่รัน ML ใหม่ แค่คํานวณ geometry ใหม่)
Backend
FastAPI มี endpoints หลัก:
- GET
/api/v1/health - POST
/api/v1/analyze - POST
/api/v1/recalculate
Model service เป็น lazy singleton:
- ยังไม่โหลด model ตอน import/startup
- request
/analyzeแรกเป็นคนโหลด YOLO, HRNet 5 folds และ nnU-Net 5 folds
Result
Fold MRE | 1.640, 1.539, 1.744, 1.624, 1.575 mm |
|---|---|
Mean MRE | 1.624 mm |
Dice | 0.836 |
Takeaway
ว่ากันตามตรงงานนี้คืองานแรกที่ผมได้ทำComputer Visionขนาดนี้ เทียบกับโปรเจคที่ทำเล่นๆไม่ได้เลย ผมคิดว่าผมมีข้อผิดพลาดหลายๆอย่างที่ไม่ได้ตรวจสอบ และปล่อยหลุดไป ทั้งด้วยเวลาที่มีข้อจำกัดและทำทั้งหมดเพียงคนเดียวโดยไม่มีmentor (บริษัททำเกี่ยวกับทัตกรรมล้วนๆแทบไม่มีทีมเทค) โดยมีข้อผิดพลาดดังนี้
- การสื่อสารที่ไม่ชัดเจนในการทำData Guideline: เนื่องจากมีแพทย์หลายคนทำannotationถึงแม้ผมจะเขียน docs คร่าวๆแต่ไม่ได้ถือว่าอยู่ในเกณท์ที่ดีขนาดนั้นและมีจุดที่ทำให้แพทย์เข้าใจผิดได้อยู่
- ให้แพทย์ทำannotationหลายคน: มีแพทย์ที่แบ่งงานกันทำannotationประมาณ4 batchแต่เนื่องจากเป็นงานทางการแพทย์ จุดหลายๆจุดแพทย์ทั้ง4คนอาจplotคนละจุดด้วยซ้ำ ซึ่งเป็น1ในสิ่งที่ทำให้เกิดnoiseและส่งผลต่อaccuracy
- การไม่ได้แบ่งdataมาสำหรับการทำensemble: เนื่องจากตอนแรกผมกะใช้5-folds cvทำให้พอช่วงหลังทำensembleไปจึงไม่สามารถtestได้ (ผลดังกล่าวคือผลจากfoldเดียว)
- ออกแบบarchitectureค่อนข้างซับซ้อน: อย่างที่กล่าวว่าโปรเจคนี้มี2 modelsและด้วยเวลาที่จำกัดผมจึงtrain 2 modelพร้อมกัน(กับภาพraw) ประเด็นคือ2 modelนี้ทำงานแบบเป็นอิสระกัน หมายความว่ามันมีโอกาสทำงานขัดแย้งกันเอง ซึ่งส่งผลต่อผลลัพท์ ถ้าทำpipelineแบบlandmarkก่อนแล้วค่อยนำผลจากlandmarkไปtrain segmentationผมก็คิดว่าเป็นวิธีที่น่าลอง
- ไม่ได้จดผลลัพท์เป็นระเบียบ: อย่างที่อ่านเนื้อหาข้างบนมาว่าแทบไม่มีตัวเลขmatrixมาก ทั้งๆที่จริงๆงานนี้เปลี่ยนpipelineมาค่อนข้างเยอะ รวมถึงเคยใช้DeepLabสำหรับsegmentationมาก่อน แต่เนื่องจากผมแทบไม่ได้เก็บผลลัพท์ให้ดีในช่วงแรกๆจึงมีผลเพียงแค่ช่วงหลัง
แต่จากที่ว่ามา โปรเจคนี้เป็นโปรเจคนึงที่ผมสนุกมากๆ ไม่ว่ามันจะถูกๆผิดๆบ้าง ลองผิดลองถูกบ้าง ได้ทำงานกัsupervisor(ในทางทัตกรรม)ซึ่งอยู่คนละdomainกับเรา สื่อสารต่างภาษา เรียนรู้วัฒนธรรมที่แตกต่าง งานนี้เป็นงานที่ผมลองใช้AI Agent(Claude Code, Hermes, Pi Agent)ครั้งแรก ศึกษาliterature reviewฝั่งai+การแพทย์ และความรู้อีกมากมายที่คงแชร์ไม่หมดในนี้ ผมรู้สึกคิดถูกมากๆที่ไม่ได้นอนอยู่ห้องในช่วงปิดเทอมแต่เลือกมาหาโอกาศที่นี่
Read the next thing.
New articles, projects, Interactive Labs, and occasional professional or site announcements, primarily in Thai, with no more than one routine email a week.