# Đọc ảnh hiện trường, biểu mẫu viết tay và video của khách bằng vision model: hướng dẫn từng bước

> Ảnh chụp nghiêng, chữ viết tay có dấu và clip quay rung từ điện thoại mới là dữ liệu thật ở công trường, và pipeline của bạn chỉ dùng được khi xử lý được chúng.

Bản gốc: https://fdetimes.net/vi/bach-khoa/vision-model-cho-anh-va-video-cua-khach/

Người dùng ở hiện trường không chụp ảnh theo kiểu tài liệu mẫu. Kỹ thuật viên chụp phiếu kiểm tra từ xa, điện thoại xoay ngang, chữ viết tay có dấu tiếng Việt, kèm thêm một clip 3 phút quay băng chuyền mà chuyện đáng chú ý chỉ xảy ra trong nửa giây.

Demo chạy trên ảnh sạch thì đẹp, còn ảnh thật của khách mới cho biết pipeline có dùng được hay không.

Với một FDE, đây là việc rất hay gặp: khách đưa một thư mục ảnh, PDF scan và video rồi hỏi "AI đọc được không?". Bài này đi qua cách dựng một pipeline nhỏ đọc ba loại đầu vào đó, kiểm tra kết quả ở từng bước và biết chỗ nào model hay sai.

## Bạn sẽ dựng gì, và cần chuẩn bị gì?

Thử hình dung khách là một công ty bảo trì nhà máy. Họ gửi ba thứ: ảnh một máy bơm hỏng, ảnh biểu mẫu kiểm tra viết tay, và video điện thoại quay dây chuyền. Đầu ra mong muốn là JSON có cấu trúc để kỹ sư của khách duyệt lại, chứ không phải một đoạn văn mô tả chung chung.

Nền tảng ở đây là Vision Language Model (VLM). Hugging Face định nghĩa đây là các model hiểu và xử lý được cả hình ảnh lẫn văn bản. Bạn cần một API key cho model đọc ảnh (bài dùng tài liệu của OpenAI làm ví dụ) và một model đọc video (bài dùng Gemini), cùng khoảng 20 mẫu thật của khách.

Chuẩn bị quan trọng nhất không nằm ở code mà là **bộ đáp án**. Với mỗi biểu mẫu, hãy tự gõ lại nội dung đúng. Với mỗi video, ghi lại mốc thời gian của sự kiện cần bắt. Thiếu bộ này thì bạn không có cách nào biết model đọc đúng hay sai.

## Bước 1: lỗi hay nằm ở ảnh đầu vào

Tài liệu vision của OpenAI ghi rõ model có thể hiểu sai chữ và ảnh bị xoay hoặc lộn ngược. Ảnh chụp từ điện thoại ở hiện trường thường bị như vậy. Vì thế việc đầu tiên là chuẩn hóa chiều ảnh trước khi gửi, bằng bất kỳ thư viện xử lý ảnh nào bạn quen dùng.

Việc thứ hai là xử lý chữ nhỏ. Với biểu mẫu chụp từ xa, OpenAI khuyên phóng to phần chữ trong ảnh để model đọc dễ hơn. Trên thực tế, bạn có thể cắt riêng vùng có chữ viết tay rồi phóng to vùng đó, thay vì gửi cả tấm ảnh mà chữ chỉ chiếm một góc nhỏ.

Việc thứ ba dễ bị quên nhất: kiểm tra kích thước. Mỗi request có giới hạn dung lượng khi gửi nhiều ảnh, và tài liệu nói ảnh vượt giới hạn 30,000 patch sau khi xử lý sẽ **bị từ chối, không được tự thu nhỏ**. Nếu khách tải lên ảnh rất lớn từ máy ảnh chuyên dụng, pipeline phải tự thu nhỏ ảnh trước khi gửi.

**Kiểm tra sau bước 1:** mở 10 ảnh đã xử lý và tự đọc bằng mắt. Nếu bạn phải nghiêng đầu hoặc nheo mắt mới đọc được thì model cũng sẽ đọc khó.

## Bước 2: chọn cách gửi ảnh và thử tham số detail

OpenAI hỗ trợ ba cách đưa ảnh vào: URL, Base64 data URL, hoặc file ID. Nếu ảnh của khách nằm trong mạng nội bộ không truy cập được từ ngoài thì URL không dùng được, và Base64 thường là lựa chọn đơn giản nhất. Cấu trúc request dưới đây đã được **giản lược**; tên trường chính xác cần đối chiếu với tài liệu API bạn đang dùng:

```json
{
"role": "user",
"content": [
{ "type": "text", "text": "Đọc biểu mẫu kiểm tra này và trả về JSON." },
{ "type": "image", "image_url": "data:image/jpeg;base64,<...>", "detail": "high" }
]
}
```

Tham số `detail` quyết định cách ảnh được tiền xử lý. Mức `low` cho kết quả thô, và tài liệu nói rõ `low` **không phải lúc nào cũng tốn ít token hơn** `high`. Vì vậy đừng mặc định chọn `low` để tiết kiệm. Hãy gửi cùng một ảnh ở hai mức, rồi ghi lại số token và số trường đọc đúng của mỗi lần.

## Bước 3: đọc biểu mẫu tay mà không tin hết vào model

Tài liệu của OpenAI liệt kê vài giới hạn đã biết: model chỉ đếm số vật thể ở mức xấp xỉ, xác định vị trí trong ảnh còn yếu, và xử lý chữ không phải Latin chưa tốt. Tiếng Việt dùng chữ Latin nhưng có nhiều dấu, nên bạn cần kiểm thử riêng phần dấu thay vì cho rằng model sẽ đọc đúng.

Chữ "máy bơm hỏng" đọc thành "may bom hong" thì có thể vẫn hiểu được, nhưng với tên người hoặc tên linh kiện thì sai dấu là sai thông tin.

Từ các giới hạn đó, prompt nên cho model một cách để báo là nó không chắc:

```text
Đọc biểu mẫu kiểm tra trong ảnh. Trả về JSON với các trường:
ma_thiet_bi, ngay_kiem_tra, nguoi_kiem_tra, tinh_trang, ghi_chu.
Nếu một trường không đọc rõ, ghi "KHONG_DOC_DUOC" thay vì đoán.
Giữ nguyên dấu tiếng Việt như trong ảnh.
```

Với ảnh máy bơm hỏng, đừng giao cho model những việc như "đếm có bao nhiêu bu lông bị gỉ" hoặc "chỉ chính xác vết nứt nằm ở tọa độ nào". Đó chính là phần đếm và định vị mà tài liệu cảnh báo là yếu.

Hãy hỏi những câu mang tính mô tả, ví dụ có dấu hiệu rò rỉ hay không, và để con người xác nhận các con số.

**Kiểm tra sau bước 3:** so JSON với bộ đáp án theo từng trường, không chấm theo từng ảnh. Bạn sẽ thấy ngay trường nào hay sai, thường là tên riêng có dấu và chữ số viết tay.

## Bước 4: video bị lấy mẫu 1 khung hình mỗi giây

Gemini mặc định lấy mẫu video ở mức 1 khung hình mỗi giây. Với clip băng chuyền, nếu một sản phẩm rơi ra trong nửa giây thì model có thể không thấy khung hình đó.

Bạn có thể chỉnh tần suất lấy mẫu bằng cách truyền tham số `fps` trong object cấu hình `processing`, đồng thời giới hạn đoạn clip cần xem. Đoạn dưới đây cũng đã được **giản lược** để minh họa ý tưởng:

```json
{
"processing": { "fps": 5 }
}
```

Bạn cũng có thể hỏi về một thời điểm cụ thể bằng mốc dạng `MM:SS`:

```text
Tại 02:14, sản phẩm trên băng chuyền có rơi ra ngoài không?
Mô tả trạng thái băng chuyền từ 02:10 đến 02:20.
```

Chi phí cũng cần tính trước. Ở độ phân giải mặc định (low), video tốn khoảng 100 token mỗi giây. Clip 10 phút là 600 giây, tức khoảng 60,000 token cho mỗi lần hỏi. Nếu chỉ cắt 2 phút cần xem, con số còn khoảng 12,000.

Lưu ý rằng ước tính này dựa trên mức mặc định 1 khung hình mỗi giây; khi tăng fps, hãy đo lại số token thực tế thay vì giữ nguyên con số cũ.

Google cũng đã giới thiệu tính năng agentic video understanding, bật qua một thiết lập trong API. Tính năng này nhắm vào đúng vấn đề trên: bắt các thay đổi trạng thái chỉ diễn ra trong tích tắc, dễ bị bỏ sót ở 1 FPS. Nếu bài toán của khách là bắt khoảnh khắc ngắn như vậy, đây là lựa chọn đáng thử so với cách tự tăng fps.

## Bước 5: dữ liệu bẩn là trạng thái bình thường

Splunk khi mô tả AI đa phương thức đã nêu ba khó khăn: độ nhiễu khác nhau, dữ liệu bị thiếu, và việc ghép dữ liệu từ nhiều nguồn. Ở hiện trường, cả ba xảy ra cùng lúc: ảnh mờ, biểu mẫu thiếu trang, video không khớp với phiếu ghi. Pipeline phải coi tình trạng này là bình thường chứ không phải ngoại lệ.

| Đầu vào | Lỗi hay gặp | Việc làm đầu tiên |
|---|---|---|
| Ảnh hiện trường | Xoay ngược, file quá lớn bị từ chối | Chuẩn hóa chiều ảnh, thu nhỏ trước khi gửi |
| Biểu mẫu viết tay | Chữ nhỏ, sai dấu tiếng Việt | Cắt và phóng to vùng chữ, cho phép trả về "không đọc được" |
| Video điện thoại | Bỏ sót sự kiện nhanh ở 1 FPS | Cắt đoạn cần xem, tăng fps, hỏi theo MM:SS |

## Kỹ năng này xuất hiện ở công việc thật như thế nào?

Ở khách hàng, phần khó không nằm ở việc gọi API mà ở việc nói thật về độ chính xác. Khi demo, hãy cho khách xem bảng chấm theo từng trường trên chính dữ liệu của họ: tên thiết bị đúng bao nhiêu phần trăm, ngày tháng đúng bao nhiêu, trường nào cần người duyệt lại.

Một bảng như vậy thuyết phục hơn nhiều so với một ảnh demo chạy hoàn hảo.

Khi đọc JD vị trí FDE, hãy để ý các cụm như "unstructured data", "document processing" hay "multimodal". Trong CV, thay vì viết "dùng GPT-4 Vision", hãy viết cụ thể bạn đã nâng độ chính xác đọc biểu mẫu viết tay tiếng Việt từ bao nhiêu lên bao nhiêu nhờ xoay ảnh và cắt vùng chữ. Con số đó cho thấy bạn đã làm việc với dữ liệu thật.

Ảnh chụp nghiêng đầu tiên khách gửi cho bạn là dấu hiệu tốt. Nó có nghĩa là bạn đang làm với dữ liệu thật của khách, không còn là bản demo.

**Thử ngay tuần này:**

- Chụp 10 biểu mẫu viết tay tiếng Việt (có cả ảnh nghiêng và ảnh chụp xa), tự gõ đáp án, rồi so kết quả model trước và sau khi xoay ảnh và cắt phóng to vùng chữ
- Gửi cùng một ảnh với detail low và high, ghi lại số token và độ chính xác của từng lần
- Quay một clip 60 giây có một sự kiện chỉ kéo dài dưới một giây, hỏi model ở fps mặc định và ở fps cao hơn, rồi so hai câu trả lời

## Nguồn

- [Images and vision - OpenAI API](https://developers.openai.com/api/docs/guides/images-vision)

- [Video understanding - Gemini API](https://ai.google.dev/gemini-api/docs/video-understanding)

- [Introducing agentic video understanding with Gemini](https://blog.google/innovation-and-ai/models-and-research/gemini-models/introducing-agentic-video-in-gemini/)

- [A Multimodal World - Hugging Face Computer Vision Course](https://huggingface.co/learn/computer-vision-course/en/unit4/multimodal-models/a_multimodal_world)

- [What Is Multimodal AI? A Complete Introduction](https://www.splunk.com/en_us/blog/learn/multimodal-ai.html)
