AI

[Project] 2D Cephologram ai landmark detection and segmentation internship

สรุปโปรเจค 2D Cephologram ai landmark detection and segmentation internship

cover_ceph

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

architecture_trainarchitecture_run



ML Part

Annotation Schema

จากdata 382รูป โดยจะแบ่งงานให้แพทย์annotateซึ่งหากภาพมีวัตถุบังฟันบริเวณที่เราสนใจ(เช่น มีเหล็กบัง) หรือภาพดังกล่าวแพทย์มองว่ามีความเบลอหรือในมุมมองหมอมองยาก จะQuality Rejectออกทำให้เหลือ 278ภาพ โดยannotationจากCVATจะประกอบด้วย

Landmark 10 จุด

  1. Upper_tip
  2. Upper_apex
  3. Labial_midroot
  4. Labial_crest
  5. Palatal_midroot
  6. Palatal_crest
  7. ANS (Anterior Nasal Spine)
  8. PNS (Posterior Nasal Spine)
  9. LB (Labial bone level)
  10. PB (Palatal bone level)

Segmentation 3 class

  1. Upper_incisor
  2. Labial_bone
  3. Palatal_bone

Calibration

แต่ละภาพจะมีเส้น Calibration_30mm สองจุด

mm_per_pixel




หลังจากนั้นเอาทุกภาพมาเฉลี่ยกันจนได้ค่าcallibration (ไม่ได้มีโมเดลที่ใช้detectไม้บรรทัดเนื่องจากออกแบบให้ใช้กับเครื่องเดียว)

Landmark Detection

YOLO

ใช้เพื่อหาbounding boxของmaxilla/incisor region โดยมีขั้นตอน

  1. ส่งภาพrawเข้า YOLO
  2. เลือกbounding boxแรก (หากหาไม่เจอจะใช้ภาพraw)
  3. เพิ่ม padding 10%
  4. clamp ให้อยู่ในขอบภาพ
  5. cropแล้วresizeเป็น512 * 512 (สำหรับHRNet)

HRNet-W32

HRNet เป็น1ในโมเดลที่ทำคะแนนได้อันดับต้นๆในงานประเภทนี้ และยังรักษาhigh-resolution featureตั้งแต่ต้นจนจบ(ตามชื่อ)

hrnet


https://www.mathworks.com/help/vision/ug/hrnetarchitecture.png

Step:

  • เรียก HRNet 5 folds
  • แต่ละโมเดลทำนายheatmap
  • ใช้hard argmax หา coordinate x, y
  • เฉลี่ย coordinate และ confidence ของทั้ง5โมเดล
  • remap จากที่cropมาเป็นสเกลภาพปกติ


xy


Segmentation / nnU-Net

โดยเริ่มต้นจากการแบ่งclasses

  1. background
  2. upper incisor
  3. labial bone
  4. 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ตามที่แพทย์กำหนดมาทั้งหมด

  1. U1-PP angle
    • U1 axis: Upper_tip → Upper_apex
    • Palatal plane: ANS → PNS
    • นำvectorมา dot product → arccosine เพื่อให้ได้มุมองศาและนำไป classification ผลลัพท์ที่คลินิกต้องการอีกที
  2. Bone distances
    โดยทั่วไปทางการแพทย์จะแบ่งเป็น 4 types หลักๆเพียงแค่วัดระยะระหว่าง labial และpalatalเทียบกับฟัน แปลงเป็นmm แล้วclassificationผลลัพท์เช่นเดิม
  3. 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:

  1. เลือกภาพ
  2. preview ด้วย browser object URL
  3. POST /api/v1/analyze
  4. แปลง API landmarks/polygons เป็น Konva objects
  5. วาด overlay บนภาพ
  6. แพทย์แก้ไข landmark หรือ polygon vertex
  7. undo ได้สูงสุด 20 snapshots
  8. autosave annotations ลง localStorage
  9. กด 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.

Double opt-in. Unsubscribe anytime. Your address is never sold or shared for third-party marketing. Privacy