Tìm hiểu cách sinh ảnh mosaic với OpenCV
#OpenCV
3
C++
27
White

Cùi Bắp viết ngày 17/03/2016

Nhân tiện vừa đọc bài viết liên quan tới OpenCV trên Kipalog, nên em xin giới thiệu về giải thuật sinh ảnh mosaic từ một ảnh gốc. Không hiểu sinh ảnh mosiac nhằm mục đích gì, chắc chỉ để sinh chơi. :joy:.

  • Mosaic có nguồn gốc từ thời Hy Lạp cổ đại với ý nghĩa nguyên thủy là “loại nghệ thuật xứng đáng với trí tưởng tượng bay bổng và lòng kiên trì vô biên”, thuộc loại nghệ thuật có tuổi đời lâu nhất của loài người. :heart:

Note: Hiệu ứng này có thể được thực hiện bằng Photoshop một cách dễ dàng hơn là ngồi code. Ảnh sinh trong bài viết này gọi là ảnh chấm chấm theo phong cách mosaic thì chuẩn hơn (facepalm)

1. Ý tưởng

Chúng ta sẽ tạo ra một layer gồm các hình tròn trắng trên background màu đen, sau đó thực hiện phép multiplying với layer mosaic tính toán được.

Các bước thực hiện

  1. Load ảnh gốc đầu vào.
  2. Áp dụng hiệu ứng pixelate (lấy màu trung bình) của NxN block lân cận cho toàn ảnh.
  3. Tạo ảnh mặt nạ là các hình tròn trắng (bit 1) và background đen (bit 0).
  4. Thực hiện phép toán Multiply ảnh màu trung bình với ảnh mặt nạ.

Các bước tạo ảnh có thể hình dung đơn giản như sau:

alt text

Chi tiết hơn ta thử áp dụng vào ảnh 150x150px. Trong trường hợp NxN block, N = 75;

alt text

2. Thực hành

Chúng ta sử dụng C++ và thư viện OpenCV để thực hiện ý tưởng trên. Code trong bài viết này cũng đc code từ vài năm trước, hoặc tham khảo từ một nguồn nào đó em cũng không nhớ lắm :joy: (Vì cũng khá lâu không động vào OpenCV rồi ạ).

Mat function colorDot(Mat image) {

    Mat dst = Mat::zeros(image.size(), CV_8UC3);
    Mat cir = Mat::zeros(image.size(), CV_8UC1);

    // Áp dụng phương thức pixelate cho NxN block lân cận có size = 10x10
    int N = 10;

    for (int i = 0; i < image.rows; i += N)
    {
        for (int j = 0; j < image.cols; j += N)
        {
            Rect rect = Rect(j, i, N, N) &
                    Rect(0, 0, image.cols, image.rows);

            // Create block có màu trung bình
            Mat sub_dst(dst, rect);
            sub_dst.setTo(mean(image(rect)));

            // Tạo các hình tròn màu trắng (bit 1) trên layer đen (bit 0), bán kính N/2
            circle(
                cir,
                Point(j + N/2, i + N/2),
                N/2-1,
                CV_RGB(255,255,255),
                -1,
                CV_AA
            );
        }
    }

    // Convert ảnh circles sang floating-point 
    Mat cir_32f;
    cir.convertTo(cir_32f, CV_32F);
    normalize(cir_32f, cir_32f, 0, 1, NORM_MINMAX);

    // Convert ảnh pixelate sang floating-point 
    Mat dst_32f;
    dst.convertTo(dst_32f, CV_32F);

    // Tiến hành phép toán Multiply trên từng channel màu
    vector<Mat> channels;
    split(dst_32f, channels);
    for (int i = 0; i < channels.size(); ++i) {
        channels[i] = channels[i].mul(cir_32f);
    }

    // Merge 3 channels màu lại thành ảnh mosaic
    merge(channels, dst_32f);
    dst_32f.convertTo(dst, CV_8U);

    return dst;
}

3. Kết quả

Bên dưới đây là các ảnh đầu vào và đầu ra tương ứng :smile:

alt text
alt text

Xử lý realtime với video thu được webcam:
alt text

4. Đôi điều về xử lý ảnh

Nói chung là khá nhiều toán, nhất là về ma trận, xác suất :dizzy_face:
Chuyển sang code web app trên php/python có vẻ dễ chịu hơn nhiều và không bị đau đầu.

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Cùi Bắp

16 bài viết.
78 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
66 3
Bài viết này được dịch từ (Link) https://code.facebook.com/ mà theo mình khá hữu ích đối với web developer. Trong hai năm qua, Facebook đã làm việ...
Cùi Bắp viết 1 năm trước
66 3
White
44 9
Bài viết này xin đề cập tới Nginx Load balancing 1. Thế nào Load Balancing Load Balancing hay còn gọi là Cân bằng tải ?? một kỹ thuật thường đượ...
Cùi Bắp viết hơn 1 năm trước
44 9
White
16 2
Bài viết này được dịch từ (Link) https://blog.twitter.com/engineering mà mình mới đọc, để mô tả một công việc tưởng chừng như đơn giản mà lại không...
Cùi Bắp viết 11 tháng trước
16 2
Bài viết liên quan
White
71 34
Bài viết thuộc chủ đề nghiên cứu trong nhóm hardcore của Cộng đồng Ruby Việt Nam Đọc manga trên mobile là một nhu cầu rất lớn, nhưng hiện nay chư...
Huy Trần viết hơn 1 năm trước
71 34
Male avatar
5 2
Sử dụng OpenCV function với C.Net Nếu bạn đã từng làm một số project có liên quan đến xử lý ảnh thì chắc hẳn sẽ biết thư viện OpenCV. Hiện tại đã ...
vankhangfet viết hơn 2 năm trước
5 2
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
16 bài viết.
78 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!