使用 OpenCV 实现国庆渐变版的头像

国庆期间发现很多小伙伴的头像都换了,添加了国旗的效果,变得更加喜庆。

该效果看上去不难,用 OpenCV 几十行就可以实现了。

最简单的图像融合版本

先来一个最简单的图像融合版本,找一张头像以及一张标准国旗的图片,将找到的头像做裁剪,大小跟国旗的大小保持一致。

icon.jpg

然后,两张图片进行叠加

    cv::Mat image = cv::imread("/Users/tony/Downloads/icon.jpg");
    cv::Mat flag = cv::imread("/Users/tony/Downloads/flag.png");
    cv::Mat roi,dst;
    cv::imshow("image",image);
    cv::imshow("flag",flag);

    roi = image(cv::Rect(300,400, flag.cols, flag.rows));

    cv::addWeighted(roi, 0.8, flag, 0.35, 0, dst);
    cv::imshow("dst",dst);
复制代码

roi.png

渐变版本

刚才的效果一般,那我们再尝试一下渐变的版本。离红旗越近,红旗的权重越大。这样就可以实现渐变的效果。

    cv::Mat image = cv::imread("/Users/tony/Downloads/icon.jpg");
    cv::Mat flag = cv::imread("/Users/tony/Downloads/flag.png");

    int flag_width = flag.cols;
    int flag_height = flag.rows;

    Mat roi = image(cv::Rect(450,1200, flag_width, flag_height));

    int radius = 0;
    if (flag_width > flag_height) {
        radius = flag_width;
    } else {
        radius = flag_height;
    }

    for (int i=0; i<roi.rows; i++) {
        for (int j=0;j<roi.cols;j++) {

            int distance = std::sqrt(i*i+j*j);

            double alpha;
            if (distance > radius) {
                alpha =  1;
            }  else {
                alpha = (double) distance / radius;
            }

            Vec3b v1 = roi.at<Vec3b>(i,j);
            roi.at<Vec3b>(i,j)[0]=alpha*v1[0] + (1-alpha)*flag.at<Vec3b>(i,j)[0];
            roi.at<Vec3b>(i,j)[1]=alpha*v1[1] + (1-alpha)*flag.at<Vec3b>(i,j)[1];
            roi.at<Vec3b>(i,j)[2]=alpha*v1[2] + (1-alpha)*flag.at<Vec3b>(i,j)[2];
        }
    }

    cv::imshow("dst",roi);
复制代码

result.png

这次的效果,比第一次好多了:)。 btw,祝大家国庆节快乐!

猜你喜欢

转载自juejin.im/post/7014356958387896327