Có thể nhiều bạn đã biết ảnh PNG có thể “trong suốt – transparent”. Ảnh transparent khi nằm chồng lên ảnh khác thì phần transparent đó sẽ hiện ra ảnh bên dưới. Ví dụ như logo VisCom solution dạng PNG khi nằm ở trên ảnh camera sẽ không che lấp các pixel bên dưới:
Bài viết này hướng bạn dẫn tạo ảnh PNG bằng cách xóa phông trắng của 1 ảnh có sẵn background màu trắng.
Nguyên lý
Ảnh thông thường sẽ có 3 kênh màu BGR, để ảnh có thể trong suốt người ta thêm 1 kênh alpha nữa. Ảnh có 4 kênh màu thường gọi là BGRA, với A chỉ thị độ transparent của pixel. Giá trị transparent trong khoảng 0-255, để trong suốt hoàn toàn thì set giá trị là 0.
Sau khi load ảnh thì chuyển ảnh từ BGR sang BGRA rồi xử lý từng pixel. Sau khi convert thì kênh alpha có giá trị mặc định là 255.
Với ảnh ví dụ bạn có thể tìm ra pixel nào có màu trắng rồi set kênh alpha thành 0. Sau khi set ta được kết quả:
Lưu ý: trong thực tế đôi khi các pixel màu trắng sẽ không có giá trị 255 mà có thể thấp hơn 1 chút. Do đó trong source code sẽ tìm các giá trị lớn hơn 200 thì xem đó là màu trắng.
Khi hiển thị trên cửa sổ opencv thì các pixel nào có alpha bằng 0 sẽ hiện ra màu đen.
Source code
Bạn có thể tham khảo source code phía dưới hoặc vào https://github.com/thigiacmaytinh/TGMTcpp chạy ConvertJpgToPng.sln
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 |
void _tmain(int argc, _TCHAR* argv[]) { cv::Mat mat = cv::imread("dog.jpg"); cv::Mat matGRBA; cv::cvtColor(mat, matGRBA, CV_BGR2BGRA); for (int y = 0; y < matGRBA.rows; y++) { for (int x = 0; x < matGRBA.cols; x++) { cv::Vec4b val = matGRBA.at<cv::Vec4b>(y, x); if (val[0] > 200 && val[1] > 200 && val[2] > 200) { matGRBA.at<cv::Vec4b>(y, x) = cv::Vec4b(0, 0, 0, 0); } } } cv::imwrite("dog_rgba.png", matGRBA); cv::imshow("dog", matGRBA); cv::waitKey(); getchar(); } |
Tham khảo
Các bạn có thể tham khảo bài Blend màu ảnh