Ảnh số
Thường gọi tắt là ảnh, kèm theo kích thước của nó. Ví dụ: 1 ảnh có kích thước 640px * 480 px
. Ảnh là 1 ma trận 2 chiều có kích thước với:
- Số cột là chiều rộng (640).
- Số dòng là chiều cao (480).
- Mỗi phần tử trong ma trận là 1 pixel - điểm ảnh.
Đơn vị cơ bản nhất của ảnh là điểm ảnh (pixel), tùy vào giá trị của điểm ảnh mà ảnh có kết quả hiển thị khác nhau. Mỗi điểm ảnh có giá trị được lưu trữ bằng số lượng byte (depth) và số kênh màu khác nhau.
Các loại ảnh
Ảnh nhị phân
Mỗi điểm ảnh có thể nhận 1 trong 2 giá trị là 0 hoặc 1. Thông thường, khi thực hiện thao tác với ảnh nhị phân, sử dụng ảnh xám để lưu trữ. Bằng cách này, có cái nhìn trực quan hơn khi thao tác. Giá trị độ xám bằng 0 (biểu diễn cho giá trị nhị phân 0) - màu đen, và giá trị độ xám bằng 255 (biểu diễn cho giá trị nhị phân 1) - màu trắng.
Ảnh xám
Mỗi điểm ảnh trong ảnh xám có 1 kênh màu duy nhất, thông thường giá trị của kênh màu này được lưu trữ bởi 8 bits, vì thế, có thể gọi ảnh xám này có 256 mức xám, mỗi điểm ảnh có thể nhận các giá trị màu từ 0 → 255.
Ảnh màu
Mỗi điểm ảnh là sự kết hợp của 3 hay 4 kênh màu và tùy vào hệ màu. Hệ màu được sử dụng phổ biến là RGB. Mỗi kênh màu được lưu trữ bởi n bits. Vậy, với ảnh màu có 3 kênh màu gồm: R - Red, G - Green, B - Blue; thì số lượng bits để biễu diễn mỗi điểm ảnh là 3n bits và số lượng màu mà điểm ảnh này có thể hiển thị là 2^(3n).
Độ sâu màu - Depth
Độ sâu màu quyết định độ sống động của hình ảnh. Bởi do, khi 1 điểm ảnh có thể biểu diễn được nhiều giá trị, tương ứng với số lượng màu mà mỗi điểm ảnh trong ảnh có thể diễn tả. Ở mục này, có 2 khái niệm con là: bits per chanel (bpc) và bits per pixel (bpp). Sử dụng ảnh màu RGB (24bpp) để làm ví dụ.
Bits per chanel
Số lượng bit dùng để biễu diễn giá trị cho 1 kênh màu. Theo như ví dụ: kênh R - 8 bits, kênh G - 8 bits, kênh B - 8 bits.
Bits per pixel
Số lượng bit trong 1 pixel. 8x3 = 24bpp.
Số kênh màu - Chanel
Trong không gian màu RGB, mỗi điểm ảnh trong ảnh màu là sự pha trộn của 3 kênh màu (R - G - B). Đối với ảnh xám, mỗi điểm ảnh chỉ có 1 kênh màu.
Trong lập trình xử lý ảnh, OpenCV đã định nghĩa 1 số MACRO để biểu điễn cho kênh màu và độ sâu màu.
Cấu trúc lưu trữ ảnh của OpenCV
OpenCV sử dụng 2 cấu trúc cho việc lưu trữ hình ảnh: Mat
và IplImage
.
Cấu trúc Mat
bpc / chanels | C1 (single channel) | C2 (2 chanels) | C3 (3 chanels) | C4 (4 chanels) | C(n) (1 - 512 chanels) |
CV_8U (Unsigned 8bits uchar 0~255) | CV_8UC1 | CV_8UC2 | CV_8UC3 | CV_8UC4 | CV_8UC(n) |
CV_8S (Signed 8bits char -128~127) | CV_8SC1 | CV_8SC2 | CV_8SC3 | CV_8SC4 | CV_8SC(n) |
CV_16U (Unsigned 16bits ushort 0~65535) | CV_16UC1 | CV_16UC2 | CV_16UC3 | CV_16UC4 | CV_16UC(n) |
CV_16S (Signed 16bits short -32768~32767) | CV_16SC1 | CV_16SC2 | CV_16SC3 | CV_16SC4 | CV_16SC(n) |
CV_32S (Signed 32bits int -2147483648~2147483647) | CV_32SC1 | CV_32SC2 | CV_32SC3 | CV_32SC4 | CV_32SC(n) |
CV_32F (Float 32bits float -1.18*10-38~3.40*10-38) | CV_32FC1 | CV_32FC2 | CV_32FC3 | CV_32FC4 | CV_32FC(n) |
CV_64F (Double 64bits double) | CV_64FC1 | CV_64FC2 | CV_64FC3 | CV_64FC4 | CV_64FC(n) |
Cấu trúc IplImage
IPL_DEPTH_1U: Unsigned 1bit bool
IPL_DEPTH_8U
IPL_DEPTH_8S
IPL_DEPTH_16U
IPL_DEPTH_16S
IPL_DEPTH_32S
IPL_DEPTH_32F
OpenCV lưu ma trận ảnh
Đối với ảnh xám
Mỗi phần tử là 1 điểm ảnh, với 1 kênh màu:
Column 0 | Column 1 | Column ... | Column m | |
Row 0 | 0, 0 | 0, 1 | ..., ... | 0, m |
Row 1 | 1, 0 | 1, 1 | ..., ... | 1, m |
Row ... | ..., 0 | ..., 1 | ..., ... | ..., m |
Row n | n, 0 | n, 1 | n, ... | n, m |
Cách truy cập IplImage
IplImage *img = cvLoadImage([Đường dẫn đến file ảnh]); int step = img->widthStep / sizeof(uchar); uchar *data = (uchar*)img->imageData; uchar value_gray = data[i * step + j];
Cách truy cập Mat
Mat img = imread([Đường dẫn đến file ảnh]); uchar value_gray = img.at<uchar>(i, j);
Đối với ảnh màu
Mỗi phần tử là 1 điểm ảnh, với 3 kênh màu được sắp theo thứ tự B-G-R.
Column 0 | Column 1 | Column ... | Column m | |||||||||
Row 0 | 0, 0 | 0, 0 | 0, 0 | 0, 1 | 0, 1 | 0, 1 | ..., ... | ..., ... | ..., ... | 0, m | 0, m | 0, m |
Row 1 | 1, 0 | 1, 0 | 1, 0 | 1, 1 | 1, 1 | 1, 1 | ..., ... | ..., ... | ..., ... | 1, m | 1, m | 1, m |
Row ... | ..., 0 | ..., 0 | ..., 0 | ..., 1 | ..., 1 | ..., 1 | ..., ... | ..., ... | ..., ... | ..., m | ..., m | ..., m |
Row n | n, 0 | n, 0 | n, 0 | n, 1 | n, 1 | n, 1 | n, ... | n, ... | n, ... | n, m | n, m | n, m |
Cách truy cập IplImage
IplImage * img = cvLoadImage([Đường dẫn đến file ảnh]); int step = img->widthStep/sizeof(uchar); int chanels = img->nChanels; uchar * data = (uchar *)img->imageData; uchar value_k = data[i * step + j * chanels + k];
Cách truy cập Mat
Mat img = imread([Đường dẫn đến file ảnh]); uchar value_k = img.at<cv::Vec3b>(i, j)[k];
Kí hiệu
i
: chỉ số dòng.j
: chỉ số cột.k
: 0: B, 1: G, 2: R