OCR APIOpenThai2.0-OCR-Text · CPU

API REFERENCE

อ่านเอกสารสแกน ได้ JSON ที่ใช้ต่อได้ทันที

ส่งไฟล์ PDF, DOCX หรือภาพ แล้วได้หัวหนังสือที่แยกเป็น field เนื้อความแยกตามประเภท ตารางพร้อม merged cells และ Markdown สำหรับแสดงผล ระบบอื่นนำไปใช้ต่อได้โดยไม่ต้องตัดข้อความเอง

POST/ocr
Base URL
http://<host>:5000
การยืนยันตัวตน
ไม่ต้องใช้ API key
ขนาดไฟล์
ไม่เกิน 100 MB · 30 หน้า
เวลา
0.5–1 วินาที/หน้า

ภาพรวม

ไม่ต้องใช้ key เรียกได้ทันทีโดยไม่ต้องส่ง API key หรือ header พิเศษ จึงควรเปิดให้เข้าถึงเฉพาะภายในเครือข่ายองค์กร
ไม่เก็บเอกสาร ไม่บันทึกไฟล์ ภาพ หรือข้อความที่อ่านได้ เก็บเฉพาะสถิติของ request (เวลา, ขนาดไฟล์, ชนิดไฟล์, จำนวนหน้า, สถานะ)
Synchronous ส่งไฟล์แล้วรอผลใน request เดียว ตั้ง timeout ฝั่ง client อย่างน้อย 60 วินาที (เอกสาร 30 หน้าควรตั้ง 120 วินาที)

POST/ocr

ส่งไฟล์เอกสาร 1 ไฟล์ต่อ request แบบ multipart/form-data

ส่วนประกอบของ request

ส่วนค่าหมายเหตุ
MethodPOST
URLhttp://<host>:5000/ocr
Header Content-Typemultipart/form-data; boundary=... HTTP library ส่วนใหญ่ตั้งให้อัตโนมัติเมื่อแนบไฟล์ ไม่ต้องกำหนดเอง
Authorizationไม่ต้องส่ง

Form fields

ชื่อ fieldชนิดจำเป็นคำอธิบาย
filebinary (ไฟล์)ใช่ ไฟล์เอกสาร ขนาดไม่เกิน 100 MB ชื่อไฟล์ไม่มีผลต่อการประมวลผลและไม่ถูกบันทึก part นี้ต้องระบุ Content-Type ด้วย (ดูตารางด้านล่าง)

ชนิดไฟล์ที่รองรับ

ชนิดไฟล์Content-Type ของ partวิธีที่ระบบตรวจชนิดไฟล์การประมวลผล
PDFค่าใดก็ได้ (แนะนำ application/pdf)จากเนื้อไฟล์ (ขึ้นต้นด้วย %PDF-) แปลงแต่ละหน้าเป็นภาพ 200 dpi แล้ว OCR ทุกหน้า สูงสุด 30 หน้า
DOCXค่าใดก็ได้จากเนื้อไฟล์ (ไฟล์ zip) OCR เฉพาะภาพที่แทรกในเนื้อเอกสาร ตามลำดับที่ปรากฏ โดยแต่ละภาพนับเป็น 1 หน้า ข้อความที่พิมพ์ใน Word ไม่ถูก OCR เพราะอ่านจากไฟล์ได้โดยตรงอยู่แล้ว
ภาพ (PNG, JPEG, TIFF, BMP, WebP)ต้องเป็น image/*จาก Content-Type ของ part OCR 1 หน้า และหมุนภาพที่เอียงหรือกลับหัวให้ตรงอัตโนมัติ

ถ้าส่งไฟล์ภาพด้วย Content-Type application/octet-stream จะได้ 415 ให้ระบุ image/png, image/jpeg หรือชนิดที่ตรงกับไฟล์

การนำผลไปใช้

Response มีข้อมูลหลายระดับ ตั้งแต่หัวเอกสารที่แยกเป็น field ไปจนถึงพิกัดของแต่ละคำ ให้เลือกใช้ส่วนที่ตรงกับงาน ไม่จำเป็นต้องใช้ทุกส่วน

ต้องการใช้ fieldวิธีใช้
ข้อมูลหัวหนังสือ (ที่, วันที่, เรื่อง, เรียน, ผู้ลงนาม)documents 1 รายการต่อ 1 เอกสารในไฟล์ แต่ละรายการบอกหน้าที่เอกสารเริ่ม และมี key ตาม fields
เนื้อความของหนังสือpages[].structure.blocks เลือกเฉพาะ block ที่ type เป็น paragraph และ list_item (ไม่รวมหัวเอกสาร ตรารับ ลายเซ็น และเลขหน้า)
ตาราง เช่น บัญชีรายชื่อแนบท้ายpages[].structure.blocks เลือก block ที่ type เป็น table แล้วใช้ rows (array 2 มิติ) หรือใช้ cells ถ้าต้องการโครงสร้างการ merge
แสดงผลให้คนอ่านmarkdown Markdown ของทั้งไฟล์ ตารางเป็น HTML <table> เพื่อรองรับ merged cells
ค้นหาข้อความ หรือทำ full-text indexpages[].text ข้อความดิบของทั้งหน้าเรียงตามบรรทัด ไม่มีโครงสร้าง
ไฮไลต์ตำแหน่งบนภาพ หรือตรวจความมั่นใจpages[].lines แต่ละบรรทัดมีกรอบ (box) และ confidence ส่วน words ใช้ระบุตำแหน่งระดับคำ

ขั้นตอนที่แนะนำ

  1. ตรวจ HTTP status ถ้าไม่ใช่ 200 ให้อ่านสาเหตุจาก detail (ดู Error)
  2. ตรวจว่าประมวลผลครบทุกหน้า โดยเทียบ total_pages กับจำนวนรายการใน pages ถ้าไม่เท่ากัน แสดงว่าไฟล์เกิน 30 หน้าและหน้าที่เกินถูกข้าม
  3. วนอ่าน pages แล้วข้ามหน้าที่มี error หน้าที่อ่านได้จะมี structure เสมอ
  4. ใช้ documents เป็นตัวแบ่งเอกสาร: PDF หนึ่งไฟล์มักรวมหลายเอกสาร เช่น บันทึกข้อความ + คำสั่ง + บัญชีแนบท้าย เนื้อหาของแต่ละเอกสารคือหน้าตั้งแต่หน้าที่เอกสารนั้นเริ่ม จนถึงก่อนหน้าที่เอกสารถัดไปเริ่ม
  5. ถ้าไม่ต้องการภาพ ให้ทิ้ง pages[].image ทันทีหลังรับ response ภาพนี้มีขนาด 200–400 KB ต่อหน้า

ค่าทั้งหมดเป็นข้อความตามที่ OCR อ่านได้ วรรณยุกต์อาจตกหรือเกิน และเว้นวรรคอาจหายบ้าง ก่อนนำค่าไปเทียบตรงตัว (เช่น ค้นฐานข้อมูลด้วย ref_no) ควร normalize ก่อน หรือให้คนตรวจทาน ใช้ confidence ใน lines ช่วยคัดบรรทัดที่ควรตรวจ

Response ระดับไฟล์

สำเร็จได้ HTTP 200 body เป็น JSON object ซ้อนกัน 3 ชั้น: ไฟล์ → หน้า → โครงสร้าง

ระดับไฟล์

  • kind
  • total_pages
  • documents
  • markdown

ต่อหน้า

  • name
  • text · lines · dropped
  • rotation · timing
  • image

structure (ใช้ส่วนนี้เป็นหลัก)

  • fields
  • blocks
  • markdown

key ระดับไฟล์:

fieldชนิดคำอธิบาย
kindstringชนิดไฟล์ที่ระบบตรวจได้: "pdf", "docx" หรือ "image"
total_pagesintegerจำนวนหน้าทั้งหมดในไฟล์ (DOCX คือจำนวนภาพ) ถ้ามากกว่าจำนวนรายการใน pages แสดงว่ามีหน้าที่ถูกข้ามเพราะเกิน 30 หน้า
pagesarray of objectผลของแต่ละหน้าตามลำดับ ดู pages[]
documentsarray of object1 รายการต่อทุกหน้าที่เป็นหน้าแรกของเอกสาร ประกอบด้วย page (string ชื่อหน้า เช่น "หน้า 2") และ key ทั้งหมดของ fields ในหน้านั้น เป็น [] ถ้าไม่พบหัวเอกสารเลย
markdownstringMarkdown ของทั้งไฟล์ แต่ละหน้าคั่นด้วย comment <!-- หน้า n --> ไม่รวมเลขหน้าและข้อความบอกต่อหน้า

ตัวอย่าง response

ตัวอย่างจาก PDF 3 หน้า: หน้า 1 เป็นบันทึกข้อความ หน้า 2 เป็นบัญชีแนบท้ายที่มีตาราง และหน้า 3 เป็นหน้าที่อ่านไม่ได้ (ใส่ไว้เพื่อให้เห็นรูปแบบ error ปกติจะเกิดกับภาพใน DOCX) ข้อมูลในตัวอย่างสมมติขึ้น และตัดบางส่วนให้สั้นลง: image ตัดเหลือ ... และ lines แสดงเพียงบรรทัดเดียว

200 OK · application/json
{
  "kind": "pdf",
  "total_pages": 3,
  "documents": [
    {
      "page": "หน้า 1",
      "doc_type": "บันทึกข้อความ",
      "department": "องค์การบริหารส่วนจังหวัดตัวอย่าง กองการเจ้าหน้าที่",
      "ref_no": "ตย ๕๑๐๑๑/๑๒๓",
      "date": "๕ พฤศจิกายน ๒๕๖๙",
      "subject": "ขออนุมัติแต่งตั้งคณะทำงาน",
      "to": "นายกองค์การบริหารส่วนจังหวัดตัวอย่าง",
      "signers": [
        { "name": "นายสมชาย ใจดี", "position": "ผู้อำนวยการกองการเจ้าหน้าที่" }
      ]
    }
  ],
  "markdown": "<!-- หน้า 1 -->\n\n# บันทึกข้อความ\n\n**ส่วนราชการ** องค์การบริหารส่วนจังหวัดตัวอย่าง ...",
  "pages": [
    {
      "name": "หน้า 1",
      "image": "data:image/jpeg;base64,...",
      "text": "บันทึกข้อความ\nส่วนราชการ องค์การบริหารส่วนจังหวัดตัวอย่าง กองการเจ้าหน้าที่\n...",
      "lines": [
        {
          "text": "บันทึกข้อความ",
          "confidence": 0.9871,
          "row": 0,
          "box": [[612.0, 180.5], [1050.2, 180.5], [1050.2, 248.0], [612.0, 248.0]],
          "words": [
            { "text": "บันทึกข้อความ", "confidence": 0.9871,
              "box": [[612.0, 180.5], [1050.2, 180.5], [1050.2, 248.0], [612.0, 248.0]] }
          ]
        }
      ],
      "dropped": [
        { "text": "ส", "confidence": 0.41, "row": 21,
          "box": [[880.0, 1702.0], [1010.0, 1702.0], [1010.0, 1790.0], [880.0, 1790.0]],
          "reason": "too_short" }
      ],
      "rotation": 0,
      "text_angle": 0.12,
      "timing": { "det_ms": 142.3, "rec_ms": 268.9, "n_lines": 24 },
      "structure": {
        "fields": {
          "doc_type": "บันทึกข้อความ",
          "department": "องค์การบริหารส่วนจังหวัดตัวอย่าง กองการเจ้าหน้าที่",
          "ref_no": "ตย ๕๑๐๑๑/๑๒๓",
          "date": "๕ พฤศจิกายน ๒๕๖๙",
          "subject": "ขออนุมัติแต่งตั้งคณะทำงาน",
          "to": "นายกองค์การบริหารส่วนจังหวัดตัวอย่าง",
          "signers": [
            { "name": "นายสมชาย ใจดี", "position": "ผู้อำนวยการกองการเจ้าหน้าที่" }
          ]
        },
        "blocks": [
          { "type": "stamp", "text": "เลขรับ: 1343\nวันที่: 6 พ.ย. 69" },
          { "type": "title", "text": "บันทึกข้อความ" },
          { "type": "field", "key": "department", "text": "ส่วนราชการ องค์การบริหารส่วนจังหวัดตัวอย่าง กองการเจ้าหน้าที่" },
          { "type": "field", "key": "ref_no", "text": "ที่ ตย ๕๑๐๑๑/๑๒๓ วันที่ ๕ พฤศจิกายน ๒๕๖๙" },
          { "type": "field", "key": "subject", "text": "เรื่อง ขออนุมัติแต่งตั้งคณะทำงาน" },
          { "type": "field", "key": "to", "text": "เรียน นายกองค์การบริหารส่วนจังหวัดตัวอย่าง" },
          { "type": "paragraph", "text": "ด้วยกองการเจ้าหน้าที่มีความจำเป็นต้องแต่งตั้งคณะทำงาน\nเพื่อดำเนินการปรับปรุงทะเบียนประวัติ ดังนี้" },
          { "type": "list_item", "text": "๑) นายสมศักดิ์ ตัวอย่าง ประธานคณะทำงาน" },
          { "type": "list_item", "text": "๒) นางสาวสมหญิง ตัวอย่าง คณะทำงาน" },
          { "type": "paragraph", "text": "จึงเรียนมาเพื่อโปรดพิจารณาอนุมัติ" },
          { "type": "signature", "text": "(นายสมชาย ใจดี)", "name": "นายสมชาย ใจดี", "position": "ผู้อำนวยการกองการเจ้าหน้าที่" },
          { "type": "note", "text": "- อนุมัติ" }
        ],
        "markdown": "# บันทึกข้อความ\n\n..."
      }
    },
    {
      "name": "หน้า 2",
      "image": "data:image/jpeg;base64,...",
      "text": "บัญชีรายชื่อคณะทำงาน\nที่ ชื่อ - สกุล ตำแหน่ง\n...",
      "lines": [],
      "dropped": [],
      "rotation": 0,
      "text_angle": -0.05,
      "timing": { "det_ms": 120.7, "rec_ms": 190.4, "n_lines": 15 },
      "structure": {
        "fields": {},
        "blocks": [
          { "type": "caption", "text": "บัญชีรายชื่อคณะทำงาน" },
          {
            "type": "table",
            "kind": "ruled",
            "n_rows": 4,
            "n_cols": 4,
            "rows": [
              ["ที่", "ชื่อ - สกุล", "ตำแหน่ง", ""],
              ["", "", "ประเภท", "ระดับ"],
              ["๑", "นายสมศักดิ์ ตัวอย่าง", "อำนวยการ", "ต้น"],
              ["๒", "นางสาวสมหญิง ตัวอย่าง", "วิชาการ", "ชำนาญการ"]
            ],
            "cells": [
              { "row": 0, "col": 0, "rowspan": 2, "colspan": 1, "text": "ที่" },
              { "row": 0, "col": 1, "rowspan": 2, "colspan": 1, "text": "ชื่อ - สกุล" },
              { "row": 0, "col": 2, "rowspan": 1, "colspan": 2, "text": "ตำแหน่ง" },
              { "row": 1, "col": 2, "rowspan": 1, "colspan": 1, "text": "ประเภท" },
              { "row": 1, "col": 3, "rowspan": 1, "colspan": 1, "text": "ระดับ" },
              { "row": 2, "col": 0, "rowspan": 1, "colspan": 1, "text": "๑" },
              { "row": 2, "col": 1, "rowspan": 1, "colspan": 1, "text": "นายสมศักดิ์ ตัวอย่าง" },
              { "row": 2, "col": 2, "rowspan": 1, "colspan": 1, "text": "อำนวยการ" },
              { "row": 2, "col": 3, "rowspan": 1, "colspan": 1, "text": "ต้น" },
              { "row": 3, "col": 0, "rowspan": 1, "colspan": 1, "text": "๒" },
              { "row": 3, "col": 1, "rowspan": 1, "colspan": 1, "text": "นางสาวสมหญิง ตัวอย่าง" },
              { "row": 3, "col": 2, "rowspan": 1, "colspan": 1, "text": "วิชาการ" },
              { "row": 3, "col": 3, "rowspan": 1, "colspan": 1, "text": "ชำนาญการ" }
            ],
            "box": [[150.0, 420.0], [2200.0, 420.0], [2200.0, 1100.0], [150.0, 1100.0]]
          },
          { "type": "page_number", "text": "-๒-" }
        ],
        "markdown": "**บัญชีรายชื่อคณะทำงาน**\n\n<table>...</table>"
      }
    },
    {
      "name": "หน้า 3",
      "error": "ถอดรหัสภาพไม่ได้ (เช่น EMF/WMF ไม่รองรับ)"
    }
  ]
}

จุดที่ควรสังเกตในตัวอย่าง:

  • ค่าใน fields ไม่มีคำนำหน้า เช่น "subject": "ขออนุมัติ…" แต่ text ของ block field มีคำนำหน้า เช่น "เรื่อง ขออนุมัติ…"
  • paragraph แรกมี \n ตรงจุดที่เอกสารขึ้นบรรทัดใหม่
  • หน้า 2 ไม่ได้ขึ้นต้นเอกสารใหม่ จึงมี fields เป็น {} และไม่อยู่ใน documents
  • ในตาราง "ที่" และ "ชื่อ - สกุล" คลุม 2 แถว (rowspan: 2) ส่วน "ตำแหน่ง" คลุม 2 คอลัมน์ (colspan: 2) ใน rows ช่องที่ถูกคลุมจึงเป็น ""
  • หน้า 3 มีเพียง name และ error

pages[]: ผลแต่ละหน้า

แต่ละหน้ามี 2 แบบ: หน้าที่อ่านได้มี field ครบตามตาราง ส่วนหน้าที่อ่านไม่ได้มีเพียง name และ error ใช้การมีอยู่ของ structure หรือ error แยกสองกรณีนี้

fieldชนิดคำอธิบาย
namestringชื่อหน้า: PDF เป็น "หน้า 1", DOCX เป็น "ภาพ 1 (image1.png)", ไฟล์ภาพเป็น "ภาพ"
errorstringมีเฉพาะหน้าที่อ่านไม่ได้ เช่น ภาพใน DOCX เป็น EMF/WMF หรือภาพใหญ่เกิน หน้าแบบนี้ไม่มี field อื่น และ request ยังได้ 200
structureobjectผลการแยกโครงสร้างของหน้า ซึ่งเป็นส่วนหลักที่ควรใช้ ดู structure
textstringข้อความทั้งหน้าเรียงตามลำดับอ่าน แต่ละบรรทัดคั่นด้วย \n ไม่มีการแยกโครงสร้าง
linesarray of objectบรรทัดที่อ่านได้พร้อมตำแหน่งและความมั่นใจ ดู lines
droppedarray of objectบริเวณที่ตรวจพบแต่ถูกคัดออกจากผล ดู dropped
rotationintegerองศาที่ระบบหมุนภาพให้ตรงก่อน OCR: 0, 90, 180 หรือ 270
text_anglenumberมุมเอียงของข้อความบนภาพต้นฉบับ (องศา)
timingobjectเวลาที่ใช้ประมวลผลหน้านี้ ดู timing
imagestring (data URL)ภาพหน้าที่ใช้ OCR ในรูป data:image/jpeg;base64,... พิกัด box ทุกตัวในหน้านี้อ้างอิงภาพนี้ (สำหรับ PDF คือภาพที่ render ที่ 200 dpi)

structure

fieldชนิดคำอธิบาย
fieldsobjectหัวเอกสารที่แยกเป็น key แล้ว มีค่าเฉพาะหน้าที่เป็นหน้าแรกของเอกสาร หน้าอื่นเป็น {} ดู fields
blocksarray of objectเนื้อหาทั้งหน้า (รวมตาราง) แยกตามประเภท เรียงตามลำดับการอ่าน ดู blocks
markdownstringMarkdown ของหน้านี้ที่สร้างจาก blocks

blocks: เนื้อหาตามประเภท

ทุก block มี type ทุก block ยกเว้นตารางมี text และบาง type มี key เพิ่มตามตาราง การขึ้นบรรทัดใหม่ในเอกสารเก็บเป็น \n ระบบไม่ต่อบรรทัดให้ เพราะเอกสารราชการตัดบรรทัดทั้งที่เว้นวรรคและกลางคำ ฝั่งผู้ใช้เลือกแทน \n ด้วย "" หรือ " " ตามงานได้

paragraphlist_itemtable headingcaption titlefieldsignature stampnotepage_numbercontinuation
เนื้อหาหัวเอกสารและผู้ลงนามส่วนประกอบ ไม่ใช่เนื้อหา
typeคืออะไรkey เพิ่มเติม
titleชื่อเอกสาร เช่น บันทึกข้อความ, คำสั่ง…, ประกาศ…
fieldบรรทัดหัวเอกสาร: ส่วนราชการ, ที่…วันที่, เรื่อง, เรียน, อ้างถึง, สิ่งที่ส่งมาด้วย, สั่ง ณ วันที่ โดย text รวมคำนำหน้า (เช่น "เรื่อง") ไว้ด้วย key (string): ชื่อ key เดียวกับใน fields เช่น "subject"
headingหัวข้อในเนื้อหา เช่น "๒. คณะทำงาน… ประกอบด้วย", "มีหน้าที่"
captionชื่อตารางที่อยู่เหนือตาราง เช่น "บัญชีรายละเอียด…"
paragraphเนื้อหาหลักของเอกสาร คือข้อความเนื้อความที่ตามหลังหัวเอกสารหรือหัวข้อ
list_itemข้อย่อยที่ขึ้นต้นด้วยเลขข้อหรือสัญลักษณ์ เช่น ๑), ๒.๑, (๓), - โดย text รวมเลขข้อไว้ด้วย
tableตารางดู ตาราง (ไม่มี text)
signatureผู้ลงนาม โดยรวมบรรทัดตำแหน่งที่อยู่ใต้ชื่อไว้แล้ว text คือบรรทัดชื่อในวงเล็บตามต้นฉบับ name (string): ชื่อที่ไม่มีวงเล็บ
position (string): ตำแหน่ง ถ้าไม่พบจะเป็นค่าว่าง
stampตรารับหนังสือเหนือชื่อเอกสาร (เลขรับ, วันที่รับ, เวลารับ)
noteข้อความเกษียณหรือสั่งการท้ายบันทึกข้อความ (หลังลายเซ็น)
page_numberเลขหน้า เช่น "-๒-"
continuationข้อความบอกต่อหน้าถัดไป เช่น "/๔. คณะทำงาน.."

ลำดับ block ทั่วไปของบันทึกข้อความคือ stamp → title → field (ส่วนราชการ, ที่/วันที่, เรื่อง, เรียน) → paragraph / list_item → signature → note

fields: หัวเอกสาร

มีค่าเฉพาะหน้าที่พบชื่อเอกสารที่ส่วนบนของหน้า หน้าอื่นเป็น {} key ที่หาไม่พบจะไม่อยู่ใน object (ไม่ได้เป็น null) ให้ตรวจการมีอยู่ของ key ก่อนใช้ ค่าทุกตัวเป็นข้อความตามที่ OCR อ่านได้ เช่น วันที่ยังเป็นเลขไทยและปี พ.ศ. ระบบไม่แปลงรูปแบบให้ ค่าจะไม่มีคำนำหน้า เช่น "เรื่อง" หรือ "เรียน" ซึ่งต่างจาก text ของ block field

keyชนิดมาจากตัวอย่างค่า
doc_typestringชื่อเอกสารบันทึกข้อความ · คำสั่งองค์การบริหารส่วนจังหวัดตัวอย่าง
departmentstringส่วนราชการองค์การบริหารส่วนจังหวัดตัวอย่าง กองการเจ้าหน้าที่
ref_nostringที่ตย ๕๑๐๑๑/๑๒๓
datestringวันที่ (บรรทัดเดียวกับ "ที่")๕ พฤศจิกายน ๒๕๖๙
subjectstringเรื่อง (รวมบรรทัดที่ขึ้นใหม่แล้ว)ขออนุมัติแต่งตั้งคณะทำงาน
tostringเรียนหัวหน้าส่วนราชการในสังกัดทุกส่วนราชการ
referencestringอ้างถึงหนังสือ… ลงวันที่…
enclosuresstringสิ่งที่ส่งมาด้วยสำเนาคำสั่ง… จำนวน ๑ ฉบับ
signed_datestringสั่ง ณ วันที่ / ประกาศ ณ วันที่๕ พฤศจิกายน พ.ศ. ๒๕๖๙
signersarray of objectผู้ลงนามในหน้านั้น แต่ละรายการมี name (string) และ position (string)

ตาราง

block ที่มี type เป็น "table" มี key ดังนี้

keyชนิดคำอธิบาย
kindstring"ruled" คือตารางที่มีเส้นตาราง "list" คือรายชื่อที่จัดเป็นคอลัมน์แต่ไม่มีเส้น (เช่น ชื่อ | ตำแหน่ง | หน้าที่ ในคำสั่งแต่งตั้ง)
n_rowsintegerจำนวนแถว (นับรวมแถวหัวตาราง)
n_colsintegerจำนวนคอลัมน์
rowsarray of array of stringข้อความของตารางในรูป 2 มิติ ขนาด n_rows × n_cols เซลล์ที่ merge กันจะมีข้อความอยู่ที่ช่องบนซ้าย ช่องที่ถูกคลุมเป็น "" ข้อความหลายบรรทัดในเซลล์เดียวกันคั่นด้วยช่องว่าง เหมาะกับการแปลงเป็น CSV หรือนำเข้า spreadsheet
cellsarray of objectรายการเซลล์จริง ใช้เมื่อต้องการโครงสร้างการ merge ที่แน่นอน แต่ละเซลล์มี row, col (integer, เริ่มที่ 0), rowspan, colspan (integer, อย่างน้อย 1) และ text (string)
boxarray of [x, y]กรอบของตารางบนภาพ image ของหน้า เป็น 4 จุด

ตัวอย่าง: ตารางที่มี merged cells

ที่ชื่อ - สกุลตำแหน่ง
ประเภทระดับ
๑นายสมศักดิ์ ตัวอย่างอำนวยการต้น
"rows": [
  ["ที่", "ชื่อ - สกุล", "ตำแหน่ง", ""],
  ["", "", "ประเภท", "ระดับ"],
  ["๑", "นายสมศักดิ์ ตัวอย่าง", "อำนวยการ", "ต้น"]
],
"cells": [
  { "row": 0, "col": 0, "rowspan": 2, "colspan": 1, "text": "ที่" },
  { "row": 0, "col": 2, "rowspan": 1, "colspan": 2, "text": "ตำแหน่ง" },
  …
]

หัวตารางหลายชั้น

ตัวอย่างเช่น หัวตารางที่มี "อัตราเงินเดือนก่อนเลื่อน" คลุม 3 คอลัมน์ และแถวล่างแยกเป็น "ประเภท", "ขั้น", "เงินเดือน" ใน cells จะมีเซลล์ row 0, col 5, colspan 3 สำหรับหัวชั้นบน และเซลล์ row 1 ที่คอลัมน์ 5, 6, 7 สำหรับหัวชั้นล่าง ส่วน rows[0] จะเป็น "อัตราเงินเดือนก่อนเลื่อน", "", "" ที่คอลัมน์ 5–7 ถ้าต้องการชื่อคอลัมน์ชั้นเดียว เช่น "อัตราเงินเดือนก่อนเลื่อน / ขั้น" ให้ระบบปลายทางรวมเองจาก cells

ตารางที่ต่อกันหลายหน้าจะได้เป็นหลายตาราง หน้าละหนึ่งตาราง

lines, words, dropped, timing

ข้อมูลระดับบรรทัดและคำจากโมเดล OCR โดยตรง ใช้สำหรับไฮไลต์ตำแหน่งบนภาพหรือตรวจคุณภาพ พิกัดทุกตัวหน่วยเป็นพิกเซลของ image ในหน้านั้น box คือ 4 จุด [[x, y], …] เรียงจากมุมบนซ้าย บนขวา ล่างขวา ล่างซ้าย

lines[]

fieldชนิดคำอธิบาย
textstringข้อความในบรรทัด
confidencenumber 0–1ความมั่นใจของโมเดล บรรทัดที่ต่ำกว่า 0.9 ควรตรวจทาน
rowintegerลำดับแถวบนหน้า ส่วนที่อยู่ในแนวเดียวกัน (เช่น "ที่…" กับ "วันที่…") จะได้ row เดียวกัน
boxarray of [x, y]กรอบของบรรทัด
wordsarray of objectคำในบรรทัด แต่ละคำมี text, confidence และ box

dropped[]

บริเวณที่ตรวจพบว่าเป็นข้อความแต่ถูกคัดออก ส่วนใหญ่คือตราประทับ ลายเซ็น หรือลายมือ มี text, confidence, row, box เหมือน lines และมี reason เพิ่ม

reasonความหมาย
low_confidenceความมั่นใจต่ำกว่า 0.8
too_shortสั้นกว่า 2 ตัวอักษร
invalid_thaiลำดับอักษรไทยที่เป็นไปไม่ได้ เช่น สระหรือวรรณยุกต์ลอย
emptyอ่านแล้วไม่ได้ข้อความ

timing

fieldชนิดคำอธิบาย
det_msnumberเวลาหาตำแหน่งบรรทัด (มิลลิวินาที)
rec_msnumberเวลาอ่านข้อความ (มิลลิวินาที)
n_linesintegerจำนวนบรรทัดที่ส่งให้โมเดลอ่าน (รวมบรรทัดที่ถูกคัดออก)

Error

ทุก error ตอบกลับเป็น JSON object ที่มี key detail (string ภาษาไทยบอกสาเหตุ) ยกเว้น 422 ซึ่ง detail เป็น array รายละเอียดตามรูปแบบ validation ของ FastAPI

415 · application/json
{ "detail": "รองรับเฉพาะไฟล์ภาพ, PDF และ DOCX" }
422 · application/json
{ "detail": [ { "type": "missing", "loc": ["body", "file"], "msg": "Field required", "input": null } ] }
Statusเมื่อไรควรทำอย่างไร
400อ่านไฟล์ไม่ได้: PDF/DOCX/ภาพเสีย, PDF ติดรหัสผ่าน, DOCX ไม่มีภาพในเนื้อเอกสารไม่ต้องส่งซ้ำ ให้แจ้งผู้ใช้ตรวจไฟล์
413ไฟล์ใหญ่เกิน 100 MBแบ่งไฟล์หรือลดความละเอียดก่อนส่ง
415ไม่ใช่ PDF หรือ DOCX และ Content-Type ไม่ใช่ image/*ตรวจชนิดไฟล์และ Content-Type ของ part
422ไม่ได้ส่ง field file หรือชื่อ field ไม่ตรงแก้ request ให้ส่งไฟล์ใน field file
500ข้อผิดพลาดภายใน serviceส่งซ้ำได้ ถ้ายังเกิดซ้ำให้แจ้งผู้ดูแล

ใน DOCX ถ้ามีบางภาพที่อ่านไม่ได้ (เช่น EMF/WMF) request ยังสำเร็จด้วย 200 โดยหน้านั้นใน pages จะมี error แทนผลลัพธ์

GET/health

ใช้ตรวจว่า service พร้อมรับงาน (โหลดโมเดลเสร็จแล้ว) เหมาะกับ health check ของ load balancer หรือ container ไม่ต้องส่ง parameter

fieldชนิดคำอธิบาย
statusstring"ok" เมื่อพร้อมใช้งาน
backendstringengine ที่ใช้รันโมเดล: "openvino" หรือ "onnxruntime"
200 OK · application/json
{ "status": "ok", "backend": "openvino" }

ข้อจำกัด

  • ไฟล์ไม่เกิน 100 MB และประมวลผลสูงสุด 30 หน้า ต่อ request หน้าที่เกินจะถูกข้าม
  • อ่านเอกสารพิมพ์ภาษาไทยและอังกฤษได้ดี แต่ลายมือ ตัวอักษรตกแต่ง และภาพถ่ายทั่วไปจะอ่านไม่ได้หรือไม่แม่น
  • OCR อาจอ่านวรรณยุกต์ตกหรือเกิน (เช่น ที่ → ที) และอาจตกเว้นวรรค
  • การแยกโครงสร้าง (fields, blocks, ตาราง) ปรับจากหนังสือราชการรูปแบบ อบจ. เอกสารรูปแบบอื่นจึงอาจได้ paragraph มากกว่า
  • ผลของเอกสารหลายหน้าแยกตามหน้า ตารางแนบท้ายที่ต่อหลายหน้าจึงได้เป็นหลายตาราง