Chuyển màu ảnh trong xử lý ảnh

Series bài viết

  • Tut 1: Cài đặt OpenCV
  • Tut 2: Chuyển đổi ảnh màu
  • Tut 3: Phương pháp lọc ảnh
  • Tut 4: Xác định viền trong ảnh

Mục tiêu bài viết

Bài viết sẽ giúp các bạn có thể thực hiện một số phép xử lý ảnh phổ biến với OpenCV trên C++ bắt đầu bằng việc biến đổi ảnh màu về thành ảnh xám [grayscale image] và ảnh đen trắng [black and white].

Mỗi một mục được trình bày nhằm giải đáp bốn câu hỏi chính

  • What: Cái gì? Kỹ thuật này cho ra kết quả như thế nào.
  • Why: Tại sao? Kỹ thuật này được ứng dụng trong trường hợp nào.
  • How: Như thế nào? Cách giải quyết trên mặt lý thuyết.
  • Implement: Cách cài đặt.

1. Biến đổi ảnh xám [Grayscale convert]

What ?
Đưa vào một ảnh màu, bạn sẽ thu được một ảnh xám.

Why ?
Trong xử lý ảnh, việc chuyển đổi ảnh màu sang ảnh xám là công việc vô cùng phổ biến.
Ảnh màu thực chất chỉ là tập hợp của những ma trận số có cùng kích thước [xem lại phần 1]. Khi muốn xử lý thông tin trên ảnh, sẽ dễ dàng hơn nếu ta chỉ xử lý dữ liệu trên một ma trận số thay vì nhiều ma trận số. Việc biến đổi ảnh màu về ảnh số [Grayscale converting] xuất hiện vì mục đích trên - biến đổi thông tin ảnh về một ma trận số hai chiều duy nhất.

How ?
Giả sử, hình ảnh của bạn được lưu trữ dưới dạng RGB [Red-Green-Blue]. Điều này có nghĩa bạn có ba ma trận xám tương ứng cho màu Red, Green, Blue. Công việc của bạn là tìm cách tổng hợp ba ma trận này về thành một ma trận duy nhất. Một trong số các công thức phổ biến để thực hiện việc đó là
Y = 0.2126R + 0.7152G + 0.0722B
Trong đó:

  • Y: ma trận xám cần tìm
  • R: ma trận xám đỏ của ảnh
  • G: ma trận xám lục của ảnh
  • B: ma trận xám lam của ảnh

Nếu bạn chưa quen về việc thực hiện phép toán trên ma trận, hãy hình dung Y, R, G, B là giá trị mức xám trên các ô có tọa độ giống nhau.

Implement
- Cách 1: Đọc trực tiếp ảnh dưới dạng ảnh xám

#include

using namespace cv;

int main[]{
	Mat img = imread["img_sample.png", CV_LOAD_IMAGE_GRAYSCALE];
	imshow["Sample", img];	
	waitKey[0];
	return 0;
}

Trong đoạn code trên, việc chuyển đổi ảnh sang dạng xám ngay từ lúc đọc ảnh vào bằng cách truyền thêm tham số CV_LOAD_IMAGE_GRAYSCALE trong hàm imread. Tham số CV_LOAD_IMAGE_GRAYSCALE thực chất là số 0 nên bạn có thực hiện lệnh imread["img_sample.png", 0] với chức năng tương tự.
Nếu muốn giữ nguyên việc đọc ảnh đầu vào là ảnh màu, bạn có thể sử dụng một trong các lệnh sau
imread["img_sample.png"]
imread["img_sample.png",1]
imread["img_sample.png",CV_LOAD_IMAGE_COLOR]
với chức năng tương tự

- Cách 2: Sử dụng lệnh cvtColor

#include

using namespace cv;

int main[]{
	Mat img = imread["img_sample.png", CV_LOAD_IMAGE_COLOR];
	Mat grayscale_img;
	cvtColor[img, grayscale_img, CV_BGR2GRAY];
	imshow["Sample", grayscale_img];
	waitKey[0];
	return 0;
}

Lệnh cvtColor[source, dest, mode] cho phép bạn chuyển đổi ảnh màu source sang ảnh xám và lưu vào dest với độ chuyển đổi màu là mode. CV_BGR2GRAY là chế độ cho phép chuyển từ ảnh màu lưu ở format BGR sang ảnh xám.

2. Biến đổi ảnh đen trắng [Black-and-white convert]

What ?
Từ ảnh xám, bạn có thể biến đổi về thành ảnh chỉ có hai màu đen-trắng [black-and-white]

Why ?
Ảnh đen trắng thường được ứng dụng trong bài toán phân vùng ảnh [Image segmentation]. Giả sử trong hình ví dụ trên, bằng cách biến đổi ảnh về nhị phân, bạn có thể loại bỏ các thông khung cảnh xung quanh và chỉ giữ lại hai con cá heo trên hình.

How ?
Ảnh đen trắng, như tên gọi, chỉ có hai màu đen với giá trị là 0 và trắng với giá trị 255. Bài toán đặt ra là làm thế nào để biến đổi ảnh xám [hay nói cách khác là một ma trận 2 chiều với giá trị mỗi ô trong khoảng 0-255] về thành một ma trận 2 chiều với giá trị mỗi ô là 0 hoặc 255.
Cách giải quyết là chọn một ngưỡng [threshold] để xác định đâu là điểm ảnh đen và đâu là điểm ảnh trắng. Nếu giá trị trên ảnh xám lớn hơn ngưỡng threshold, đấy là điểm ảnh trắng và ngược lại.
Gọi ảnh xám là Gray, ảnh đen trắng cần xác định là BW, tọa độ các pixel trên hình là [x,y], ta có
- BW[x,y] = 255 nếu Gray[x,y] > threshold
- BW[x,y] = 0 nếu Gray[x,y]

Chủ Đề