OpenCV cơ bản: xử lý ảnh camera trước khi đưa vào AI
Atlasbot · 18/8/2026 · 11 phút đọc
Trước khi robot "hiểu" được nó đang nhìn thấy gì (object detection, tracking...), khung hình thô từ camera thường cần qua vài bước xử lý cơ bản — đổi không gian màu, resize, làm mượt nhiễu. OpenCV là thư viện tiêu chuẩn cho việc này, được dùng gần như trong mọi pipeline thị giác robot.
Khái niệm chính
OpenCV (Open Source Computer Vision Library) cung cấp hàng trăm hàm xử lý ảnh đã được tối ưu, viết bằng C++ nhưng có binding Python đầy đủ — hầu hết code robot dùng bản Python (cv2) vì viết nhanh, dễ đọc, và tốc độ vẫn đủ tốt vì phần tính toán nặng chạy ở lõi C++ bên dưới.
import cv2
cap = cv2.VideoCapture(0) # mở camera tại /dev/video0
ret, frame = cap.read() # đọc 1 khung hình (BGR, không phải RGB!)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # chuyển sang ảnh xám
blurred = cv2.GaussianBlur(gray, (5, 5), 0) # làm mượt, giảm nhiễu
resized = cv2.resize(frame, (640, 480)) # đổi kích thước cho mô hình AI
Nguyên lý hoạt động
Một điểm hay gây nhầm: OpenCV đọc ảnh theo BGR, không phải RGB — đây là lỗi phổ biến nhất với người mới. cv2.imread/cv2.VideoCapture trả về ảnh theo thứ tự kênh màu BGR thay vì RGB quen thuộc. Nếu đưa thẳng vào mô hình AI được huấn luyện trên ảnh RGB mà không chuyển đổi, kết quả nhận diện sẽ sai lệch dù code chạy không báo lỗi gì.
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # chuyển đúng trước khi đưa vào mô hình
Kiến thức kỹ thuật
Công thức
Resize ảnh trước khi đưa vào mô hình AI cần giữ đúng tỉ lệ khung hình (aspect ratio) để tránh biến dạng vật thể, ảnh hưởng độ chính xác nhận diện:
Tỉ_lệ_gốc = Chiều_rộng_gốc / Chiều_cao_gốc
Tỉ_lệ_đích = Chiều_rộng_đích / Chiều_cao_đích
Nếu Tỉ_lệ_gốc ≠ Tỉ_lệ_đích → ảnh bị kéo dãn/nén méo khi resize trực tiếp
VD: ảnh gốc 640×480 (tỉ lệ 4:3), resize thẳng về 640×640 (tỉ lệ 1:1, YOLO cần)
→ vật thể tròn trong ảnh gốc bị méo thành hình bầu dục sau resize
Giải pháp: letterbox — thêm viền đệm (padding) thay vì kéo dãn trực tiếp,
giữ đúng tỉ lệ gốc bên trong khung hình đích
Thông số
| Thao tác | Hàm OpenCV | Mục đích |
|---|---|---|
| Đổi không gian màu | cv2.cvtColor() | BGR↔RGB, hoặc sang HSV để lọc theo màu |
| Làm mượt/giảm nhiễu | cv2.GaussianBlur() | Giảm nhiễu hạt trước khi phát hiện cạnh/vật thể |
| Resize | cv2.resize() | Đưa về đúng kích thước input mô hình AI yêu cầu |
| Phát hiện cạnh | cv2.Canny() | Tìm biên vật thể, dùng trong các thuật toán cổ điển |
Ứng dụng thực tế
OpenCV là bước tiền xử lý bắt buộc trước khi đưa ảnh vào các mô hình object detection như YOLO (chuyên mục Computer Vision/AI) — mô hình AI kỳ vọng đúng định dạng màu (thường RGB), đúng kích thước input cố định, và đôi khi cần chuẩn hoá giá trị pixel (normalize) về khoảng [0,1]. Bỏ qua bất kỳ bước nào trong chuỗi tiền xử lý này khiến mô hình vẫn chạy được (không báo lỗi) nhưng cho kết quả sai lệch — đây là loại lỗi khó chẩn đoán nhất vì không có thông báo lỗi rõ ràng.
Ví dụ thực tế
import cv2
import numpy as np
def preprocess_for_model(frame, target_size=640):
h, w = frame.shape[:2]
scale = target_size / max(h, w)
new_w, new_h = int(w * scale), int(h * scale)
resized = cv2.resize(frame, (new_w, new_h))
# Letterbox: dem vien de giu dung ti le
canvas = np.full((target_size, target_size, 3), 114, dtype=np.uint8)
pad_x, pad_y = (target_size - new_w) // 2, (target_size - new_h) // 2
canvas[pad_y:pad_y+new_h, pad_x:pad_x+new_w] = resized
rgb = cv2.cvtColor(canvas, cv2.COLOR_BGR2RGB)
normalized = rgb.astype(np.float32) / 255.0
return normalized
frame = cv2.imread("test.jpg")
processed = preprocess_for_model(frame)
print(f"Kich thuoc dau vao mo hinh: {processed.shape}, gia tri: [{processed.min():.2f}, {processed.max():.2f}]")
Output:
Kich thuoc dau vao mo hinh: (640, 640, 3), gia tri: [0.00, 1.00]
Pipeline này minh hoạ đủ 4 bước tiền xử lý quan trọng nhất: resize giữ tỉ lệ (letterbox), đổi màu BGR→RGB, và chuẩn hoá giá trị pixel — thiếu bất kỳ bước nào cũng có thể khiến mô hình AI cho kết quả sai mà không báo lỗi.
Lỗi thường gặp
- Quên chuyển BGR sang RGB trước khi đưa vào mô hình AI — như đã nêu ở phần Nguyên lý hoạt động, đây là lỗi phổ biến nhất, mô hình vẫn chạy nhưng kết quả sai lệch không có cảnh báo.
- Resize trực tiếp không giữ tỉ lệ khung hình — như tính ở mục Công thức, gây méo vật thể, ảnh hưởng độ chính xác nhận diện, đặc biệt với vật thể có hình dạng đặc trưng (biển báo, mã vạch).
- Bỏ qua bước chuẩn hoá giá trị pixel khi mô hình yêu cầu — nhiều mô hình AI kỳ vọng input trong khoảng [0,1] hoặc đã chuẩn hoá theo mean/std cụ thể, đưa thẳng giá trị pixel gốc [0,255] khiến mô hình hoạt động sai.
- Không kiểm tra kích thước ảnh đầu ra khớp đúng yêu cầu input của mô hình — mô hình có thể tự động resize lại (một số framework), nhưng không phải lúc nào cũng vậy, cần xác nhận rõ ràng.
Kết luận
OpenCV là nền tảng xử lý ảnh mà hầu hết pipeline thị giác robot đều đi qua trước khi tới bước AI — nắm vững các thao tác cơ bản (đổi màu, resize giữ tỉ lệ, chuẩn hoá) và nhớ kỹ vụ BGR/RGB sẽ tránh được phần lớn lỗi "mô hình chạy nhưng kết quả sai" khi mới bắt đầu. Bài tiếp theo trong chuyên mục đi vào image_transport — cách gửi ảnh hiệu quả giữa các node ROS2 khi hệ thống có nhiều máy tính.