Photo to colored dot patterns with OpenCV

I was trying to write the code to achieve the same photo effect with this Photoshop tricks. With only a few lines of code, I’m pretty amazed with the result. Given a photo, the code will turn the photo into a colored dot patterns as shown in Figure 1d.

In Photoshop, this is done by first applying the mosaic filter and create a new layer containing the white circles on black background. By multiplying the mosaic filtered layer and the new layer, we obtain the result image. In OpenCV, I write the code to mimic the steps.

The algorithm:

  1. Load the source image.
  2. Apply pixelate effect by averaging NxN block neighborhood.
  3. Create circles mask.
  4. Multiply the pixelated image with the mask to obtain the final result.
dot-patterns-src-img.jpg   dot-patterns-pixelate.jpg   dot-patterns-circles-mask.jpg   dot-patterns-dst-img.jpg

Figure 1. The steps for creating colored dot patterns.
(a) The source image. (b) The pixelated image. (c) The mask. (d) The final result.

Here is the full code.

// im2dots.cpp
// OpenCV code to achieve similar photo effect as shown in 
// http://photoshopessentials.com/photo-effects/color-dots/

#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>

int main()
{
    cv::Mat src = cv::imread("image.jpg");
    if (!src.data)
        return -1;

    cv::Mat dst = cv::Mat::zeros(src.size(), CV_8UC3);
    cv::Mat cir = cv::Mat::zeros(src.size(), CV_8UC1);
    int bsize = 10;

    for (int i = 0; i < src.rows; i += bsize)
    {
        for (int j = 0; j < src.cols; j += bsize)
        {
            cv::Rect rect = cv::Rect(j, i, bsize, bsize) & 
                            cv::Rect(0, 0, src.cols, src.rows);

            cv::Mat sub_dst(dst, rect);
            sub_dst.setTo(cv::mean(src(rect)));

            cv::circle(
                cir, 
                cv::Point(j+bsize/2, i+bsize/2), 
                bsize/2-1, 
                CV_RGB(255,255,255), -1, CV_AA
            );
        }
    }

    cv::Mat cir_32f;
    cir.convertTo(cir_32f, CV_32F);
    cv::normalize(cir_32f, cir_32f, 0, 1, cv::NORM_MINMAX);

    cv::Mat dst_32f;
    dst.convertTo(dst_32f, CV_32F);

    std::vector<cv::Mat> channels;
    cv::split(dst_32f, channels);
    for (int i = 0; i < channels.size(); ++i)
        channels[i] = channels[i].mul(cir_32f);

    cv::merge(channels, dst_32f);
    dst_32f.convertTo(dst, CV_8U);

    cv::imshow("dst", dst);
    cv::waitKey();
    return 0;
}

One thing to note is, when mutiplying the circles mask with the pixelated image both images need to be converted to the floating-point numbers e.g: CV_32F or CV_64F.

Below are some results using the code above.

dot-patterns-result-1.jpg

Figure 2. The photo of my wife.

dot-patterns-result-2.jpg

Figure 3. Mariko shinoda of AKB48.

dot-patterns-result-3.jpg

Figure 4. Band of Horses, courtesy of NRKP3 on Flickr.

dot-patterns-result-4.jpg

Figure 5. Band of Horses, courtesy of derekskey on Flickr.

Perhaps the code still needs some improvements. But in general I’m quite happy with the results. Tell me what you think in the comments below.


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值