Vì sao gốc tọa độ ảnh ở góc trên bên trái?

  Jul 8, 2026      2m      0   
 

OpenCV - Tut 1.3: Vì sao gốc tọa độ ảnh nằm ở góc trên bên trái?

Vì sao gốc tọa độ ảnh ở góc trên bên trái?

Tut 1.3: Vì sao gốc tọa độ ảnh ở góc trên bên trái?

Hi mọi người, lại là Minh đây. Trong Tut 1.1: Cấu trúc dữ liệu ảnh trong OpenCV. Pixel là gì? ta đã biết rằng gốc tọa độ của ảnh được đặt ở góc trên bên trái. Điều này khá khác với hệ trục tọa độ quen thuộc trong Toán học.

Điều này thật bất tiện khi mỗi lần tính quỹ đạo di chuyển ta phải thực hiện chuyển đổi trục y=height-y, để nó trở về hệ trục tọa độ trong toán học quen thuộc. Nhiều bạn hỏi Minh: "Ủa vì sao lại như vậy?" — nên ở Tut 1.3 này ta cùng mổ xẻ cho ra ngô ra khoai lý do nha.

👉 Câu trả lời ngắn gọn là: gốc tọa độ ảnh nằm ở góc trên bên trái vì lý do lịch sử, thực tiễn và cách tổ chức bộ nhớ.

Ảnh được lưu trong bộ nhớ máy tính như thế nào?

Ảnh số gần như luôn được lưu dưới dạng mảng 1 chiều theo "row-major order":

  • Bắt đầu từ dòng trên cùng (row 0).
  • Pixel được lưu từ trái qua phải trên cùng một dòng.
  • Sau đó chuyển xuống dòng tiếp theo, rồi lặp lại.

Do đó, cách ánh xạ trong bộ nhớ sẽ tự nhiên trở thành:

  • (x=0, y=0) = pixel ở góc trên bên trái
  • y tăng dần theo hướng đi xuống

Cách này phù hợp với hầu hết định dạng ảnh phổ biến (PNG, JPEG, và phần lớn bitmap buffer khi load vào bộ nhớ) cũng như cách GPU / texture memory được tổ chức. Nếu ta cố đảo ngược lại thì mỗi lần load ảnh hoặc hiển thị ảnh đều sẽ cần thêm bước xử lý không cần thiết.

BMP là một trường hợp hơi đặc biệt về mặt lịch sử. File BMP kiểu cũ mặc định lưu các dòng ảnh theo thứ tự từ dưới lên trên (giá trị biHeight dương trong header nghĩa là bottom-up). Tuy nhiên, đa số thư viện ảnh sẽ âm thầm đảo nó lại thành top-down buffer trong lúc giải mã. Vì vậy tới lúc code của ta đọc pixel ra thì nó vẫn hoạt động giống PNG/JPEG — tức là gốc ở góc trên bên trái.

Đây là lý do cốt lõi của vị trí gốc tọa độ ảnh đặt góc trên bên trái.

1d array - row major order

Nguồn gốc lịch sử (từ trước thời đồ họa máy tính)

  • Tivi và màn hình CRT (khoảng 1930s–1980s): chùm electron quét từ trên xuống dưới, từ trái qua phải. Dòng tín hiệu đầu tiên chính là dòng trên cùng. Cách làm này dần trở thành chuẩn de-facto.
  • Text terminal và framebuffer đời đầu cũng đi theo đúng quy ước đó (line 0 = phía trên).
  • Khi bitmap graphics xuất hiện (1970s–80s), chúng kế thừa trực tiếp thứ tự quét này. Nếu đổi ngược lại thì sẽ phá vỡ tính tương thích với phần cứng lúc bấy giờ.

Vì sao trong Toán học lại khác?

Trong hệ tọa độ Descartes tiêu chuẩn:

  • y tăng dần theo hướng đi lên
  • Gốc tọa độ thường được đặt ở góc dưới bên trái (đặc biệt khi vẽ đồ thị)

Điều này phù hợp với trực giác vật lý của con người (đi lên là dương) và được các nhà toán học chọn để phục vụ hình học, cơ học, vật lý.

Trong khi đó, máy tính ưu tiên hiệu năng và sự thuận tiện cho phần cứng hơn là "vẻ đẹp hình thức" của Toán học.

So sánh trực quan

SystemOriginX directionY directionReason
Toán học (tiêu chuẩn)Góc dưới bên tráiPhảiLên trênTrực giác vật lý, hình học
Ảnh số / Tọa độ pixelGóc trên bên tráiPhảiĐi xuốngCách lưu bộ nhớ + cách màn hình quét
Một số graphics APIsGóc dưới bên tráiPhảiLên trênVí dụ: OpenGL với "normalized coordinates / UV texture coordinates". Tuy nhiên DirectX, Vulkan và Metal lại dùng quy ước top-left trong nhiều ngữ cảnh, nên chỗ này còn tùy API cụ thể.

Cách xử lý linh hoạt ở thời hiện đại

  • Graphics libraries hiện đại thường hỗ trợ cả hai kiểu hệ trục:
    • Tọa độ pixel: top-left (0,0)
    • "Normalized device coordinates / UV texture coords": thường là bottom-left (0,0)
  • Bạn hoàn toàn có thể tự lật trục y khi cần (ví dụ thường gặp trong shader: y = height - y).
  • Các công cụ như Matplotlib, Processing, … cũng cho phép ta chọn hệ trục tọa độ phù hợp.

Tóm lại: gốc tọa độ ở góc trên bên trái là một quyết định kỹ thuật rất thực dụng. Nó khớp với cách màn hình hoạt động và cách bộ nhớ được tổ chức. Toán học tối ưu cho trực giác của con người; máy tính tối ưu cho tốc độ và sự đơn giản khi hiện thực. Vì vậy, quy ước này ngày nay gần như xuất hiện ở khắp nơi trong xử lý ảnh, thị giác máy tính (computer vision), web (Canvas), và cả game engines.

Nếu đọc tới đây mà bạn thấy "à ha, hiểu rồi đó", hãy quay lại xem lại các ví dụ indexing pixel trong Tut 1.1 — lúc đó thứ tự img[y, x] sẽ trở nên dễ hiểu hơn rất nhiều 🤗 :)~

Kết nối lại với các bài OpenCV

Kiến thức về gốc tọa độ ảnh không phải để biết cho vui đâu nha, mà nó sẽ đụng trực tiếp tới hầu hết thao tác cơ bản trong OpenCV:

  • Khi đọc một pixel, ta dùng img[y, x] chứ không phải img[x, y] vì ma trận ảnh được tổ chức theo height x width.
  • Khi lấy ROI (Region of Interest), cú pháp đúng sẽ là img[y_from:y_to, x_from:x_to].
  • Khi crop ảnh, bản chất vẫn chỉ là cắt theo trục y trước, rồi mới tới trục x.
  • Khi resize ảnh, kích thước ảnh có thay đổi nhưng quy ước gốc tọa độ vẫn giữ nguyên ở góc trên bên trái.

Nắm chắc chỗ này rồi thì sang Tut 2: Xử lý ảnh - OpenCV resize, crop và padding hình ảnh (code Python và C++) hoặc Tut 4: Xử lý ảnh - OpenCV vùng quan tâm (ROI) là gì? (code Python) bạn sẽ đỡ bị nhầm trục hơn rất nhiều.

Bài viết tiếp theo Tut 2: Xử lý ảnh - OpenCV resize, crop và padding hình ảnh (code Python và C++)


Cảm ơn bạn đã theo dõi bài viết. Hãy kết nối với tớ nhé!

Khám phá xử lý ảnh - GVGroup


Danh sách bài viết series OpenCV: