Mỗi bức ảnh kỹ thuật số là một ma trận số nguyên không dấu 8-bit (uint8, nhận giá trị từ $0$ đến $255$).
import cv2
import numpy as np
import requests
from google.colab.patches import cv2_imshow
# 1. Tải ảnh bằng requests kèm User-Agent để tránh bị chặn
url = "https://raw.githubusercontent.com/opencv/opencv/master/samples/data/lena.jpg"
headers = {"User-Agent": "Mozilla/5.0"}
response = requests.get(url, headers=headers)
# Lưu ảnh ra file trên máy ảo Colab
with open("sample.jpg", "wb") as f:
f.write(response.content)
# 2. Đọc ảnh vào bộ nhớ bằng OpenCV
img = cv2.imread("sample.jpg")
# Kiểm tra đảm bảo ảnh đã nạp thành công
if img is None:
print("❌ Lỗi: Không thể đọc file ảnh. Vui lòng kiểm tra lại đường dẫn!")
else:
# 3. Phân tích cấu trúc ma trận
print("Kiểu dữ liệu:", type(img))
print("Kích thước ma trận (Height, Width, Channels):", img.shape)
print("Kiểu phần tử điểm ảnh:", img.dtype)
# 4. Hiển thị ảnh trên Colab
cv2_imshow(img)
OpenCV quy ước thứ tự kênh màu là Blue - Green - Red (BGR), trong khi các thư viện hiển thị như matplotlib lại hiểu theo chuẩn Red - Green - Blue (RGB).
# Hiển thị trực tiếp bằng matplotlib -> Ảnh sẽ bị lệch tông màu xanh
fig, axes = plt.subplots(1, 2, figsize=(10, 5))
axes[0].imshow(img)
axes[0].set_title("Hiển thị gốc BGR (Lệch màu)")
# Chuyển đổi BGR sang RGB bằng cv2.cvtColor
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
axes[1].imshow(img_rgb)
axes[1].set_title("Sau khi đổi sang RGB (Màu chuẩn)")
plt.show()
Vì ảnh là một mảng NumPy, các thao tác cắt ảnh (crop) thực chất là cắt lát mảng đa chiều theo trục $Y$ (dòng) và $X$ (cột): img[y_start:y_end, x_start:x_end].
# 1. Cắt vùng trung tâm bức ảnh (Cropping)
h, w = img.shape[:2]
crop_region = img[h//4 : 3*h//4, w//4 : 3*w//4]
# 2. Thay đổi kích thước ảnh (Resizing)
# Lưu ý: cv2.resize nhận tham số kích thước theo thứ tự (Width, Height)
resized_img = cv2.resize(img, (300, 200))
# 3. Xoay ảnh 90 độ theo chiều kim đồng hồ
rotated_img = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)
# Hiển thị kết quả
cv2_imshow(crop_region)
cv2_imshow(resized_img)
Không gian màu BGR rất nhạy cảm với ánh sáng (bóng râm, độ chói). Trong Computer Vision, hệ màu HSV (Hue - Saturation - Value) được sử dụng phổ biến khi cần nhận diện màu:
Hue (0-179 trong OpenCV): Bản chất sắc độ màu (Đỏ, Vàng, Xanh...).
Saturation (0-255): Độ đậm đặc của màu.
Value (0-255): Cường độ sáng.
Tạo một tấm ảnh nhân tạo chứa các khối màu và lọc riêng màu xanh lá:
# Tạo ảnh mẫu gồm nền đen và 2 khối màu
synthetic_img = np.zeros((300, 500, 3), dtype=np.uint8)
synthetic_img[50:250, 50:200] = [0, 255, 0] # Khối Xanh lá (BGR)
synthetic_img[50:250, 300:450] = [0, 0, 255] # Khối Đỏ (BGR)
# Chuyển đổi sang không gian HSV
hsv = cv2.cvtColor(synthetic_img, cv2.COLOR_BGR2HSV)
# Định nghĩa dải ngưỡng màu Xanh lá trong HSV
lower_green = np.array([35, 50, 50])
upper_green = np.array([85, 255, 255])
# Tạo mặt nạ nhị phân (Binary Mask): 255 cho vùng trúng màu, 0 cho vùng khác
mask = cv2.inRange(hsv, lower_green, upper_green)
# Phép toán Bitwise-AND để giữ lại đúng vật thể màu xanh
result = cv2.bitwise_and(synthetic_img, synthetic_img, mask=mask)
print("Ảnh gốc:")
cv2_imshow(synthetic_img)
print("Mặt nạ nhị phân (Mask):")
cv2_imshow(mask)
print("Kết quả sau khi lọc tách màu:")
cv2_imshow(result)
Đây là pipeline xử lý hình thái học kinh điển để đếm sản phẩm trên băng chuyền hoặc đo đạc kích thước:
# 1. Chuyển ảnh về ảnh xám (1 kênh)
gray = cv2.cvtColor(synthetic_img, cv2.COLOR_BGR2GRAY)
# 2. Khử nhiễu tần số cao bằng Gaussian Blur (Kernel 5x5)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
# 3. Dò viền bằng thuật toán Canny
edges = cv2.Canny(blurred, threshold1=50, threshold2=150)
# 4. Trích xuất đường biên hình học (Contours)
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
print(f"Tổng số lượng vật thể phát hiện: {len(contours)}")
# 5. Vẽ khung bao chữ nhật (Bounding Box) quanh từng vật thể
output = synthetic_img.copy()
for i, cnt in enumerate(contours):
x, y, w, h = cv2.boundingRect(cnt)
# Vẽ khung chữ nhật màu trắng, độ dày nét = 2
cv2.rectangle(output, (x, y), (x + w, y + h), (255, 255, 255), 2)
cv2.putText(output, f"Object #{i+1}", (x, y - 10),
cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2)
cv2_imshow(output)
Do Colab chạy trên máy chủ đám mây, hàm cv2.VideoCapture(0) không thể kết nối tới webcam máy tính cá nhân của bạn thông qua cổng USB máy ảo.
Đối với video có sẵn (file .mp4), quy trình xử lý chuẩn là:
Mở file video bằng cv2.VideoCapture("input.mp4").
Đọc và can thiệp từng khung hình trong vòng lặp while.
Ghi kết quả vào một video mới qua cv2.VideoWriter.
# 1. Tải video ngắn mẫu
!wget -q -O sample_video.mp4 "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4"
cap = cv2.VideoCapture("sample_video.mp4")
# Lấy các thông số của video gốc
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = cap.get(cv2.CAP_PROP_FPS)
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
# Khởi tạo bộ ghi video (VideoWriter)
out = cv2.VideoWriter("processed_output.mp4", fourcc, fps, (width, height), isColor=False)
frame_count = 0
# Xử lý 100 khung hình đầu tiên để demo
while cap.isOpened() and frame_count < 100:
ret, frame = cap.read()
if not ret:
break
# Biến đổi: Chuyển sang ảnh xám và vẽ số thứ tự khung hình
gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
cv2.putText(gray_frame, f"Frame: {frame_count}", (30, 50),
cv2.FONT_HERSHEY_SIMPLEX, 1.2, (255), 2)
# Ghi frame vào file đầu ra
out.write(gray_frame)
frame_count += 1
cap.release()
out.release()
print(f"Đã xử lý và lưu thành công {frame_count} frames vào file 'processed_output.mp4'!")