Lý thuyết


1. Nhận diện màu trong ảnh

Không gian màu được sử dụng rộng rãi trong các ứng dụng thị giác máy tính như xử lý hình ảnh và video, phát hiện đối tượng... Chúng cho phép xử lý và phân tích thông tin màu sắc một cách hiệu quả và hiệu nghiệm.

Tóm lại, không gian màu được sử dụng để biểu diễn màu sắc dưới dạng số học có thể được xử lý bởi các thuật toán. Có nhiều không gian màu khác nhau, mỗi cái có ưu điểm và nhược điểm riêng của nó.

Không gian màu RGB (Đỏ, Xanh lá cây, Xanh dương)

Đây là không gian màu phổ biến nhất được sử dụng trong thị giác máy tính. Đó là một không gian màu 3 chiều, trong đó màu sắc được tạo ra bằng cách thêm các mức khác nhau của đỏ, xanh lá cây và xanh dương.

Không gian màu HSV (Hue - Màu sắc, Saturation - Bão hòa, Value - Giá trị)

Để phân đoạn màu sắc và nhận diện đối tượng dựa trên màu sắc, chúng ta sử dụng không gian màu HSV. Đó là một không gian màu trụ, biểu thị màu sắc dưới dạng màu sắc của chúng, độ bão hòa và giá trị.

Không gian màu LAB/Lab*

Để tách màu sắc thành ba chiều, độ sáng lightness (L*), màu xanh đỏ green-red (a*), và màu xanh vàng blue-yellow (b*), chúng ta sử dụng không gian màu LAB. Nó được thiết kế để có tính đồng nhất hơn so với các không gian màu khác, có nghĩa là sự khác biệt số học giữa các màu sắc gần giống nhau hơn với sự khác biệt được cảm nhận bởi mắt người.

Việc sử dụng các không gian màu khác nhau có những ưu điểm khác nhau tùy thuộc vào ứng dụng cụ thể. Ví dụ, không gian màu HSV thường được sử dụng cho việc phát hiện đối tượng dựa trên màu sắc vì nó tách riêng thông tin màu sắc khỏi thông tin độ sáng, giúp nó đảm bảo ổn định trong điều kiện ánh sáng thay đổi.

Không gian màu HSV là một cách biểu diễn màu sắc dưới dạng Màu chủ đạo (Hue), Bão hòa (Saturation), và Giá trị (Value).

# import thư viện
import numpy as np
import cv2

# đọc file ảnh:
img = cv2.imread("02.png")

# đặt tên cửa sổ hiển thị file ảnh 
# cv2.WINDOW_AUTOSIZE -> autosize window theo ảnh
# cv2.WINDOW_NORMAL -> fit ảnh trong window
#cv2.namedWindow("Color Detection", cv2.WINDOW_NORMAL)
#cv2.namedWindow("Mask", cv2.WINDOW_NORMAL)

# chuyển ảnh sang không gian màu HSV:
hsv_img = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# xác định giới hạn trên và giới hạn dưới cho màu sắc cần phân loại:
lower_limit = np.array([106, 60, 90])
upper_limit = np.array([124, 255, 255])

# Sau đó, sử dụng hàm cv2.inRange() để tạo một mặt nạ cho khoảng màu được chỉ định
# Hàm này nhận vào hình ảnh HSV và giới hạn dưới + giới hạn trên của khoảng màu (ở bước trước) làm đầu vào
# và trả về một hình ảnh mặt nạ nhị phân.

# tạo mặt nạ phân đoạn màu
mask = cv2.inRange(hsv_img, lower_limit, upper_limit)

# show ảnh mặt nạ
cv2.imshow("Mask", mask)

# sử dụng hàm cv2.boundingRect() để lấy hộp giới hạn của đối tượng trong hình ảnh
# ở đây là phần ảnh chứa màu sắc cần phân đoạn
# Hàm này nhận hình ảnh mặt nạ làm đầu vào và trả về tọa độ hộp giới hạn (x, y, w, h)
# trong đó (x, y) là góc trên cùng bên trái của hộp giới hạn và (w, h) là chiều rộng và chiều cao của hộp giới hạn.

# lấy thông số hộp giới hạn bao quanh vùng màu cần phân đoạn
bbox = cv2.boundingRect(mask)

# kiểm tra xem biến bbox có khác rỗng hay không (tức là có tìm được hộp giới hạn bao quanh vùng chứa màu cần phân đoạn)
# Nếu khác rỗng, tức là có tồn tại hộp giới hạn thì vẽ một hình chữ nhật trên hình ảnh 
# bằng cách sử dụng hàm cv2.rectangle() với các thông số (x,y,w,h) của hộp giới hạn tìm được.

# nếu có hộp giới hạn bao quanh vùng màu cần phân đoạn thì vẽ hình chữ nhật theo thông số hộp giới hạn đó
if bbox is not None:
    print("Object detected")
    x, y, w, h = bbox
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2)
else:
    print("Object not detected")

# show ảnh kết quả
cv2.imshow('Color Detection', img)
cv2.waitKey(0)

image.png

2. Nhận diện màu trong ảnh bằng cách dò thông số ngưỡng H, S, V trong không gian màu HSV

# import thư viện sử dụng
import cv2
import numpy as np

# tạo chương trình con để lấy giá trị H, S, V từ trackbar
def get_hsv_values(val):
    pass

# tạo 1 cửa sổ hiển thị ảnh
cv2.namedWindow('image')

# load ảnh
image = cv2.imread('02.png')

# tạo trackbar cho giá trị Hue
cv2.createTrackbar('H min', 'image', 0, 255, get_hsv_values)
cv2.createTrackbar('H max', 'image', 0, 255, get_hsv_values)

# tạo trackbar cho giá trị Saturation
cv2.createTrackbar('S min', 'image', 0, 255, get_hsv_values)
cv2.createTrackbar('S max', 'image', 0, 255, get_hsv_values)

# tạo trackbar cho giá trị Value
cv2.createTrackbar('V min', 'image', 0, 255, get_hsv_values)
cv2.createTrackbar('V max', 'image', 0, 255, get_hsv_values)

# tạo vòng lặp để mỗi khi kéo thanh trackbar thì giá trị H, S, V được update hiển thị trên ảnh kết quả
# điều kiện vòng lặp while luôn đúng
while True:
    # chuyển sang ảnh màu HSV
    hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

    # lấy giá trị min, max của H, S, V từ 3 thanh trackbar
    h_min = cv2.getTrackbarPos('H min', 'image')
    h_max = cv2.getTrackbarPos('H max', 'image')
    s_min = cv2.getTrackbarPos('S min', 'image')
    s_max = cv2.getTrackbarPos('S max', 'image')
    v_min = cv2.getTrackbarPos('V min', 'image')
    v_max = cv2.getTrackbarPos('V max', 'image')

    # gán giá trị min, max của H, S, V vào 2 biến giới hạn trên và giới hạn dưới
    lower_limit = np.array([h_min, s_min, v_min])
    upper_limit = np.array([h_max, s_max, v_max])

    # tạo 1 mặt nạ lọc màu phân loại
    mask = cv2.inRange(hsv_image, lower_limit, upper_limit)

    # áp mặt nạ lọc màu ở trên vào ảnh gốc
    result = cv2.bitwise_and(image, image, mask=mask)

    # hiển thị các ảnh kết quả
    cv2.imshow("orginal", image)
    cv2.imshow("mask", mask)
    cv2.imshow('result', result)

    # nếu phím Q được nhấn thì thoát chương trình
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

    # in giá trị giới hạn trên-dưới của H, S, V
    print('H min: {}, H max: {}, S min: {}, S max: {}, V min: {}, V max: {}'.format(
        h_min, h_max, s_min, s_max, v_min, v_max))

# đóng chương trình
cv2.destroyAllWindows()

image.png

Bài tập


  1. Viết chương trình đọc ảnh sau, nhận diện màu vàng và tách thành ảnh mới có cùng kích thước với ảnh cũ, nền cam chứa những chi tiết màu vàng. Lưu kết quả thành ảnh 02.png.

6.png

  1. Viết chương trình nhận diện màu trắng trong video 01.mp4 dưới đây bằng cách dò thông số ngưỡng H, S, V trong không gian màu HSV (tạo picker)