国庆期间发现很多小伙伴的头像都换了,添加了国旗的效果,变得更加喜庆。
该效果看上去不难,用 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,祝大家国庆节快乐!