Photo to colored dot patterns with OpenCV

来源:互联网 发布:oracle的端口号 编辑:程序博客网 时间:2024/06/07 23:30

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.


原创粉丝点击