Nếu bạn đã từng sử dụng OpenCV để đọc ảnh bằng hàm cv::imread(), chắc hẳn bạn sẽ nhận thấy OpenCV có thể đọc rất tốt các định dạng phổ biến như JPG, PNG, BMP hay TIFF. Tuy nhiên, khi thử mở một file ảnh RAW được chụp từ máy ảnh DSLR hoặc Mirrorless, kết quả thường là thất bại.
Vì OpenCV không đọc được ảnh RAW nên khi muốn xử lý các bạn cần convert sang định dạng khác như JPG. Việc đó làm tốn thời gian và thêm dung lượng ổ cứng để chứa, vì vậy trong các bài toán như tìm kiếm khuôn mặt trong ảnh RAW thì việc đọc trực tiếp tiết kiệm thời gian và công sức cho bạn.
Vậy ảnh RAW là gì? Vì sao OpenCV không hỗ trợ sẵn? Và làm thế nào để đọc ảnh RAW trong project C++? Bài viết này sẽ giúp bạn hiểu rõ vấn đề và hướng dẫn tích hợp thư viện LibRaw vào OpenCV.
Mục lục
Ảnh RAW là gì?
RAW là định dạng lưu trữ dữ liệu trực tiếp từ cảm biến (Image Sensor) của máy ảnh, gần như chưa qua bất kỳ quá trình xử lý nào. Khác với ảnh JPG đã được nén sẵn (compression), ảnh RAW chỉ chứa dữ liệu gốc mà cảm biến ghi nhận được.
Một số định dạng RAW phổ biến:
- Canon: .CR2, .CR3
- Nikon: .NEF
- Sony: .ARW
- Fujifilm: .RAF
- Panasonic: .RW2
- Olympus: .ORF
- Pentax: .PEF
- Adobe: .DNG
So với JPG, ảnh RAW mang lại nhiều lợi ích như giữ lại gần như toàn bộ dữ liệu từ cảm biến, giúp xử lý hậu kỳ tốt hơn. Chính vì chứa nhiều thông tin hơn nên kích thước file RAW thường lớn gấp nhiều lần ảnh JPG. Ảnh có thể từ 30MB trở lên với độ phân giải 12MPx, gấp 10 lần ảnh JPG.
LibRaw là gì?
LibRaw là thư viện C/C++ mã nguồn mở chuyên dùng để đọc và giải mã ảnh RAW từ hàng nghìn mẫu máy ảnh khác nhau. LibRaw được xây dựng dựa trên dự án nổi tiếng dcraw, đồng thời bổ sung nhiều API hiện đại giúp lập trình viên tích hợp dễ dàng vào ứng dụng.
Một số khả năng của LibRaw:
- Đọc hầu hết định dạng RAW hiện nay: Canon, Nikon, Sony, Fujifilm…
- Xuất ảnh RGB 8-bit hoặc 16-bit.
- Truy cập metadata (ISO, khẩu độ, tốc độ màn trập, tiêu cự…).
- Hỗ trợ xử lý White Balance.
- Hỗ trợ ảnh màu và ảnh đơn sắc.
Hướng dẫn tích hợp libRAW
Quy trình tích hợp libRAW gồm các bước như tích hợp project C++ thông thường: include header libraw.h và link file libraw.lib là xong.
Bước 1: download libRAW
Download/clone source code libRAW tại link: https://github.com/LibRaw/LibRaw
Bước 2: build solution
Sau đó mở solution LibRaw.sln, nếu bạn sử dụng Visual Studio 2022 trở lên thì cần retaget lên C++ mới hơn:

Trong solution có 12 projects như hình dưới:

Build cả 2 mode Debug và Release, bạn sẽ có được các file trong folder:
- buildfiles\debug-x86_64\libraw.dll
- buildfiles\debug-x86_64\libraw.lib
- buildfiles\release-x86_64\libraw.dll
- buildfiles\release-x86_64\libraw.lib
Các bạn sẽ thấy rằng các file đều trùng tên, theo quy ước thông thường các file build mode Debug sẽ có thêm chữ d phía sau tên để dễ phân biệt. Sửa properties của lib raw như sau:

Bước 3: tích hợp vào OpenCV C++
Các bạn copy các file libraw/libraw để include, đồng thời link tới các file lib ở trên. Project có cấu trúc như sau:
- libraw: thư viện đọc ảnh raw
- LibRawCpp: gọi thư viện
- LibRawWrapper: project C++/CLI để cung cấp hàm cho project C#
- UI_libRaw: giao diện viết bằng C#
Bước 4: gọi hàm đọc libRAW
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
cv::Mat imreadRaw(std::filesystem::path path) { LibRaw raw; int ret = raw.open_file(path.c_str()); if (ret != LIBRAW_SUCCESS) throw std::runtime_error(libraw_strerror(ret)); ret = raw.unpack(); if (ret != LIBRAW_SUCCESS) throw std::runtime_error(libraw_strerror(ret)); raw.imgdata.params.use_camera_wb = 1; raw.imgdata.params.no_auto_bright = 1; raw.imgdata.params.output_bps = 8; ret = raw.dcraw_process(); if (ret != LIBRAW_SUCCESS) throw std::runtime_error(libraw_strerror(ret)); libraw_processed_image_t* img = raw.dcraw_make_mem_image(&ret); if (!img || ret != LIBRAW_SUCCESS) throw std::runtime_error(libraw_strerror(ret)); if (img->colors != 3 || img->bits != 8) { LibRaw::dcraw_clear_mem(img); raw.recycle(); throw std::runtime_error("Unsupported output format"); } cv::Mat rgb(img->height, img->width, CV_8UC3, img->data); cv::Mat bgr; cv::cvtColor(rgb, bgr, cv::COLOR_RGB2BGR); bgr = bgr.clone(); LibRaw::dcraw_clear_mem(img); raw.recycle(); return bgr; } |
Ghi chú
Không sử dụng Winsock
Thêm cờ sau vào preprocessor
LIBRAW_NO_WINSOCK2
Source code
Repo bên dưới chứa các example về C++, trong đó có solution LibRawExample.sln là source code của bài này
https://github.com/thigiacmaytinh/TGMTcpp