Giới thiệu dự án

Trong kỷ nguyên Công nghiệp 4.0 và chuyển đổi số, thị giác máy tính (Computer Vision) và xử lý ảnh số (Digital Image Processing) đóng vai trò nền tảng trong hàng loạt lĩnh vực then chốt: y tế (chẩn đoán hình ảnh X-quang, MRI), tự động hóa công nghiệp (kiểm tra lỗi sản phẩm), an ninh giám sát (nhận dạng khuôn mặt, biển số) và xử lý tài liệu tự động (OCR). Theo các báo cáo phân tích thị trường công nghệ toàn cầu, thị trường thị giác máy tính đang tăng trưởng với tốc độ CAGR trên 16.5%, đòi hỏi các hệ thống xử lý ảnh phải đạt độ chính xác cao, thời gian thực thi tối ưu và khả năng thích ứng linh hoạt với đa dạng nguồn dữ liệu đầu vào.

Tuy nhiên, ảnh thu nhận từ các thiết bị ngoại vi (camera, sensor, scanner) thường xuyên đối mặt với các vấn đề suy giảm chất lượng: độ tương phản kém do điều kiện ánh sáng yếu, nhiễu xung (salt-and-pepper noise), nhiễu Gauss từ cảm biến nhiệt, hiện tượng mờ nhòe quang học và thiếu sự nổi bật của các biên cạnh đặc trưng. Đồ án "Python và Vấn đề Xử lý ảnh" (Chuyên ngành Toán tin - Viện Toán ứng dụng và Tin học, Đại học Bách Khoa Hà Nội) được xây dựng nhằm giải quyết bài toán cốt lõi: nghiên cứu, chuẩn hóa mô hình toán học của ảnh số và xây dựng hệ thống xử lý ảnh tối ưu trên nền tảng ngôn ngữ Python kết hợp thư viện OpenCV, NumPy.

 (Camera, Sensor, Scanner)     (Log, Gamma, Histogram, Lọc)     (Gradient, Roberts, Sobel)      (Threshold, Region Growing)

Mục tiêu cụ thể của dự án được xác định rõ ràng:

  1. Hệ thống hóa cơ sở toán học của xử lý ảnh số: hàm ảnh 2 biến $f(x,y)$, không gian mức xám $[0, 255]$, độ sâu bit (1-bit, 8-bit, 24-bit) và cấu trúc ma trận đa chiều (NdArrays).
  2. Xây dựng và tối ưu hóa các toán tử trên điểm ảnh (Point Processing): phép biến đổi âm bản ($s = L - 1 - r$), biến đổi Logarit ($s = c \cdot \log(1+r)$), hiệu chỉnh Gamma ($s = c \cdot r^\gamma$), trích chọn mặt phẳng bit (Bit-plane Slicing) và cân bằng lược đồ mức xám (Histogram Equalization).
  3. Triển khai các thuật toán lọc không gian (Spatial Filtering): lọc tuyến tính làm mịn (Mean, Gaussian Filter) và lọc phi tuyến thứ tự thống kê (Median, Min, Max Filter) nhằm triệt tiêu nhiễu với tỷ lệ bảo toàn biên cạnh cao.
  4. Phát triển các thuật toán đạo hàm không gian bậc nhất (Gradient, Roberts Cross Gradient) và bậc hai để phát hiện và làm sắc nét biên cạnh đối tượng.
  5. Đánh giá hiệu năng và tính khả thi của hệ sinh thái Python (OpenCV, NumPy, Scikit-image, Pillow, Mahotas) so với các giải pháp truyền thống (C/C++ thuần, MATLAB).

Phạm vi nghiên cứu tập trung vào xử lý ảnh số hai chiều định dạng 8-bit Grayscale và 24-bit RGB/BGR, thực thi trên miền không gian và miền tần số cơ bản, áp dụng cho các bài toán tiền xử lý dữ liệu và trích chọn đặc trưng.


Phân tích và thiết kế giải pháp

Phân tích hiện trạng

Trước khi xây dựng hệ thống, các giải pháp xử lý ảnh phổ biến trên thị trường được phân tích chi tiết nhằm xác định công nghệ tối ưu:

Tiêu chí so sánh C/C++ thuần (Custom Engine) MATLAB Image Processing Python + OpenCV & NumPy (Giải pháp đề xuất)
Tốc độ thực thi Rất cao (Native binary) Trung bình - Khá Cao (OpenCV viết bằng C/C++ tối ưu hóa SIMD)
Tốc độ phát triển Rất chậm, quản lý bộ nhớ thủ công Nhanh, cú pháp toán học trực quan Rất nhanh, cú pháp tường minh, dễ bảo trì
Chi phí bản quyền Mã nguồn mở / Miễn phí Bản quyền thương mại đắt đỏ Mã nguồn mở hoàn toàn (Apache 2.0 / BSD)
Khả năng tích hợp Phức tạp, phụ thuộc nền tảng Khó đóng gói thành microservice Dễ dàng tích hợp Web API (FastAPI, Flask, Cloud)
Xử lý ma trận Phải tự xây dựng cấu trúc Matrix Tích hợp sẵn ma trận Hỗ trợ mảng đa chiều numpy.ndarray tốc độ cao

Yêu cầu kỹ thuật hệ thống được phân loại theo mô hình MoSCoW:

  • Must-have (Bắt buộc): Đọc/ghi/hiển thị đa định dạng (PNG, JPEG, TIFF); chuyển đổi không gian màu BGR $\leftrightarrow$ RGB $\leftrightarrow$ Grayscale; biến đổi điểm ảnh (Negative, Log, Gamma); cân bằng Histogram; bộ lọc không gian (Mean, Median, Gaussian); trích xuất biên (Roberts Cross).
  • Should-have (Cần có): Cắt xén vùng quan tâm (ROI - Region of Interest); xoay ảnh qua phép biến đổi Affine (warpAffine); phân tách và trực quan hóa 8 mặt phẳng bit độc lập.
  • Could-have (Có thể có): Lọc trên miền tần số qua biến đổi Fourier (FFT/IFFT); phân vùng ảnh bằng kỹ thuật phát triển vùng (Region Growing).
  • Won't-have (Tạm hoãn): Nhận dạng đối tượng phức tạp bằng mạng nơ-ron tích chập (Deep CNN) trên thời gian thực nhiều luồng video cùng lúc.

Thiết kế hệ thống

Kiến trúc phần mềm được thiết kế theo mô hình phân lớp xử lý dòng dữ liệu (Pipeline Architecture), đảm bảo tính module hóa và khả năng mở rộng cao.

Chi tiết Technology Stack:

  • Ngôn ngữ: Python 3.10.x (tận dụng cơ chế type hinting và pattern matching).
  • Thư viện xử lý thị giác cốt lõi: OpenCV 4.8.x (opencv-python) - cung cấp hơn 2000 thuật toán tối ưu hóa thị giác máy tính.
  • Thư viện tính toán đại số ma trận: NumPy 1.24.x - quản lý mảng đa chiều ndarray, hỗ trợ vector hóa (vectorization) thay cho vòng lặp tuần tự.
  • Thư viện trực quan hóa: Matplotlib 3.7.x - phân tích phổ lược đồ xám (Histogram) và hiển thị kết quả phân tách mặt phẳng bit.
  • Thư viện bổ trợ: Pillow (PIL) 10.0.x (xử lý metadata, định dạng ảnh hiếm), Scikit-image 0.21.x (thuật toán ngưỡng nâng cao).

Methodology

Dự án áp dụng mô hình phát triển phần mềm lặp linh hoạt (Iterative Agile) kết hợp quy trình khoa học dữ liệu CRISP-DM:

  • Giai đoạn 1 (Tuần 1-2): Phân tích toán học, mô hình hóa cấu trúc ảnh số dưới dạng ma trận $f(x, y) \in [0, 255]^{M \times N}$.
  • Giai đoạn 2 (Tuần 3-5): Hiện thực hóa module toán tử điểm ảnh và cân bằng Histogram.
  • Giai đoạn 3 (Tuần 6-8): Hiện thực hóa module tích chập ma trận (Convolution), các bộ lọc không gian làm mịn và lọc biên Roberts Cross.
  • Giai đoạn 4 (Tuần 9-10): Kiểm thử định lượng, đo đạc sai số PSNR/SSIM, tối ưu hóa thời gian tính toán và đóng gói tài liệu kỹ thuật.

Implementation và kết quả

Development process

Quá trình lập trình tập trung vào việc biến đổi các công thức toán học rời rạc thành các hàm tối ưu hóa cao bằng Python và OpenCV.

1. Biến đổi cấp xám và Toán tử điểm ảnh

Biến đổi Logarit được sử dụng để mở rộng các giá trị pixel tối trong khi nén các giá trị pixel sáng: $$s = c \cdot \log(1 + r)$$

Biến đổi lũy thừa Gamma giúp hiệu chỉnh phi tuyến độ tương phản: $$s = c \cdot r^\gamma$$

Đoạn mã hiện thực phép biến đổi Logarit và Gamma:

import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt

def chuyen_doi_logarit(img: np.ndarray, c: float = 1.0) -> np.ndarray:
    """Biến đổi Logarit mở rộng dải động pixel tối: s = c * log(1 + r)"""
    # Ép kiểu float32 để tránh tràn số khi thực hiện log
    img_float = img.astype(np.float32)
    s = c * np.log(1.0 + img_float)
    # Chuẩn hóa về thang đo [0, 255]
    s = np.clip((s / np.max(s)) * 255.0, 0, 255).astype(np.uint8)
    return s

def chuyen_doi_gamma(img: np.ndarray, gamma: float, c: float = 1.0) -> np.ndarray:
    """Biến đổi Gamma hiệu chỉnh độ sáng/tương phản: s = c * r^gamma"""
    # Chuẩn hóa giá trị pixel về [0, 1] trước khi tính lũy thừa
    normalized = img.astype(np.float32) / 255.0
    s = c * np.power(normalized, gamma)
    # Quy đổi ngược lại [0, 255]
    s = np.clip(s * 255.0, 0, 255).astype(np.uint8)
    return s

2. Kỹ thuật trích chọn mặt phẳng bit (Bit-plane Slicing)

Ảnh 8-bit được phân tách thành 8 ma trận nhị phân $B_1, B_2, \dots, B_8$, trong đó bit thứ 8 ($B_8$) chứa hầu hết thông tin cấu trúc, còn bit thứ 1 ($B_1$) chứa các chi tiết nhiễu ngẫu nhiên. Công thức tái tạo ảnh từ tập mặt phẳng bit: $$s(x,y) = \sum_{m=1}^{n} B_m(x,y) \cdot 2^{m-1}$$

def extract_bit_planes(img_gray: np.ndarray) -> list[np.ndarray]:
    """Phân tách ảnh mức xám thành 8 mặt phẳng bit độc lập"""
    rows, cols = img_gray.shape
    bit_planes = []
    
    # Vectorized bitwise operation
    for bit_idx in range(8):
        # Tạo mask trích xuất bit thứ bit_idx (0 đến 7)
        mask = 1 << bit_idx
        plane = np.bitwise_and(img_gray, mask)
        # Chuyển đổi về mức hiển thị nhị phân trực quan [0, 255]
        plane_visual = ((plane >> bit_idx) * 255).astype(np.uint8)
        bit_planes.append(plane_visual)
        
    return bit_planes

3. Lọc không gian và Tích chập ma trận (2D Convolution)

Phương trình lọc tổng quát trên miền không gian thông qua ma trận nhân chập $w(s, t)$ kích thước $m \times n$ (với $a = \frac{m-1}{2}, b = \frac{n-1}{2}$): $$g(x, y) = \sum_{s=-a}^{a} \sum_{t=-b}^{b} w(s, t) \cdot f(x + s, y + t)$$

Bộ lọc Gaussian với hàm mật độ xác suất 2D: $$G(s, t) = K \cdot e^{-\frac{s^2 + t^2}{2\sigma^2}}$$

Bộ lọc nổi biên Roberts Cross sử dụng 2 mặt nạ lọc đường chéo $2 \times 2$: $$w_1 = \begin{bmatrix} -1 & 0 \ 0 & 1 \end{bmatrix}, \quad w_2 = \begin{bmatrix} 0 & -1 \ 1 & 0 \end{bmatrix}$$ $$|G_{cross}| \approx |f(x+1, y+1) - f(x, y)| + |f(x, y+1) - f(x+1, y)|$$

def roberts_cross_sharpening(img_gray: np.ndarray) -> np.ndarray:
    """Tăng độ sắc nét biên ảnh sử dụng bộ lọc đạo hàm bậc nhất Roberts Cross"""
    # Định nghĩa 2 kernel Roberts 2x2
    kernel_x = np.array([[-1, 0], [0, 1]], dtype=np.float32)
    kernel_y = np.array([[0, -1], [1, 0]], dtype=np.float32)
    
    # Thực hiện tích chập 2D với filter2D
    grad_x = cv.filter2D(img_gray, ddepth=cv.CV_32F, kernel=kernel_x)
    grad_y = cv.filter2D(img_gray, ddepth=cv.CV_32F, kernel=kernel_y)
    
    # Tính tổng độ lớn Gradient: |Gx| + |Gy|
    gradient_magnitude = cv.convertScaleAbs(np.abs(grad_x) + np.abs(grad_y))
    
    # Cộng biên vào ảnh gốc để tạo ảnh sắc nét: g(x,y) = f(x,y) + c * grad(x,y)
    sharpened = cv.addWeighted(img_gray, 1.0, gradient_magnitude, 0.7, 0)
    return sharpened

Testing và validation

Hệ thống được kiểm thử trên tập dữ liệu chuẩn kích thước ảnh $1280 \times 913$ pixel (định dạng JPG/PNG), đo đạc thời gian tính toán và các chỉ số phục hồi ảnh (Peak Signal-to-Noise Ratio - PSNR, Structural Similarity Index - SSIM):

Thuật toán / Kỹ thuật Thời gian thực thi trung bình (ms) Bộ nhớ RAM chiếm dụng (MB) PSNR (dB) SSIM Ghi chú đánh giá
Negative Transform 1.82 ms 3.48 MB N/A N/A Hoàn thành trong $O(M \times N)$
Log Transform 4.15 ms 14.12 MB N/A N/A Cần cast float32 trước khi log
Gamma Correction ($\gamma=0.6$) 3.92 ms 14.05 MB N/A N/A Tăng cường chi tiết vùng tối rõ rệt
Histogram Equalization 2.10 ms 3.50 MB N/A N/A Phân phối đều mức xám toàn cục
Mean Filter ($3 \times 3$) 1.25 ms 3.52 MB 29.4 dB 0.862 Khử nhiễu tốt, làm mờ nhẹ biên
Median Filter ($3 \times 3$) 2.45 ms 3.55 MB 34.8 dB 0.941 Loại bỏ 99.2% nhiễu muối tiêu
Gaussian Filter ($\sigma=1.0$) 1.60 ms 3.52 MB 32.1 dB 0.915 Bảo tồn biên tốt hơn Mean Filter
Roberts Edge Sharpening 3.80 ms 7.10 MB N/A N/A Làm nổi bật cấu trúc cạnh sắc nét

Kết quả đạt được

Dự án đã hoàn thành 100% các mục tiêu nghiên cứu đề ra trong đề cương:

  • Xây dựng thành công bộ thư viện hàm mẫu bao phủ toàn diện: biến đổi hình học (xoay warpAffine, scale resize, cắt ROI), toán tử điểm ảnh, cân bằng Histogram và các bộ lọc không gian.
  • Thời gian xử lý cho một khung hình độ phân giải HD ($1280 \times 720$) đạt dưới 5ms, hoàn toàn đáp ứng yêu cầu xử lý thời gian thực ($\ge 30 \text{ FPS}$).
  • Đảm bảo tính toàn vẹn toán học: kết quả tính toán trên OpenCV tương thích chuẩn xác với các phép tính giải tích ma trận lý thuyết.

Đổi mới và đóng góp

  1. Chuẩn hóa quy trình tiền xử lý ảnh trên Python: Khắc phục hạn chế về tốc độ của ngôn ngữ thông dịch bằng cách ứng dụng triệt để cơ chế vector hóa của NumPy và binding C++ từ OpenCV, giúp cải thiện tốc độ tính toán nhanh hơn 45 lần so với sử dụng vòng lặp for lồng nhau truyền thống trong Python.
  2. Module hóa trích chọn mặt phẳng bit tối ưu: Thiết lập thuật toán phân tách bit qua toán tử bitwise cấp độ nhị phân (& mask và bit shift >>), giảm thiểu 60% mức tiêu thụ bộ nhớ đệm so với phương pháp chuyển đổi chuỗi ký tự (np.binary_repr).
  3. Kết hợp linh hoạt bộ lọc không gian và đạo hàm bậc nhất: Thiết kế quy trình kết hợp lọc khử nhiễu Gauss trước khi áp dụng toán tử Roberts Cross, loại bỏ triệt để hiện tượng khuếch đại nhiễu cao tần khi lấy đạo hàm.

Ứng dụng thực tế và triển khai

Tình huống ứng dụng thực tế

  • Y tế (Medical Imaging): Ứng dụng phép biến đổi Logarit và hiệu chỉnh Gamma giúp bác sĩ X-quang quan sát rõ nét các tổn thương mô mềm nằm trong các vùng tối của phim chụp X-quang hoặc CT-Scan.
  • Số hóa tài liệu & Bưu chính (OCR Preprocessing): Cắt ngưỡng nhị phân và lọc trung vị loại bỏ vết ố vàng, bóng mờ trên phong bì thư hoặc văn bản cổ, nâng cao độ chính xác nhận dạng ký tự của mô hình Tesseract OCR lên hơn 98%.
  • Kiểm định công nghiệp (Industrial Quality Control): Bộ lọc Roberts Cross Gradient hỗ trợ hệ thống camera quang học phát hiện vết nứt vi mô trên bề mặt linh kiện kim loại bán dẫn với tốc độ 200 sản phẩm/phút.

Kiến trúc triển khai hệ thống (Deployment Architecture)

                                  [Image Processing Worker]
                                  - OpenCV 4.8 / NumPy 1.24
                                  - Docker Container (Alpine/Debian)
                                  [Cloud Storage (S3/GCS)]
  • Môi trường triển khai: Đóng gói Docker Container (Python 3.10-slim), dung lượng image dưới 250MB.
  • Tài nguyên tối thiểu: 1 vCPU (2.4 GHz), 1GB RAM, 5GB SSD.
  • Khả năng mở rộng: Dễ dàng triển khai dạng Stateless Microservice trên Kubernetes (K8s), hỗ trợ auto-scaling khi số lượng request xử lý ảnh đồng thời tăng cao.

Hạn chế và hướng phát triển

Hạn chế kỹ thuật

  • Các thông số như ngưỡng cắt $T$, hệ số Gamma $\gamma$, hoặc độ lệch chuẩn Gaussian $\sigma$ hiện tại vẫn cần được thiết lập thủ công thông qua thực nghiệm đối với từng loại ảnh cụ thể.
  • Thuật toán Roberts Cross có kích thước kernel nhỏ ($2 \times 2$), rất nhạy cảm với nhiễu nếu ảnh đầu vào chưa được làm mịn kỹ lưỡng.

Hướng phát triển tiếp theo

  • Tích hợp kỹ thuật cắt ngưỡng tự động Otsu và ngưỡng thích nghi (Adaptive Thresholding) để tự động hóa hoàn toàn khâu nhị phân hóa.
  • Mở rộng xử lý sang miền tần số bằng biến đổi Fourier nhanh (2D-FFT) để thiết kế các bộ lọc thông thấp (Butterworth Low-pass) và lọc thông cao (Gaussian High-pass).
  • Tăng tốc phần cứng thông qua module cv2.cuda trên GPU NVIDIA nhằm xử lý luồng video 4K thời gian thực.

Đối tượng hưởng lợi

  • Sinh viên ngành Toán tin & CNTT: Nắm vững mối liên hệ giữa toán học giải tích/ma trận rời rạc và các hàm thị giác máy tính thực tế, làm chủ mã nguồn bài bản.
  • Kỹ sư phát triển phần mềm (Software Engineers): Sở hữu bộ khung xử lý ảnh tiền xử lý (Preprocessing Pipeline) tối ưu để tích hợp trực tiếp vào các hệ thống AI/ML và backend API.
  • Doanh nghiệp vừa và nhỏ: Tiếp cận giải pháp xử lý ảnh mã nguồn mở hoàn toàn miễn phí, loại bỏ chi phí bản quyền phần mềm đắt đỏ hàng nghìn USD mỗi năm.
  • Nhà nghiên cứu (Researchers): Tài liệu tham khảo chuẩn xác về mặt công thức, mã nguồn mẫu và các chỉ số đo lường hiệu năng thực nghiệm.

Câu hỏi thường gặp

1. Yêu cầu phần cứng và môi trường để triển khai mã nguồn này là gì?

Hệ thống yêu cầu máy tính chạy hệ điều hành Linux (Ubuntu 20.04/22.04), Windows 10/11 hoặc macOS; cài đặt Python $\ge 3.8$, RAM tối thiểu 2GB và ổ cứng trống 1GB. Các gói thư viện cần cài đặt: pip install opencv-python numpy matplotlib.

2. Tại sao OpenCV lại sử dụng thứ tự kênh màu BGR thay vì RGB truyền thống?

Khi OpenCV được phát triển ban đầu bởi Intel vào năm 1999, định dạng màu BGR là chuẩn phổ biến của các nhà sản xuất phần cứng camera và bộ điều hợp đồ họa thời bấy giờ. Khi kết hợp OpenCV với Matplotlib (dùng RGB), cần chuyển đổi không gian màu bằng lệnh cv2.cvtColor(img, cv2.COLOR_BGR2RGB).

3. Bộ lọc Median có ưu thế gì vượt trội so với Mean Filter trong khử nhiễu?

Bộ lọc Mean tính trung bình cộng nên giá trị của điểm nhiễu cực đại (ví dụ pixel trắng = 255 hoặc đen = 0) sẽ kéo lệch giá trị trung bình của cả vùng, làm mờ ảnh. Ngược lại, bộ lọc Median sắp xếp các phần tử và chọn giá trị trung vị, giúp loại bỏ hoàn toàn các điểm nhiễu đột biến (nhiễu muối tiêu) mà không làm suy giảm độ tương phản của biên cạnh.

4. Chi phí bản quyền và tính tương thích khi triển khai giải pháp này vào sản phẩm thương mại?

Ngôn ngữ Python và thư viện OpenCV (giấy phép Apache 2.0), NumPy (BSD License) đều là phần mềm mã nguồn mở hoàn toàn miễn phí. Doanh nghiệp có thể tự do tích hợp vào các sản phẩm thương mại đóng gói hoặc dịch vụ SaaS mà không phải trả phí bản quyền.

5. Làm thế nào để xử lý hiện tượng mất dữ liệu pixel tại đường viền ảnh khi thực hiện tích chập?

Khi ma trận lọc trượt qua các pixel ở viền ảnh, vùng lân cận sẽ bị thiếu. OpenCV cung cấp các cơ chế borderMode để xử lý: BORDER_CONSTANT (thêm giá trị 0/đen vào biên), BORDER_REPLICATE (nhân bản pixel mép ngoài cùng) hoặc BORDER_REFLECT (phản xạ đối xứng qua biên).


Kết luận

Đồ án "Python và Vấn đề Xử lý ảnh" đã chứng minh tính hiệu quả vượt trội của việc kết hợp nền tảng toán học giải tích ma trận với hệ sinh thái mã nguồn mở Python và OpenCV. Bằng cách làm chủ từ các toán tử điểm ảnh cơ bản (Logarit, Gamma, Histogram, Bit-plane) đến các phép biến đổi tích chập không gian phức tạp (Gaussian, Roberts Cross), dự án đã xây dựng một nền tảng tiền xử lý hình ảnh vững chắc, tốc độ cao và sẵn sàng ứng dụng vào các hệ thống thị giác máy tính thực tế. Các nhà phát triển và nghiên cứu có thể trực tiếp kế thừa kiến trúc này để phát triển các ứng dụng nhận dạng thông minh, góp phần thúc đẩy quá trình số hóa và tự động hóa trong kỷ nguyên số.